DevOps Guide

Run your own apps on a VPS without running a platform team

One rented Linux box, a control plane that gives you git-push deploys and automatic HTTPS, backups you have actually restored, and a monitor that is not on the same machine. That is the whole self-hosting stack. This guide picks the control plane, sets the guardrails, and then does the honest arithmetic on when paying a platform is the cheaper answer.

About 7 min read. Tooling and prices verified August 2026.

The arithmetic, before the tooling

A Hetzner CX22 is roughly 4 to 5 euros a month for 2 vCPU, 4 GB of RAM, 40 GB of NVMe, and 20 TB of outbound traffic. The same workload - one web service, one background worker, one Postgres, modest traffic - lands somewhere between $7 and $15 on Render or Railway, $10 to $20 on Fly.io once you count an IPv4 address and volume snapshots, and anywhere from $20 to $200 on Vercel depending entirely on how much of your traffic is bots.

So the saving is real but small in absolute terms: call it $200 to $500 a year for a typical small product. That number only justifies itself if the maintenance costs you less than about two hours a month, which is exactly what a good control plane is for. Self-hosting stops being cheap the moment somebody is debugging a certificate renewal at midnight.

Where self-hosting wins decisively is at the shapes managed platforms price badly: large egress, long-running processes, big background jobs, GPU or memory-heavy workloads, ten internal tools that each cost a seat somewhere, and data you are not allowed to hand to a third party.

Step 1: pick a control plane

All three of these install onto a server you already rent, deploy Docker containers from a git push, and terminate TLS for you. They differ in how much platform they leave running on your box.

Coolify

The default for most people

The most mature option and the one with the biggest community. Over 280 one-click service templates cover the things you would otherwise install by hand - Postgres, Redis, Plausible, n8n, Supabase - plus git integration, scheduled database backups to any S3-compatible bucket, and a real UI a non-Linux teammate can operate. Version 4.0 went stable in April 2026 after a long beta, and 4.1 added Railpack builds and audit logging. The cost is footprint: it is a full platform with its own database and background workers, so budget 1 to 2 GB of RAM for Coolify itself. coolify.io

Dokploy

Leaner, Swarm-native

Newer and deliberately thinner. Built natively on Docker Swarm, which buys first-class multi-server clustering and means your docker-compose.yml runs as written instead of being massaged into a platform-specific shape. Lower idle overhead than Coolify, scheduled S3 backups, Traefik for routing and certificates. Smaller template catalogue and a smaller community, so you will read more source and fewer forum threads. dokploy.com

Kamal

Zero UI, one or two apps

37signals built Kamal to move Basecamp and HEY off the cloud, and it shows. There is no dashboard and no server-side daemon: one YAML file, kamal deploy from your laptop or from CI, SSH in, pull the image, zero-downtime swap behind kamal-proxy. Nothing runs on the server except your app and a small proxy, so all 4 GB of that VPS belongs to you. The tradeoff is that everything a UI would have given you - databases, backups, logs, a second pair of eyes - is now your job. kamal-deploy.org

Short version

Several apps, several databases, or a teammate who needs a UI: Coolify. Docker Compose fluency and a preference for less platform: Dokploy. One or two apps and a strong dislike of dashboards: Kamal.

Step 2: harden the box once

Do this before the first deploy, not after the first incident. It is twenty minutes.

  • SSH keys only. Set PasswordAuthentication no and PermitRootLogin no, deploy as a non-root user with sudo. Password auth on port 22 is scanned continuously within minutes of a server booting.
  • Close every port but 22, 80, and 443. ufw or your provider's cloud firewall, and prefer the provider's - it filters before the traffic reaches your NIC. Databases bind to the Docker network, never to 0.0.0.0.
  • Turn on unattended security upgrades. An unpatched kernel is the most likely way you get owned, and it is one package on Debian and Ubuntu.
  • Let the proxy own TLS. Coolify and Dokploy both run Traefik, Kamal runs kamal-proxy, and all of them fetch and renew Let's Encrypt certificates automatically. If you are wiring a reverse proxy yourself, Caddy does this with no configuration at all - see Nginx vs Caddy.
  • Cap the logs. Set max-size and max-file on the Docker log driver. A full disk from unrotated JSON logs is the single most common way a hobby server takes itself down.

Step 3: backups you have restored

This is the part that separates self-hosting from gambling. A managed database gives you point-in-time recovery whether you thought about it or not; a container you started gives you nothing. Coolify and Dokploy both ship scheduled database backups with retention policies and S3-compatible targets, which covers most of it. With Kamal you write the cron job.

