What is n8n?
n8n is a workflow automation platform that connects APIs, databases and AI models with a visual node editor, much like Zapier or Make. Its source code is on GitHub under the Sustainable Use License, a fair-code license that lets you self-host it for free for internal use. It ships hundreds of integrations, JavaScript and Python code nodes, and AI agent building blocks.
Requirements
- A Linux server with 1 vCPU and 2 GB of RAM to start. Give it more if you run many parallel executions.
- Docker Engine and Docker Compose v2.
- A domain name with a DNS record pointing at the server. Third-party services need a public HTTPS URL to call your webhooks.
Step 1: Prepare the server
The steps below assume Ubuntu 24.04 with Docker installed. If you need Docker, follow the official install guide. Then create a folder for the stack:
mkdir -p ~/n8n && cd ~/n8n
Step 2: Create the Docker Compose file
This stack runs n8n with Postgres, which the n8n team recommends for anything beyond testing. Save it as docker-compose.yml:
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
interval: 5s
timeout: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n:stable
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
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
N8N_PORT: 5678
WEBHOOK_URL: https://${N8N_HOST}/
GENERIC_TIMEZONE: ${TZ}
TZ: ${TZ}
N8N_PROXY_HOPS: 1
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 336
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
volumes:
db_data:
n8n_data:
Create a .env file in the same folder:
N8N_HOST=n8n.example.com
TZ=Europe/London
POSTGRES_PASSWORD=CHANGE_ME
N8N_ENCRYPTION_KEY=CHANGE_ME
Generate each secret with openssl rand -hex 32 and use a different value for each. Store a copy of N8N_ENCRYPTION_KEY in your password manager: without it, a restored database is useless because every credential is encrypted with it. WEBHOOK_URL makes n8n show and register the public address for webhook triggers, and N8N_PROXY_HOPS=1 tells it to trust the X-Forwarded-* headers from your reverse proxy. EXECUTIONS_DATA_MAX_AGE is in hours, so 336 keeps two weeks of execution history.
The stable tag follows the current stable release. To pin, replace it with an exact version from the n8n releases page.
Step 3: Start and open the app
docker compose up -d
docker compose logs -f n8n
When the log shows that the editor is accessible, finish Step 4 so you can open https://n8n.example.com. To test before DNS is ready, use an SSH tunnel: ssh -L 5678:127.0.0.1:5678 user@server, then browse to http://localhost:5678. On first load n8n asks you to create the owner account. That account has full admin rights, so use a strong password and turn on two-factor authentication in your user settings.
Step 4: Put it behind HTTPS
Port 5678 is bound to 127.0.0.1 in the Compose file, so only a reverse proxy on the same host can reach it. With Caddy:
n8n.example.com {
reverse_proxy 127.0.0.1:5678
}
Caddy issues the certificate automatically and passes WebSocket traffic, which the editor needs for live execution updates. With Nginx Proxy Manager, create a proxy host to port 5678 and switch on "Websockets Support".
Backups and upgrades
Back up the Postgres database (docker compose exec postgres pg_dump -U n8n n8n > n8n.sql), the n8n_data volume, and your .env file with the encryption key. You can also export workflows as JSON with docker compose exec n8n n8n export:workflow --all --output=/home/node/.n8n/backup.json.
Read the release notes before a major version jump, then upgrade:
docker compose pull && docker compose up -d
Database migrations run automatically when the new container starts.
Troubleshooting
- "Mismatching encryption keys" on start: the key in
.envdoes not match the one saved in then8n_datavolume. Restore the original key rather than generating a new one. - Webhook URLs show
localhost:5678:WEBHOOK_URLis missing or wrong. Fix it and rundocker compose up -dto recreate the container. - Editor shows "Connection lost": the proxy is dropping WebSocket connections. Enable WebSocket support or check timeouts on your proxy.
- Database grows quickly: keep execution pruning on and lower
EXECUTIONS_DATA_MAX_AGE.
Next steps
Set up SMTP so you can invite team members, connect your first credentials, and import a template from the n8n workflow library. For high-volume use, look at queue mode with Redis and separate worker containers.
Spotted something out of date? Tell us and we will update the guide.