n8n is a workflow automation tool, like Zapier or Make, that you can run on your own server. Self-hosting it means no limit on workflow executions: you pay for the server, not per run, and your API keys and data stay on a machine you control.
This guide sets up n8n the clean way: in Docker, behind Caddy, a small web server that gets a free HTTPS certificate automatically and renews it on its own. It takes about 15 minutes.
What you need
- A Linux VPS with Ubuntu 24.04 (Debian 12 works the same). 2 GB RAM is enough to try n8n; for real business workflows choose 4 GB or more (see how much RAM and CPU your VPS needs).
- A subdomain for n8n, for example
n8n.example.com, with an A record pointing to your server's IP. Not sure how? Follow how to point your domain to your VPS first. The subdomain must already point to the server, or the certificate can't be issued. - A secured server. If it's brand new, do the 8 first security steps before anything else.
In the commands below, replace n8n.example.com with your own subdomain.
1. Install Docker
Docker's official install script adds Docker and the Compose plugin in one go:
curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER Log out and log back in so the second line takes effect, then check it works:
docker --version docker compose version 2. Check the subdomain points to the server
dig +short n8n.example.com It should print your server's IP. If it prints nothing or an old IP, wait a few minutes for DNS to update before going on.
3. Open ports 80 and 443
Caddy needs both: port 80 to prove you own the domain, and port 443 for HTTPS.
sudo ufw allow 80,443/tcp sudo ufw status Note that we will not open n8n's own port, 5678. n8n is only reachable through Caddy, over HTTPS.
4. Create the n8n folder and settings
mkdir ~/n8n && cd ~/n8n nano docker-compose.yml Paste this in, change the two lines with n8n.example.com, and set your time zone if you are not in India:
services: n8n: image: docker.n8n.io/n8nio/n8n restart: unless-stopped environment: - N8N_HOST=n8n.example.com - N8N_PROTOCOL=https - N8N_PORT=5678 - WEBHOOK_URL=https://n8n.example.com/ - N8N_PROXY_HOPS=1 - GENERIC_TIMEZONE=Asia/Kolkata - TZ=Asia/Kolkata - NODE_ENV=production volumes: - n8n_data:/home/node/.n8n caddy: image: caddy:2 restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config volumes: n8n_data: caddy_data: caddy_config: Save with Ctrl+O, Enter, then Ctrl+X. Now create the Caddy settings, which are just three lines:
nano Caddyfile n8n.example.com { reverse_proxy n8n:5678 } What the important settings do:
-
WEBHOOK_URL: the address other apps use to call your workflows. Without it, n8n shows webhook links withlocalhost:5678, which nothing outside can reach. -
N8N_PROXY_HOPS=1: tells n8n it sits behind one proxy (Caddy), so it sees the visitor's real IP. -
n8n_data: a Docker volume that keeps your workflows, credentials and encryption key safe when the container is updated or recreated.
5. Start n8n
docker compose up -d docker compose logs -f caddy Within a minute you should see a line saying the certificate was obtained successfully. Press Ctrl+C to leave the log. Both containers should show as running:
docker compose ps Because of restart: unless-stopped, n8n starts again on its own after a reboot.
6. Create your owner account
Open https://n8n.example.com in your browser. You'll see the padlock and n8n's setup screen. Create the owner account straight away, because until you do, anyone who finds the address could claim it. Use a strong password, and turn on two-factor authentication under Settings → Personal.
Test it with a simple workflow: add a Schedule Trigger and a Gmail or Telegram node, run it once, and you're automating.
7. Update n8n
n8n releases new versions often. Take a snapshot of your VPS first, then:
cd ~/n8n docker compose pull docker compose up -d docker image prune -f Your workflows stay in the n8n_data volume, so nothing is lost. Before a big version jump, read n8n's release notes for breaking changes. If anything misbehaves, you can roll back to the snapshot in minutes.
8. Back up your workflows
Turn on automatic backups for the server. For an extra copy of n8n's data you can download anywhere, run:
docker run --rm -v n8n_n8n_data:/data -v ~/backups:/backup alpine tar czf /backup/n8n-$(date +%F).tar.gz -C /data . The volume name is the folder name plus _n8n_data; check yours with docker volume ls. This archive includes n8n's encryption key, and without it saved credentials can't be read on a new server, so keep the file somewhere safe and private.
Common problems
| Problem | Usual fix |
|---|---|
| No certificate, browser shows an error | The subdomain doesn't point to the server yet, or port 80 is closed. Check dig, ufw status and docker compose logs caddy. |
Webhook URLs show localhost:5678 | WEBHOOK_URL is missing or misspelled. Fix it and run docker compose up -d. |
| Times in workflows are off by 5½ hours | Set GENERIC_TIMEZONE and TZ to Asia/Kolkata. |
| n8n becomes slow or restarts | The server is out of memory; check with free -h. Heavy workflows and AI agents need 4–8 GB RAM. |
Originally published on the Volyte blog. Prefer it ready-made? Our n8n VPS comes with n8n, the subdomain and SSL already set up.