Three rules that matter more than the tool:

  • Off the box, always. A snapshot on the same disk protects you from a bad migration and from nothing else. Push to Backblaze B2, Cloudflare R2, or any S3 bucket at a different vendor than your VPS.
  • Back up the data, not the container. Logical dumps for Postgres and MySQL, plus the volumes holding user uploads. Application containers are rebuilt from the registry, so they do not need backing up at all.
  • Restore one on purpose, this month. Pull last night's dump into a scratch container and run the app against it. An untested backup is a hypothesis, and roughly half of them are wrong about something - a missing extension, an empty volume, a password nobody recorded.

Restic or Borg to object storage handles the file side well and both do encrypted, deduplicated, incremental snapshots. Whichever you use, write the restore command in the README next to the backup command.

Step 4: monitoring that survives the outage

The one non-negotiable rule: the thing that tells you the server is down must not be running on that server. An external uptime check hitting a real health endpoint every minute, alerting to somewhere you will actually see it, is worth more than every dashboard you will ever build.

On the box itself, keep it modest. Disk usage and free memory alerts catch the two failure modes that actually happen on a single server, and container logs with a sane retention window cover the rest. Uptime Kuma and Beszel are the popular self-hosted picks; Grafana with Prometheus is the answer once you have several machines and want history. The monitoring tools directory covers the hosted options, several of which have free tiers generous enough that self-hosting the monitor is the wrong trade.

Deploys should come from CI rather than a laptop, for the same reason: a build on your machine has your environment in it. Point the CI/CD pipeline at the server over SSH or push images to a registry the control plane pulls from.

When a PaaS is simply the better deal

Self-hosting advocates undersell this and platform marketing oversells it, so here is the flat version. Pay somebody else when:

  • Downtime costs real money and nobody is on call. One VPS is one point of failure. A managed platform is also a point of failure, but it is somebody else's 3am.
  • You need point-in-time database recovery. Reproducing managed Postgres with PITR, automated failover, and tested restores is a genuine project, not a weekend. Neon, Supabase, and RDS sell it for less than it costs to run.
  • Nobody on the team enjoys Linux. The savings evaporate the first time a certificate, a disk, or a kernel eats an afternoon.
  • Traffic is spiky. Autoscaling is the one thing a fixed VPS genuinely cannot do. A box sized for the peak is idle capacity you pay for all month.
  • Compliance wants an audit trail. SOC 2 evidence is a product feature on a managed platform and a documentation project on your own server.

The middle path is common and entirely reasonable: static sites and the marketing frontend on a free edge host, the database managed, and the long-running or egress-heavy pieces on your own box.

Self-hosting questions, answered

Is self-hosting really cheaper than a managed platform?

On the invoice, yes: a Hetzner CX22 at roughly 4 to 5 euros a month replaces $20 to $50 of managed hosting for a typical small app. In total cost, only if maintenance stays under about two hours a month, which is what a control plane like Coolify buys you. The saving is real but modest, so self-host for control, egress, or long-running workloads rather than for the few hundred dollars a year.

Coolify, Dokploy, or Kamal - which one should I install?

Coolify if you are running several apps and databases or anyone else needs to operate them, because its 280-plus templates and built-in scheduled backups remove the most work. Dokploy if you are fluent in Docker Compose, want lower idle overhead, and like its Swarm-native multi-server story. Kamal if you have one or two apps, deploy from CI, and want nothing at all running on the server except your application.

How do HTTPS certificates work on a self-hosted server?

Your reverse proxy handles them and you should never touch certbot by hand. Coolify and Dokploy both run Traefik, Kamal ships kamal-proxy, and all of them request and renew Let's Encrypt certificates automatically once DNS points at the box. If you are configuring a proxy yourself, Caddy does automatic HTTPS with a two-line config, which is the main reason to pick it over Nginx.

What happens when the single server dies?

You rebuild it, and how long that takes is entirely down to preparation. With images in a registry, configuration in git, and last night's database dump in object storage, a fresh VPS plus a redeploy is 15 to 30 minutes. Without off-box backups it is unbounded and possibly terminal. If that window is unacceptable, you need a second machine or a managed platform, not a better VPS.

Where to go next

Everything above assumes containers, so keep the Docker cheatsheet open for build, run, and volume commands, and read container tools for the Docker versus Podman question on a server and for the orchestration ladder above a single box.

If the deploy story is still manual, the CI/CD pipeline guide wires the git push to the server. And before committing, price the alternative honestly in the hosting tools directory - several platforms are free at the size most projects stay.