n8n is a workflow automation tool, similar in spirit to Zapier, that you can run yourself. Self-hosting n8n on a VPS gives you unlimited workflows and keeps your data and credentials on your own server. This guide uses Docker Compose with PostgreSQL and HTTPS.
Before you start
- A Linux VPS with 2 GB RAM or more, Docker and the Compose plugin.
- A subdomain such as
n8n.example.compointing to the server. - Nginx with Certbot (or another reverse proxy) for HTTPS. Webhooks from services like Stripe or GitHub require a public HTTPS URL.
- Check n8n's licence terms (Sustainable Use License) for your use case.
Create the project
mkdir -p /opt/n8n && cd /opt/n8nCreate .env (chmod 600 .env):
POSTGRES_PASSWORD=change-me-long-random
N8N_ENCRYPTION_KEY=generate-with-openssl-rand-hex-32
N8N_HOST=n8n.example.com
GENERIC_TIMEZONE=Europe/BerlinGenerate the key with openssl rand -hex 32 and store it in your password manager: n8n encrypts all saved credentials with it, and without it a restored backup cannot decrypt them.
Write docker-compose.yml
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: n8n
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n"]
interval: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n:latest
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
ports:
- "127.0.0.1:5678:5678"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: ${N8N_HOST}
N8N_PROTOCOL: https
WEBHOOK_URL: https://${N8N_HOST}/
GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
N8N_PROXY_HOPS: 1
volumes:
- n8n_data:/home/node/.n8n
volumes:
pgdata:
n8n_data:For production, pin a specific n8n version tag instead of latest so updates happen when you choose. Start it:
docker compose up -d && docker compose logs -f n8nAdd HTTPS with Nginx
n8n's editor uses WebSockets, so include the upgrade headers:
server {
server_name n8n.example.com;
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
}Then run certbot --nginx -d n8n.example.com. Open the URL and create the owner account straight away.
Secure your instance
- Create the owner account immediately; invite other users from Settings → Users.
- Enable two-factor authentication for accounts in user settings.
- Restrict the editor to your IP or a VPN in Nginx if only you use it, while leaving
/webhook/paths public. - Keep Postgres unexposed (no published port), as above.
Back up and update
docker compose exec -T postgres pg_dump -U n8n -Fc n8n > /backup/n8n-$(date +%F).dumpAlso keep the encryption key. You can export workflows as JSON with docker compose exec n8n n8n export:workflow --all --output=/home/node/.n8n/workflows.json.
To update: read the release notes for breaking changes, back up, change the image tag, then docker compose pull && docker compose up -d.
Troubleshooting
- Webhook URLs show localhost:5678:
WEBHOOK_URLis not set to the public HTTPS address. - Editor shows "Connection lost": WebSocket headers are missing in the proxy.
- Credentials could not be decrypted: the encryption key changed. Restore the original
N8N_ENCRYPTION_KEY. - Workflows run at the wrong time: set
GENERIC_TIMEZONEand the workflow's own time zone setting.
n8n FAQ
How much does a self-hosted n8n need?
2 GB RAM handles many light workflows. Heavy data processing or many parallel executions need more, or queue mode with workers.
SQLite or PostgreSQL?
SQLite works for testing; PostgreSQL is more robust for production and required for queue mode.
Can I run n8n on cPanel hosting?
Not reliably: it is a long-running Node.js service with WebSockets. Use a VPS.
