June 21, 2026
Self-Hosting n8n on a Cheap VPS: The Setup I Actually Use
Most “how to self-host n8n” guides stop at docker run and call it done. That’s fine
until you need HTTPS, a stable domain, and the thing to survive a server reboot. This
is what I landed on after a weekend of trial and error getting it to actually stick.
What you need
- A VPS (a $5-6/mo box is plenty to start - n8n is light unless you’re running heavy workflows)
- A domain or subdomain pointed at the VPS’s IP
- Docker and Docker Compose installed
The docker-compose setup
version: "3.7"
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
environment:
- N8N_HOST=automate.yourdomain.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://automate.yourdomain.com/
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
Note the port binding to 127.0.0.1 only - n8n isn’t exposed directly to the
internet. A reverse proxy handles that, which is also where SSL comes from.
Reverse proxy + SSL
Caddy is the least fuss option here - it gets you free, auto-renewing SSL with a 3-line config:
automate.yourdomain.com {
reverse_proxy 127.0.0.1:5678
}
That’s genuinely the whole config. Caddy handles the certificate from Let’s Encrypt automatically on first request.
The part most guides skip: backups
Your workflows and credentials live in that n8n_data volume. If you lose it, you
lose everything. A simple daily cron job covers this:
docker run --rm -v n8n_data:/data -v /backups:/backup \
alpine tar czf /backup/n8n-$(date +%F).tar.gz /data
Drop the resulting .tar.gz files somewhere off the box - even a free-tier object
storage bucket is enough for personal use.
What I’d do differently starting today
If I were setting this up fresh, I’d add a WEBHOOK_TUNNEL_URL only during local
dev (not production), and split webhook-heavy workflows onto their own n8n instance
once volume picks up - but for a first self-hosted setup, the above is genuinely
enough to run reliably for months without touching it.