Skip to content

Running a Production API on a $6 VPS Without Regretting It

This is the article I wish I had read before I learned running a production api on a $6 vps without regretting it the hard way — through production incidents, surprise...

7 min read Hosting #vps#servers#hosting#scaling#devops

This is the article I wish I had read before I learned running a production api on a $6 vps without regretting it the hard way — through production incidents, surprise bills, and late-night restores. Every paragraph comes from operating real applications, not from a marketing page.

Introduction

A VPS is the first place where you truly own a server, and with ownership comes a checklist: updates, users, firewalls, swap, backups, and a hundred small decisions that determine whether the box runs for years or dies dramatically at 3 a.m. This guide walks through a production-grade VPS setup from purchase to live traffic in one sitting.

The premise is simple: a virtual private server is a slice of a real machine, rented to you with root access. Everything above the hypervisor is yours to manage — and everything you forget to manage is a future incident. The goal of this article is to make the boring parts boring: predictable, scripted, and done once.

I have run the exact workflow described here on the platform behind this site — the same stack of tools, the same firewall rules, the same monitoring loop. Every step below is something I actually do, in the order I actually do it.

Hosting concept

The model in practice: the pieces fit together before the first line of application code.

Why It Matters

A well-set-up VPS removes an entire class of anxiety. Security is configured before anything is exposed, failures are visible before they become incidents, and every credential is in one place. The result is a server you forget about — which is the highest compliment a server can receive.

The economics matter too: a $5–10 VPS handles a surprising amount of production traffic when it is configured properly. Most projects outgrow their first VPS long after they outgrow their first shared plan — and the upgrade path (bigger VPS, then cloud) is smooth when the foundations are sound.

  • One-time configuration pays off for years: security, swap, and monitoring are set once
  • Root access means no hidden limits — you control CPU, memory, and disk
  • The same setup steps apply to every future server, making new deployments routine
  • A VPS is the standard training ground for cloud skills — the mental model transfers directly

The Problem

The typical first-VPS experience is a cascade: default SSH password left on, updates ignored, no firewall, swap missing, and a database that grows until the disk fills. Each omission is invisible until it is catastrophic, and none of them take more than ten minutes to fix.

The second common failure is the opposite: hardening theatre. People install eleven security tools and then can't deploy their app, or lock themselves out of SSH. Security should be a small, boring, reversible set of actions — not a ceremony.

The Approach

The setup order matters. First, SSH keys and a non-root user — you should never log in as root again. Second, updates and a firewall allowing only SSH, HTTP, and HTTPS. Third, swap and filesystem checks, so memory spikes degrade gracefully. Fourth, install only what the app needs: a runtime, a reverse proxy, a database, and a process manager.

Then monitoring: a cron-driven health check that pings an endpoint and alerts you when it dies, plus disk and memory checks. That single script has caught more issues than any dashboard I have ever paid for.

The whole hardening pass in one block. A non-root deploy user, a minimal firewall, fail2ban for brute force, swap so the kernel never OOM-kills your app, and a health check that texts you when the endpoint dies.


# The 15-minute hardened VPS

adduser deploy && usermod -aG sudo deploy

mkdir -p ~deploy/.ssh && cp ~/.ssh/authorized_keys ~deploy/.ssh/

chown -R deploy:deploy ~deploy/.ssh



apt update && apt upgrade -y

apt install -y ufw fail2ban nginx

ufw allow OpenSSH && ufw allow 'Nginx Full' && ufw enable



fallocate -l 2G /swapfile && chmod 600 /swapfile

mkswap /swapfile && swapon /swapfile



# health check every 5 minutes

*/5 * * * * curl -fsS https://yourdomain/health || curl -fsS 'https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<ID>&text=SERVER DOWN'

Hosting workflow

The workflow applied: configuration and discipline, not heroics.

VPS vs Cloud VPS

FactorVPSCloud VPS
Resource modelFixed sizeElastic, resizable
BillingFlat monthlyPer-second / per-hour
ScalingUpgrade to a bigger planAuto-scale horizontally
NetworkSimpleVPCs, load balancers, regions
Ops skill neededBasic LinuxNetworking + IaC
Best forSteady workloadsSpiky, growing workloads

A cloud VPS is not a different animal — it is a VPS with more knobs. Run the same setup steps, then add elasticity when traffic actually demands it.

Implementation

With the box hardened, deploy the app: a systemd unit for the process, nginx as reverse proxy with TLS, and the firewall already allowing traffic. Backups belong off-server — a nightly mongodump or pg_dump piped to object storage costs pennies and saves careers.

Finally, write the runbook. Where the logs live, how to restart the app, how to roll back a deploy, who has access to what. Future you will thank you during the first incident.

  • SSH keys only; root login and password auth disabled
  • Firewall default-deny with explicit SSH, HTTP, HTTPS
  • Swap configured before the first memory spike
  • App runs as a non-root user under systemd
  • TLS via certbot; renewals automatic
  • Off-server backups tested monthly
  • A health-check alert that reaches your phone

Key Decisions

Root or non-root user for the app?

Non-root, always. The app should run as an unprivileged user with access only to what it needs. If a vulnerability ever lets someone run code as the app user, root access to the box is still required to do real damage.

How much swap is enough?

Enough to survive brief spikes: 1–2GB for small VPSes. Swap is not a scaling strategy — if the box lives in swap, buy more RAM. It exists to turn OOM kills into slow responses.

Common Mistakes to Avoid

The classic mistakes: keeping password auth enabled, skipping the firewall 'until later', storing the database on the same disk as the app, and never testing backups. Each one is a ten-minute fix that prevents a disaster.

Also common: over-monitoring. Five dashboards that nobody reads are worse than one alert that reaches your phone. Build the phone alert first.

  • SSH on the default port with password auth
  • No swap on memory-constrained boxes
  • Firewall configured after the attack, not before
  • Backups stored on the same server they protect
  • No health check — discovering downtime from user complaints
Hosting results

The payoff: infrastructure that runs quietly so the product gets the attention.

Putting It Into Practice

This week: run the hardening block above on any server you own that is missing a step, then verify SSH works before you log out. Then set up the health-check alert before you need it.

For new projects, script the whole setup into a setup.sh so the next server is ten minutes instead of an evening.

Key Takeaways

  • Never log in as root; SSH keys and a deploy user from day one
  • Firewall default-deny; expose only what you serve
  • Swap, monitoring, and off-server backups are not optional
  • Deploy as a non-root user under systemd
  • Write the runbook before the incident, not during it
  • Script the setup so every future server is routine

Frequently Asked Questions

Is a VPS secure enough for production?

Yes, when configured properly: keys-only SSH, a default-deny firewall, regular updates, and a non-root app user. The steps in this article take fifteen minutes and cover the overwhelming majority of real-world attacks.

When should I move from VPS to cloud?

When you need horizontal scaling (multiple instances behind a load balancer), geographic distribution, or elastic capacity for spiky traffic. Until then, a bigger VPS is simpler and usually cheaper.

How do I recover from a failed VPS?

Provision a new one, run your setup script, restore the off-server backup, point DNS, and update the health-check target. With the checklist above, recovery is a couple of hours — which is exactly why the boring parts matter.

Conclusion

A VPS is a small, predictable machine with a big responsibility. Handle the fifteen minutes of setup — keys, firewall, swap, monitoring, backups — and it will serve you for years without drama.

The platform behind this site runs on exactly this playbook: hardened by default, monitored by cron, recovered from backups. Boring, on purpose.

Related posts