Your First VPS: From Purchase to Launch, Step by Step

2026-09-21 · 9 min read

First-time buyers get stuck for a week on “which provider, which specs.” Your first server has exactly one goal: get it running. Buy the smallest box, get the site loading on it, worry about the rest later. This walks through in order, and every step says what “done” looks like.

Your first cloud server in five steps: buy, init, deploy, domain, launch1Buy a serverSmallest planGet it running2InitializeUpdate the OSSecurity baseline3Deploy the sitePush the codeService is live4Add the domainDNS recordsHTTPS on5LaunchMonitoring onYou hear it first
Your first server in five steps: buy → initialize → deploy → point the domain → launch

Three decisions to make before buying

  • Region: put the server near your target users. If you want to skip the filing hassle, pick Hong Kong, Singapore, or the US; mainland China servers need an ICP filing, which both individuals and companies can get — it just takes the regulator's review time.
  • Specs: start with 1 CPU and 2GB RAM — plenty for a small personal site. Start bandwidth at the minimum and add more later.
  • OS: pick the LTS long-term-support release of Ubuntu. Don't pick Windows — Linux is the mainstream for hosting sites, with way more tutorials.

Three things to check while ordering

First is renewal pricing — many providers are cheap the first year and double on renewal; it's the long-term cost that counts. Second is how bandwidth is billed: fixed bandwidth or by traffic — traffic billing can cost more for image-heavy sites. Third is whether snapshots (backups) cost money and how. A glance at these three dodges most “second-year bill shock.”

First four things to do once you have the server

The provider gives you an IP, a username (usually root), and a password or key. SSH in, update the system first, then do these four:

  • Change to a strong password, or switch to key login and disable password login entirely
  • Open ports 22 (SSH), 80 (HTTP), 443 (HTTPS) in the provider's security group (firewall)
  • Install Node.js (the version your project requires — the delivery package docs say which)
  • Install PostgreSQL, or use the provider's managed database to skip backups
ssh root@YOUR_SERVER_IP
# update the system right after connecting
apt update && apt upgrade -y

Get the site uploaded and running

