A VPS as a dev and staging server

For developers and students who want a server to build and test on.

A staging server is a copy of your site or app where you test changes before real users see them. A dev server is a remote machine you build on. A small VPS can be both, and it behaves much more like real hosting than your laptop does.

This guide shows how to set one up safely: a password-protected staging site, deploys with Git, private access to databases and tools, and a few habits that stop test servers becoming a security problem. It assumes Ubuntu or Debian and basic comfort with the command line. Tool names are given in plain text, so follow each project's own documentation for details.

2 GB and 4 GB VPS plans in stock, common sizes for a dev server

In stock when this page loaded. See all 6 matching plans

What is in this guide

A few words you will see

TermWhat it means
ProductionThe live site or app that real users use.
StagingA copy of production used to test changes first.
DeployPutting a new version of your code onto a server.
Reverse proxyA web server, such as nginx or Caddy, that receives visits and passes them to your app.
SSH tunnelA way to reach a private port on the server through your SSH connection.
Env fileA file of settings and secrets, such as API keys, that your app reads at start-up.
CI runnerA machine that runs automated tests or builds when you push code.

Why use a VPS for this

  • It matches real hosting. A Linux server with a public IP address shows the problems your laptop hides: file permissions, firewalls, SSL and DNS.
  • It is always on. Clients, teammates or teachers can look at the staging site at any time.
  • It keeps your laptop clean. Databases and background services run on the server, not on your own machine.
  • It teaches useful skills. Deploying, logging and fixing a real server is good practice for any developer.

If you only need to show a static site, a free static hosting service may be simpler. If you are learning the basics of Linux, getting started and Linux server tools come first.

What size to pick

Rough guidance. Memory use varies with your language, framework and database.

UseStarting size
One staging site with a small database2 GB
A few apps in Docker, or a heavier framework4 GB
Builds, CI jobs, several databases, or a team6 GB to 8 GB

Builds are often the hungriest step. Compiling or installing packages can use far more memory than running the finished app. A small swap file helps, but swap is a safety net, not extra RAM. The guides for 2 GB and 4 GB plans have more ideas.

Before you start

  • A VPS running Ubuntu or Debian.
  • A domain or subdomain for the staging site, such as staging.example.com, pointed at the server's IP address.
  • Your project in a Git repository.
  • An SSH key on your computer. See setting up SSH keys.

In the examples, replace alex with your username, SERVER_IP with the server's address and app with your project name.

1. Secure the server

Do this before anything else. A test server is a common way in for attackers, because people treat it as unimportant.

  • Update the system, create a normal user, switch to SSH keys and turn off password login.
  • Turn on a firewall that allows only SSH, plus HTTP and HTTPS for the staging site.
  • Turn on automatic security updates.

Your first hour on a new RackNerd VPS walks through each step, and securing your VPS goes further.

2. Install your stack

Install what production uses, as closely as you can. Two common approaches:

  • Directly from packages. Install your language runtime, database and web server with apt. This uses less memory and suits smaller plans.
  • With Docker. Run each part in a container defined in a Compose file. This matches many production setups and makes the stack easy to rebuild. See installing Docker.

Either way, use the same major versions as production. Many staging bugs come from a different version of the language or database.

Put a reverse proxy in front of your app. nginx and Caddy are both common. It handles SSL and passes visits to your app on a local port. Web servers compares them.

3. Keep services private

Your database, admin tools and app ports should never be open to the internet. Bind them to 127.0.0.1, which means "this server only", and let the reverse proxy be the only public door.

In a Docker Compose file, publish ports on the local address only:

ports:
  - "127.0.0.1:8080:80"

Docker can open ports in a way that skips UFW rules, so publishing on 127.0.0.1 matters even if your firewall looks closed.

To reach a private service from your own computer, use an SSH tunnel. This makes the server's database port appear on your laptop:

ssh -L 5432:127.0.0.1:5432 alex@SERVER_IP

While that session is open, connect your database tool to 127.0.0.1 port 5432 on your laptop. Change the port numbers to match your database. For something you use all the time, a VPN is another option. See setting up a VPN.

4. Put the staging site behind a password

Staging sites should not be public. They often have debug output, test accounts and unfinished features, and you do not want search engines listing them.

With nginx, add a simple login. Install the tool that creates the password file and add a user:

sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd alex

Then, in the staging site's server block, add:

auth_basic "Staging";
auth_basic_user_file /etc/nginx/.htpasswd;
add_header X-Robots-Tag "noindex, nofollow" always;

Test and reload nginx:

sudo nginx -t
sudo systemctl reload nginx

The first two lines ask for a username and password. The last one asks search engines not to index the site. Add a certificate so the password is never sent unencrypted, for example with Certbot. Caddy has its own way to do the same. Follow its documentation.

5. Deploy with Git

A simple way to deploy is to push to a Git repository on the server and let a hook copy the code into place. On the server:

mkdir -p ~/repos /var/www/app
git init --bare ~/repos/app.git
nano ~/repos/app.git/hooks/post-receive

Your user needs to own /var/www/app. If it does not, fix that with sudo chown alex:alex /var/www/app. Put this in the hook file:

#!/bin/sh
git --work-tree=/var/www/app --git-dir="$HOME/repos/app.git" checkout -f main

Make it executable with chmod +x ~/repos/app.git/hooks/post-receive. Change main if your branch has another name. On your computer, add the server as a remote and push:

git remote add staging alex@SERVER_IP:repos/app.git
git push staging main

After each push, the hook updates the files. If your app needs a build step or a restart, add those commands to the end of the hook. Start simple, and only add steps you have run by hand first.

Many teams use a CI service instead, which runs tests and then deploys. A VPS can act as a self-hosted CI runner. If you do this, do not let it run code from untrusted pull requests, as that code runs on your server.

6. Handle data and secrets safely

  • Do not copy real personal data to staging. Use test data, or remove and replace names, emails and payment details first. A leak from staging is still a leak, and privacy laws may apply.
  • Use separate credentials. Staging should have its own database passwords and API keys, never the production ones.
  • Keep secrets in env files, not in Git. Store them in a file only the app's user can read, set with chmod 600, and add the file to .gitignore.
  • Use test modes. Payment providers and email services usually offer test keys. Use them so staging never charges a card or emails a real customer.
  • Turn off open sign-up. If your app has user registration, disable it or lock it to invited users on staging.
  • Back up what you cannot recreate. Your code is in Git, but test databases and uploads may not be. See using a storage VPS for backups.

4 GB VPS plans in stock, for Docker stacks and heavier frameworks

In stock when this page loaded. See every plan

7. Edit and run code remotely

You can also use the VPS as your development machine, not just a place to deploy.

  • Remote editing. Editors such as Visual Studio Code can open folders on a server over SSH, using an extension. The editor runs on your computer while files and commands run on the server. Check the extension's memory needs, as its server side runs on your VPS.
  • Terminal tools. tmux keeps your session running when you disconnect, so long jobs continue. Install it with apt.
  • Previewing a dev server. If your framework starts a dev server on a local port, reach it with an SSH tunnel, as in step 3, rather than opening the port.

If you use AI coding tools, read and test anything they write before you deploy it, and never paste secrets into them.

Troubleshooting

SymptomLikely causeFix
Build killed partway throughRan out of memoryAdd a swap file, build on your laptop and upload the result, or use a bigger plan
Push works but the site does not changeHook not executable, wrong branch name, or wrong folder ownerCheck chmod +x, the branch in the hook and the folder ownership
502 Bad Gateway from nginxThe app is not running, or is on a different portCheck the app's logs and the port in the nginx config
Database port reachable from outsidePort published on all addressesBind it to 127.0.0.1 and restart the service or container
Password prompt does not appearThe auth lines are in the wrong block, or nginx was not reloadedPut them in the staging site's server block, run sudo nginx -t and reload
Disk filling upOld Docker images, logs or build cachesRemove unused images with docker image prune and clear old logs

Limits

  • Staging is not production. A small staging server will not show how your app behaves under real traffic. Do not use it to judge performance.
  • Fair use applies. Unmetered does not mean unlimited. Heavy builds running all day can hit CPU fair-use limits. Load tests and scanning, even against your own sites, should be small and checked against the acceptable use policy.
  • Licences still apply. Some databases, tools and frameworks have licence terms for server use. Check before you install.
  • It is still your server. Updates, security and backups are your job, even for a test box. An abandoned staging server is a real risk, so delete it when the project ends.

When to step up

Step up when builds keep running out of memory, when you run several projects or databases at once, or when a team shares the server. A 6 GB or 8 GB VPS gives room for builds, CI jobs and a few full stacks side by side. For heavy builds running all day, a dedicated server may suit better.

6 GB and 8 GB VPS plans in stock, for builds and team servers

In stock when this page loaded. See all 6 matching plans

What next

To compare what is available now, start with the cheapest RackNerd VPS guide and check the sales page.

More RackNerd guides