This guide gives you two containers: n8n, and Traefik, which handles the HTTPS certificate (Let’s Encrypt) and routing. It follows the official n8n documentation.
Self-hosting takes some comfort with servers: you are responsible for updates, backups and security of the instance. If you would rather not run a server at all, see n8n Cloud vs self-hosting.
Before you start
- A Linux VPS with root or sudo access. Not sure what size to get? Read the n8n RAM and CPU requirements or use the VPS calculator.
- A domain where you can create a DNS record.
- Ports 80 and 443 open in the VPS firewall.
Install Docker and Docker Compose
Follow the official Docker instructions for your distribution, then check:
docker --version
docker compose version
To run Docker without sudo, add your user to the docker group (sudo usermod -aG docker ${USER}) and open a new session.
Point a subdomain at the VPS
Create an A record named n8n (or whatever you prefer) pointing to the VPS IP address. n8n will answer at https://n8n.yourdomain.com.
Create the project folder and the .env file
mkdir n8n-compose && cd n8n-compose
mkdir local-files
Create the .env file:
DOMAIN_NAME=yourdomain.com
SUBDOMAIN=n8n
GENERIC_TIMEZONE=Europe/Berlin
SSL_EMAIL=[email protected]
GENERIC_TIMEZONE sets the timezone used by the Cron and other scheduling nodes; use your own from the tz database list. Without it, n8n falls back to New York time.
Create the compose.yaml
Use the file from the official documentation. The key points:
- The
traefikservice listens on ports 80 and 443, redirects HTTP to HTTPS and requests the certificate usingSSL_EMAIL. - The
n8nservice publishes port 5678 only on 127.0.0.1, so outside traffic goes through Traefik. - The
n8n_datavolume (at/home/node/.n8n) holds the SQLite database and the encryption key;traefik_dataholds the certificates; the./local-filesfolder is mounted at/files. - The
N8N_WEBHOOK_URLvariable exists from n8n 2.30.0. On earlier versions, useWEBHOOK_URL.
Use the stable tag, not latest. The latest tag can point to a beta release. In production, change the image to n8nio/n8n:stable or pin a version such as n8nio/n8n:2.43.6.
The official example also sets --api.insecure=true on Traefik, which turns on the Traefik dashboard without a password. It is not exposed because port 8080 is not published, but if you don’t use the dashboard you can delete that line.
Start the containers
sudo docker compose up -d
On the first start, the database and the certificate take about 20 seconds to be ready. Then open https://n8n.yourdomain.com and create the administrator account. To stop everything: sudo docker compose stop.
After it is running
- Backups: copy the
n8n_datavolume regularly. Without the encryption key stored in it, saved credentials cannot be read. The steps are in n8n backup. - Updates: n8n ships a new version almost every week. Watch the minimum safe version page and update with
docker compose pull && docker compose up -d(details in how to update n8n). - Database: the default is SQLite. For higher volume or queue mode, use PostgreSQL: see n8n with Docker Compose and PostgreSQL.
How much memory to reserve
With a simple workflow (Webhook → Edit Fields → Respond to Webhook), n8n idles at around 450 to 550 MiB and stays in that range while answering dozens of calls per second, on 1 GB/1 vCPU as well as on 2 GB/2 vCPUs. Traefik uses 20 to 30 MiB. Workflows with AI, large files or heavy use of the Code node use a lot more (see what memory use depends on).
In practice, 1 GB free for n8n covers light personal use; for production, prefer a VPS with 2 GB or more. The n8n and Traefik images take a little over 1 GB of disk; set aside about 5 GB for data, logs and updates.
To keep n8n from taking over the whole VPS, limit the container in the n8n service:
deploy:
resources:
limits:
memory: 1g
cpus: "1"
Optional: DNS challenge certificate (Cloudflare)
If the server cannot accept connections on port 443 while the certificate is issued, replace the two mytlschallenge lines with:
- "--certificatesresolvers.mytlschallenge.acme.dnschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.dnschallenge.provider=cloudflare"
Also pass CF_DNS_API_TOKEN in Traefik’s environment:, using a Cloudflare token with only DNS Edit permission on your zone. Traefik creates and removes the _acme-challenge TXT record by itself.
Where to run it
For current plans and prices, see how much it costs to host n8n. One example is Hostinger KVM 2 (2 vCPU, 8 GB): see the plan ↗.
Frequently asked questions
How much RAM does n8n need on a VPS?
With a simple workflow, n8n idles at around 450 to 550 MiB, and Traefik uses 20 to 30 MiB. 1 GB free is enough for light personal use; for production, prefer a VPS with 2 GB or more. The images take a little over 1 GB of disk.
Should I use the n8nio/n8n:latest image?
Not in production. The latest tag can point to a beta release. Use n8nio/n8n:stable or pin a specific version.
How do I update n8n installed with Docker Compose?
Back up the n8n_data volume, then run docker compose pull followed by docker compose up -d in the project folder.
What do I need to keep in the n8n backup?
The n8n_data volume, which holds the SQLite database and the encryption key. Without that key, saved credentials cannot be read.