Any way up works: git clone is easiest, or zip it locally and upload. For an EazyOPC delivery package, follow START_HERE.md in order: install dependencies, fill in environment variables (things like DATABASE_URL — do them one section at a time, don't paste the whole block), generate the database client, create tables, build, start. Each step has a verification method in the docs — don't skip ahead.

npm install
npx prisma generate
npm run db:push
npm run build
npm start

Point the domain and set up HTTPS

At your domain registrar, point the domain's A record at the server IP and wait minutes to hours for it to take effect. Then install a reverse proxy on the server (Nginx or Caddy) to forward port 80/443 traffic to your site process. HTTPS certificates are all free now — Caddy applies automatically, and Nginx with certbot is just a few commands. This step is done when the browser address bar shows the little lock.

The first time you run this flow, you'll very likely get stuck at some step — blocked ports, database won't connect, build runs out of memory — that's the rite of passage for everyone. Write down the full original error message and go through the “Deployment Error Troubleshooting Guide” entry by entry.

Use pm2 to keep the site always running

npm start got the site running, but there's a fatal problem: close the SSH window and the site dies. Production needs a process manager, and the usual one is pm2. It does three things: runs the site in the background, restarts it when it crashes, and centralizes logs. Installing and using it is not hard:

npm install -g pm2
# start the site with a name you recognize
pm2 start npm --name "my-site" -- start
# view logs / restart / stop
pm2 logs my-site
pm2 restart my-site
pm2 stop my-site

Name it something you recognize so you don't mix sites up when several run on one server. When the site has problems, pm2 logs first — the answer is usually in there. After fixing code and redeploying, pm2 restart is enough; no need to kill the process and start it by hand. Remember: anything that “keeps running” should show up in pm2 list. Bare processes will bite you sooner or later.

Make the site come back up by itself after a server reboot

Patching and upgrades reboot servers. After a reboot, pm2-managed sites won't come back up by themselves — unless you do two things. First, run pm2 startup; it gives you a command to copy and execute, which makes pm2 itself start on boot. Second, pm2 save, which saves the current list of running sites. Every time you add or remove a site, run pm2 save again, or the next reboot will bring up the old list and the new site won't start.

How to verify: after setting it up, manually reboot the server once (the provider's console has a reboot button), wait two minutes, and open your site in a browser. It only counts if it opens. Don't wait until the middle of the night when auto-updates reboot the box and you discover the site is down — you'll be asleep and users will already be complaining.

Disk full: the culprit behind slow sites and failed writes

The site gets slow, uploads fail, the database won't write — eight times out of ten the disk is full. Run df -h to see which partition is full, then drill down with du to find what's eating space. The usual three suspects: ever-growing pm2 and nginx log files, accumulating database backup files, and npm cache plus useless packages.

df -h
# find the big directories, drill down level by level
du -sh /var/log/* 2>/dev/null | sort -rh | head
# clear pm2 logs (make sure you have read the errors first)
pm2 flush

The real fix is log rotation: Ubuntu ships logrotate; configure nginx and pm2 logs to rotate daily and keep only 14 days. Keep backup files for only the last 7 days — the cron job from the previous post already auto-deletes old ones. Five minutes with df -h once a month beats being woken up by a full disk at 3am.

Switching servers or reinstalling: the confidence of a 30-minute recovery

Someday you will switch servers: price hikes, datacenter outages, a different region. Whether you can recover in 30 minutes depends on having three things ready ahead of time: code in a git repo (not just sitting on the server), environment variables stored separately (database passwords, payment keys — fill them in after reinstalling), and daily database backups. With those three, a fresh machine is four steps — install environment, pull code, fill variables, import data — done in half an hour. Missing one, and you're in for a whole night.

Remember this troubleshooting order: site misbehaves → pm2 logs first, then df -h for disk, then free -h for memory. These three moves solve most “the site suddenly died” cases. If nothing shows up, go through the “Deployment Error Troubleshooting Guide” entry by entry.

Where the logs are: look at them first when things break

Three log locations to know: for pm2-managed sites, pm2 logs; nginx or Caddy access and error logs live under /var/log; app-written logs depend on the project config. Read logs bottom-up — the newest is at the bottom; find the first ERROR or stack trace. Don't start from line one; tens of thousands of lines will keep you reading until dawn without finding anything.

Environment variables: don't put them in code

Database passwords, payment keys — those go in a .env file or pm2 environment variables, never hardcoded in code. Two reasons: first, code goes into git, and keys in git are public; second, when you switch servers or rotate a password, you only change the env file, not the code. Keep an encrypted copy of your environment variables separately — if the server dies and you rebuild, fill them back in.

Cron jobs: automate backups and cleanup

Hand two things to cron: back up the database every night (just copy the cron command from the previous post), and clean old logs and backups weekly. Edit with crontab -e, confirm with crontab -l. If a cron job didn't run, first check whether the cron service is running, then look for its execution records in /var/log/syslog. Nobody tells you when a cron job silently dies — regular checking is the only way.

Security group: open only the ports you need

The security group (firewall) opens only 22 (SSH), 80 (HTTP), and 443 (HTTPS) — everything else stays closed. Never expose the database port (5432); the database serves localhost only. Safer SSH: switch to key login and disable password login; or move port 22 to an uncommon number. Being probed and brute-forced is the norm — thousands of login attempts in the logs daily; get used to it, just keep them out.

Swap: the lifesaver for a 1GB box

On a 1GB machine, building projects and running databases often run out of memory. Add a swap partition for emergencies: disk space as memory — slow, but it saves you. Turn swap on for the build, turn it off after. If you're living on swap long-term, you genuinely need more RAM and should upgrade — swap is a band-aid, not a cure.

Install monitoring: know the moment it dies

With the server set up, finally add uptime monitoring: UptimeRobot's free plan checks whether your site loads every 5 minutes and emails you when it's down. The details are in the “Free Tools Roundup for Indie Developers” post. Monitoring is the last piece of operations: everything before it exists so the site stays alive; monitoring is what lets you know first when it dies.

Your First VPS: From Purchase to Launch, Step by Step · EazyOPC Blog