How to Self-Host n8n with Docker Compose
What Is n8n?
n8n is a self-hosted workflow automation platform. It’s the best self-hosted alternative to Zapier, Make (Integromat), and IFTTT. Build automated workflows with a visual node-based editor — connect APIs, transform data, send notifications, sync databases, and automate virtually anything. n8n has 400+ integrations, supports JavaScript/Python code nodes, and can handle everything from simple webhook triggers to complex multi-step workflows with branching logic.
Updated March 2026: Verified with latest Docker images and configurations.
The key difference from Zapier: your data stays on your server, there are no per-execution fees, and you can write custom code in any workflow.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 1 GB of free RAM (2 GB recommended)
- 2 GB of free disk space
- A domain name (recommended for webhook URLs)
Docker Compose Configuration
Create a docker-compose.yml file:
services:
n8n:
image: n8nio/n8n:2.12.3
container_name: n8n
restart: unless-stopped
ports:
- "5678:5678"
environment:
N8N_HOST: "localhost" # Set to your domain
N8N_PORT: "5678"
N8N_PROTOCOL: "https" # Use "http" for local access
WEBHOOK_URL: "https://n8n.example.com/" # Your public URL for webhooks
N8N_ENCRYPTION_KEY: "change_this_to_random_string" # CHANGE THIS — generate with: openssl rand -hex 24
DB_TYPE: "postgresdb"
DB_POSTGRESDB_HOST: "n8n_db"
DB_POSTGRESDB_PORT: "5432"
DB_POSTGRESDB_DATABASE: "n8n"
DB_POSTGRESDB_USER: "n8n"
DB_POSTGRESDB_PASSWORD: "change_this_strong_password" # Must match PostgreSQL password
GENERIC_TIMEZONE: "America/New_York" # Your timezone
volumes:
- n8n_data:/home/node/.n8n
depends_on:
n8n_db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 3
n8n_db:
image: postgres:16-alpine
container_name: n8n_db
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: change_this_strong_password # Must match DB_POSTGRESDB_PASSWORD
POSTGRES_DB: n8n
volumes:
- n8n_pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n"]
interval: 10s
timeout: 5s
retries: 5
volumes:
n8n_data:
n8n_pgdata:
Start the stack:
docker compose up -d
Initial Setup
- Open
http://your-server-ip:5678in your browser - Create your owner account (email and password)
- You’re dropped into the workflow editor — start building
n8n uses SQLite by default if you don’t configure PostgreSQL. The PostgreSQL setup above is recommended for production — it handles concurrent executions better and supports n8n’s queue mode.
Configuration
Key Environment Variables
| Variable | Default | Description |
|---|---|---|
N8N_ENCRYPTION_KEY | auto-generated | Encrypts credentials. Set explicitly and back up — losing this means losing all stored credentials. |
WEBHOOK_URL | N8N_HOST | Public URL for incoming webhooks. Must be accessible from the internet. |
EXECUTIONS_DATA_PRUNE | true | Auto-delete old execution data |
EXECUTIONS_DATA_MAX_AGE | 336 | Hours to keep execution data (default 14 days) |
N8N_BASIC_AUTH_ACTIVE | false | Add HTTP Basic Auth in front of n8n |
N8N_CONCURRENCY_PRODUCTION_LIMIT | -1 | Max concurrent workflow executions (-1 = unlimited) |
Credentials Security
n8n encrypts all stored credentials (API keys, passwords, OAuth tokens) using N8N_ENCRYPTION_KEY. This key is critical:
- Set it explicitly in your Compose file
- Back it up separately
- If you lose it, all stored credentials become unreadable
- Generate with:
openssl rand -hex 24
Webhook Configuration
For workflows triggered by external webhooks, WEBHOOK_URL must be your publicly accessible URL:
WEBHOOK_URL: "https://n8n.example.com/"
Without this, webhook URLs in your workflows will use the internal hostname, which external services can’t reach.
Advanced Configuration (Optional)
Queue Mode (Worker Architecture)
For high-volume workflows, run n8n in queue mode with separate main and worker processes:
n8n:
# ... same as above, plus:
environment:
EXECUTIONS_MODE: "queue"
QUEUE_BULL_REDIS_HOST: "n8n_redis"
n8n_worker:
image: n8nio/n8n:2.12.3
container_name: n8n_worker
restart: unless-stopped
command: worker
environment:
# Same database and Redis config as main instance
EXECUTIONS_MODE: "queue"
QUEUE_BULL_REDIS_HOST: "n8n_redis"
volumes:
- n8n_data:/home/node/.n8n
n8n_redis:
image: redis:7-alpine
container_name: n8n_redis
restart: unless-stopped
volumes:
- n8n_redis:/data
SMTP for Email Notifications
environment:
N8N_EMAIL_MODE: "smtp"
N8N_SMTP_HOST: "smtp.example.com"
N8N_SMTP_PORT: "587"
N8N_SMTP_USER: "[email protected]"
N8N_SMTP_PASS: "your-smtp-password"
N8N_SMTP_SSL: "false"
External Storage for Binary Data
For workflows handling large files:
environment:
N8N_EXTERNAL_STORAGE_TYPE: "s3"
N8N_EXTERNAL_STORAGE_S3_HOST: "minio.example.com"
N8N_EXTERNAL_STORAGE_S3_BUCKET_NAME: "n8n"
N8N_EXTERNAL_STORAGE_S3_ACCESS_KEY: "your-access-key"
N8N_EXTERNAL_STORAGE_S3_SECRET_KEY: "your-secret-key"
Reverse Proxy
Set WEBHOOK_URL and N8N_HOST to match your domain. n8n requires WebSocket support for the editor.
Nginx Proxy Manager config:
- Scheme: http
- Forward Hostname: n8n
- Forward Port: 5678
- Enable WebSocket Support: Yes (critical for the editor)
See Reverse Proxy Setup for full configuration.
Backup
Back up two things:
- PostgreSQL database — contains workflows, credentials (encrypted), execution history:
docker compose exec n8n_db pg_dump -U n8n n8n > n8n-backup-$(date +%Y%m%d).sql
- n8n data volume — contains the encryption key (if auto-generated) and custom nodes:
docker run --rm -v n8n_data:/data -v $(pwd):/backup alpine \
tar czf /backup/n8n-data-$(date +%Y%m%d).tar.gz /data
See Backup Strategy for a complete backup approach.
Troubleshooting
Webhooks Not Receiving Data
Symptom: External services send webhooks but n8n doesn’t trigger.
Fix: Check WEBHOOK_URL — it must be your public URL with HTTPS. Verify the URL is reachable from the internet. If behind a reverse proxy, ensure WebSocket support is enabled and the proxy passes all headers.
”Encryption key is missing” Error
Symptom: n8n can’t decrypt stored credentials after restart or migration.
Fix: The N8N_ENCRYPTION_KEY must be the same as when the credentials were created. If you didn’t set it explicitly, n8n generated one and stored it in ~/.n8n/config. Check the data volume for the original key.
Workflow Executions Pile Up / Memory Issues
Symptom: n8n memory grows over time, eventually crashes. Fix: Enable execution data pruning:
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: "168" # 7 days
EXECUTIONS_DATA_SAVE_ON_ERROR: "all"
EXECUTIONS_DATA_SAVE_ON_SUCCESS: "none" # Don't save successful execution data
Container Starts But Web UI Is Blank
Symptom: Port 5678 responds but the editor doesn’t load.
Fix: This is usually a reverse proxy issue. n8n’s editor uses WebSockets. Ensure your proxy passes the Upgrade and Connection headers. In Nginx, add:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
Resource Requirements
- RAM: ~200 MB idle, 500 MB+ under load (depends on workflow complexity)
- CPU: Low idle, medium during execution (JavaScript/Python code nodes are CPU-intensive)
- Disk: ~300 MB for the application, PostgreSQL storage grows with execution history
Verdict
n8n is the best self-hosted workflow automation tool. It’s the closest you’ll get to Zapier without paying per execution or sending your data to a third party. The visual editor is intuitive, the integration library is massive, and the ability to write custom JavaScript/Python code makes it handle edge cases that Zapier can’t. The main competition is Node-RED — which is more IoT/hardware focused — and Huginn — which is more developer-oriented. For most workflow automation needs, n8n is the clear winner.
Frequently Asked Questions
Is self-hosted n8n free?
Yes. Self-hosted n8n is free under the Sustainable Use License for personal and internal business use. You can run unlimited workflows with unlimited executions on your own server at no cost. The paid n8n Cloud service ($20+/month) is for people who want managed hosting. The license restricts reselling n8n as a service to third parties — but running it for your own automations is completely free.
How does n8n compare to Zapier?
n8n replaces Zapier for most automation needs. Key differences: n8n has no per-execution pricing (Zapier charges $0.01-0.03 per task on paid plans), n8n runs on your server so your data stays private, and n8n supports custom JavaScript/Python code nodes for complex logic. Zapier has more polished integrations for SaaS products and requires zero technical setup. If you are comfortable with Docker, n8n saves significant money — a heavy Zapier user paying $50-100/month gets the same capability from self-hosted n8n for free.
Can n8n run on a Raspberry Pi?
Yes, but with limitations. n8n runs on ARM64 (Raspberry Pi 4/5) and idles at around 200 MB of RAM. Simple workflows run fine. However, complex workflows with many nodes, large data transformations, or frequent webhook triggers can strain a Pi’s CPU and memory. For a homelab with 10-20 workflows, a Pi 4 with 4 GB RAM works. For heavy production use, use an x86 server or mini PC.
How do I trigger workflows from external services?
Use the Webhook node. Each webhook node gets a unique URL that external services can POST to. Configure your service (GitHub, Stripe, your app) to send webhook events to that URL. n8n receives the data and triggers the workflow. You can also use the Schedule Trigger for time-based execution, Email Trigger (IMAP) for email-based triggers, and the n8n API for programmatic execution.
Can I use n8n with my self-hosted apps?
Yes — this is where self-hosted n8n really shines. Since n8n runs on the same network as your other containers, it can directly access their APIs without exposing anything to the internet. Common setups: Paperless-ngx document processing, Home Assistant automation triggers, Nextcloud file events, Gitea CI/CD webhooks, and Vaultwarden monitoring. Use the HTTP Request node to call any API on your local network.
How do I back up n8n workflows?
n8n stores all workflow definitions, credentials, and execution logs in its database (SQLite or PostgreSQL). Back up the /home/node/.n8n directory (or your mapped volume) to capture everything. You can also export individual workflows as JSON from the UI (Workflow > Download as File) or use the n8n API to export all workflows programmatically. For credential security, note that exported workflow JSON files do not include credential secrets — those stay in the database.
What happens if a workflow fails?
n8n shows failed executions in the Executions list with error details. You can configure error handling per workflow: add an Error Trigger node to catch failures and send alerts (email, Slack, webhook), or enable automatic retry with configurable retry count and delay. Production workflows should always have error handling — at minimum, a notification so you know when something breaks.
Related
- n8n Workflows Not Executing: Fix Guide
- Best Self-Hosted Automation Tools
- n8n vs Node-RED
- Airflow vs n8n
- Kestra vs n8n
- Temporal vs n8n
- n8n vs Activepieces
- n8n vs Huginn
- Automatisch vs n8n
- Windmill vs n8n
- Replace Zapier with Self-Hosted Automation
- Replace IFTTT with Self-Hosted Automation
- Docker Compose Basics
- Reverse Proxy Setup
- Backup Strategy
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments