Short answer: self-hosting n8n takes a Linux VPS with 2 GB RAM ($6.50 a month), a domain pointing at it, and a short Docker Compose file with n8n and Caddy. Caddy gets the HTTPS certificate on its own. You end up with your own n8n at https://n8n.yourdomain.com, no execution limits, and your credentials on a server only you control.
n8n's cloud plans charge by executions. The self-hosted Community Edition is free to run on your own server for your own workflows; check n8n's Sustainable Use License if you plan to offer n8n to others as a service.
01Which Server
| Use | Plan | Price |
|---|---|---|
| A few workflows, light data | 1–2 vCPU, 2 GB RAM, 20 GB NVMe | $6.50/month |
| Many workflows, AI nodes, larger files | 2 vCPU, 6 GB RAM, 40 GB NVMe | $13/month |
| Busy instance with Postgres and queue mode | 6 vCPU, 10 GB RAM | $26/month |
The 1 GB plan is too tight once Docker, n8n and a few workflows with data are running.
Full root SSH access · NVMe storage · DDoS protection · No setup fee
02Before You Start
- A domain or subdomain with an A record pointing to your server's IP, for example
n8n.example.com. DNS changes can take a few minutes. - Ports 80 and 443 reachable. If you use the firewall on your server page, allow both; Caddy needs port 80 to get the certificate.
- Docker: on a fresh Ubuntu 24.04 or Debian 12 server, as root:
curl -fsSL https://get.docker.com | sh
03The Compose File
Create a folder /opt/n8n with two files. First docker-compose.yml:
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
environment:
- N8N_HOST=n8n.example.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
- GENERIC_TIMEZONE=Europe/Berlin
- TZ=Europe/Berlin
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
volumes:
- n8n_data:/home/node/.n8n
expose:
- "5678"
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
volumes:
n8n_data:
caddy_data:Then the Caddyfile:
n8n.example.com {
reverse_proxy n8n:5678
}Replace n8n.example.com and the time zone with yours, then start it:
cd /opt/n8n
docker compose up -d
docker compose logs -fAfter a few seconds Caddy has the certificate. Open https://n8n.example.com and create the owner account; the first account you create is the admin.
04Settings That Matter
WEBHOOK_URL
makes n8n show the public address in Webhook nodes. Without it, they show localhost and outside services can't reach them.
GENERIC_TIMEZONE
is the zone Schedule Triggers run in. Without it, "every day at 9:00" runs in the container's default time.
n8n only behind Caddy
The compose file exposes port 5678 to Caddy only, not to the internet, so everything goes over HTTPS.
The encryption key
n8n creates one in the data volume and uses it to encrypt saved credentials. Copy it from /home/node/.n8n/config inside the volume and keep it safe.
05Updates and Backups
Update:
cd /opt/n8n
docker compose pull
docker compose up -dRead the release notes before major versions; workflows occasionally need changes.
Back up the data volume (workflows, credentials, execution history in SQLite):
docker run --rm -v n8n_n8n_data:/data -v /root:/backup alpine \
tar czf /backup/n8n-$(date +%F).tar.gz -C /data .Docker names the volume after the folder, so it's n8n_n8n_data for /opt/n8n; docker volume ls shows the exact name. Copy the archive off the server: we don't make backups for you. For a busy instance, switch n8n to Postgres; the n8n docs describe the variables.
06Keep It Safe
- Strong owner password and two-factor login in n8n's personal settings.
- SSH only from your IP, with the firewall on your server page.
- Watch what workflows can reach. An Execute Command or Code node runs with the container's rights; only give n8n accounts to people you trust.
2 GB runs n8n with a handful of workflows. Take 6 GB for many workflows, AI nodes or large files.
- self host n8n
- n8n vps
- n8n docker compose
- n8n hosting
- install n8n ubuntu
- n8n self hosted https