A self-hosted n8n dedicated server setup runs n8n's workflow automation engine on hardware you fully control, paired with PostgreSQL for data storage, Redis for queue-based execution, and NGINX for encrypted traffic. It replaces per-task billing with a fixed monthly server cost and gives you unlimited workflow executions on the Community Edition. This guide walks through the exact commands and configuration files needed to deploy n8n docker compose in a production-ready, scalable state.
What You'll Learn
Key Takeaways & What You Will Build
Introduction & Cloud Cost Comparison
Architecture Overview & Moving Past SQLite
Step 1: Preparing the Server and Installing Docker
Step 2: The Production Docker Compose File
Step 3: Securing with NGINX and SSL
Step 4: Booting Up and Creating the Owner Account
Step 5: Disaster Recovery and Backups
Frequently Asked Questions
Key Takeaways
Cost control: A $20–$50/month dedicated server can replace a $103.50/month Zapier Team plan, with no per-task metering.
Production stack: n8n's default SQLite database is not built for concurrent, production-grade workloads, this guide uses PostgreSQL for storage and Redis for queue mode instead.
Queue mode scaling: Running
EXECUTIONS_MODE=queuewith dedicated worker containers lets you scale execution capacity horizontally by adding worker replicas, independent of the main process.Security is non-negotiable: Webhooks require HTTPS, and losing your
N8N_ENCRYPTION_KEYpermanently locks you out of every stored credential ,back both up before you go live.
What You Will Build
OS: Ubuntu 22.04 LTS or 24.04 LTS with root/sudo access
Containerization: Docker Engine with Docker Compose plugin
Database: PostgreSQL 16 (persistent volume storage)
Message Broker: Redis 7 (queue mode backbone)
Automation Engine: n8n main process + scalable worker containers
Reverse Proxy & SSL: NGINX + Let's Encrypt Certbot SSL certificate
The Real Cost of Cloud Automation
If you've priced out Zapier or Make for a business running more than a handful of daily automations, you already know the task-based billing model gets expensive fast. Zapier's Professional plan starts around $29.99/month (or roughly $19.99/month billed annually) for 750 tasks, and its Team plan runs about $103.50/month billed monthly for 2,000 pooled tasks. Overages are billed at roughly 1.25x your base task rate, so a busy month can push the bill well past the sticker price.
A self-hosted n8n instance on a dedicated server flips that math. You pay a flat monthly rate for the server, and every workflow execution is included — n8n's Community Edition is free and open-source, with no execution caps.
| Factor | Zapier Professional | Zapier Team | Self-Hosted n8n (Dedicated Server) |
|---|---|---|---|
| Monthly cost | ~$29.99 | ~$103.50 | ~$20–$50 (flat server cost) |
| Task/execution limit | 750 tasks | 2,000 tasks | Unlimited executions |
| Overage billing | ~1.25x base rate | ~1.25x base rate | None — fixed cost |
| Multi-step workflows | Included | Included | Included |
| Data ownership | Zapier's cloud | Zapier's cloud | Your infrastructure |
| Scaling model | Buy a higher tier | Buy a higher tier | Add worker containers |
Pricing shown is publicly listed, task-based pricing as of mid-2026 and is subject to change — always confirm current rates directly with the vendor before budgeting.
The trade-off is obvious: self-hosting shifts the responsibility for uptime, security, and backups onto you. That's exactly what the rest of this n8n self hosting guide is designed to handle properly, not as an afterthought.
Architecture Overview & Moving Past SQLite
What is n8n queue mode? It's an execution architecture where a main n8n process handles the UI, API, and webhook triggers, while separate worker containers pick up and run the actual workflow executions from a Redis-backed queue. This decouples "receiving a trigger" from "doing the work," which is what makes horizontal scaling possible.
Why the Default SQLite Setup Fails in Production
By default, a fresh n8n install uses an embedded SQLite database. That's fine for testing on a laptop, but it breaks down under real traffic for a few concrete reasons:
- SQLite is not built for high concurrency. It locks the database file during writes, so simultaneous webhook executions can queue up or fail outright.
- Queue mode explicitly does not support SQLite. n8n's own documentation states that running a distributed setup with SQLite isn't supported — queue mode requires PostgreSQL.
- No safe path to horizontal scaling. A single SQLite file can't be shared reliably across multiple worker containers, which rules out adding more execution capacity later.
The Production Stack (n8n Production Setup)
This guide builds the architecture n8n itself recommends for scale:
- n8n (main process): Handles the editor UI, REST API, and incoming webhook requests, then hands off execution jobs.
- PostgreSQL: Stores workflows, credentials, and execution data. n8n recommends PostgreSQL 13 or newer for production.
- Redis: Acts as the message broker for queue mode. The main process pushes execution IDs into Redis; workers pull them off the queue.
- n8n (worker processes): Dedicated containers that do the actual workflow execution, running the same n8n image in worker mode.
- NGINX + Certbot: Terminates HTTPS traffic and reverse-proxies it to the n8n main process, which is mandatory for webhooks to function reliably.
Prerequisites & Sizing Your Hardware
Before you start, make sure you have:
- A dedicated server or VPS running Ubuntu 22.04 LTS or 24.04 LTS with root or sudo access. For robust production environments, hosting your automation engine on a dedicated server infrastructure ensures predictable CPU and I/O performance.
- A registered domain name pointed at your server's IP address (an A record), needed for SSL and stable webhook URLs.
- Basic terminal comfort — you'll be running Docker and editing a couple of config files, but no advanced Linux administration is required.
| Use Case | vCPU | RAM | Notes |
|---|---|---|---|
| Testing / light personal use | 1–2 | 2 GB | Meets the documented minimum only; expect instability under real load |
| Small business production | 2–4 | 4 GB | Reasonable starting point for this guide's stack (n8n + Postgres + Redis) |
| Growing team / moderate volume | 4 | 8 GB | Recommended once you add worker replicas or data-heavy workflows |
| AI-heavy / high-volume workflows | 8+ | 16 GB+ | Needed when workflows process large documents or run LLM chains |
NVMe SSD storage is strongly recommended over spinning disks, since PostgreSQL write performance — not CPU — is usually the first bottleneck on a busy n8n instance.
Step 1: Preparing the Server and Installing Docker
Connect to your server via SSH, then update the system and install Docker Engine with the Compose plugin.
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install prerequisites
sudo apt install -y ca-certificates curl gnupg
# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the Docker repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine, CLI, and Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Verify the installation
docker --version
docker compose version
# Allow your user to run Docker without sudo (log out and back in after this)
sudo usermod -aG docker $USER
Once docker compose version returns a version number, you're ready to move on.
Step 2: The Production Docker Compose File
This is the core of the deploy n8n docker compose setup — a full stack with PostgreSQL, Redis, a main n8n process, and a dedicated worker container running in queue mode.
Create a project directory and the configuration files below:
mkdir -p ~/n8n-production && cd ~/n8n-production
Create the .env file:
# ---- Domain & timezone ----
DOMAIN_NAME=n8n.yourdomain.com
GENERIC_TIMEZONE=UTC
# ---- PostgreSQL ----
POSTGRES_USER=n8n_admin
POSTGRES_PASSWORD=CHANGE_THIS_STRONG_PASSWORD
POSTGRES_DB=n8n
POSTGRES_NON_ROOT_USER=n8n_app
POSTGRES_NON_ROOT_PASSWORD=CHANGE_THIS_TOO
# ---- n8n security ----
# Generate with: openssl rand -hex 32
N8N_ENCRYPTION_KEY=REPLACE_WITH_GENERATED_64_CHAR_KEY
# ---- Execution data retention ----
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=336
Create the docker-compose.yml file:
version: "3.8"
volumes:
db_storage:
n8n_storage:
redis_storage:
x-shared-n8n: &shared-n8n
image: docker.n8n.io/n8nio/n8n:latest
restart: always
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_HEALTH_CHECK_ACTIVE=true
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_HOST=${DOMAIN_NAME}
- N8N_PROTOCOL=https
- N8N_PORT=5678
- WEBHOOK_URL=https://${DOMAIN_NAME}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${GENERIC_TIMEZONE}
- EXECUTIONS_DATA_PRUNE=${EXECUTIONS_DATA_PRUNE}
- EXECUTIONS_DATA_MAX_AGE=${EXECUTIONS_DATA_MAX_AGE}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
services:
postgres:
image: postgres:16-alpine
restart: always
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_NON_ROOT_USER=${POSTGRES_NON_ROOT_USER}
- POSTGRES_NON_ROOT_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
volumes:
- db_storage:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
redis:
image: redis:7-alpine
restart: always
volumes:
- redis_storage:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 10
n8n-main:
<<: *shared-n8n
container_name: n8n_main
ports:
- "127.0.0.1:5678:5678"
volumes:
- n8n_storage:/home/node/.n8n
command: start
n8n-worker:
<<: *shared-n8n
container_name: n8n_worker
volumes:
- n8n_storage:/home/node/.n8n
command: worker
deploy:
replicas: 2
Breaking Down the Key Environment Variables
- N8N_ENCRYPTION_KEY: This key encrypts every credential stored inside n8n. It's generated once and must stay identical across the main process and all workers. Lose it, and every stored credential becomes permanently unreadable — there's no recovery path.
- EXECUTIONS_MODE=queue: Switches n8n from single-process mode into distributed queue mode, telling the main process to push jobs to Redis instead of running them itself.
- QUEUE_BULL_REDIS_HOST: Points n8n at the Redis service so the main process and workers can communicate through the shared queue.
- EXECUTIONS_DATA_PRUNE and EXECUTIONS_DATA_MAX_AGE: Automatically delete old execution logs after a set number of hours (336 hours = 14 days in the example above) to stop the execution_entity table from growing indefinitely and slowing down PostgreSQL.
- replicas: 2 on the worker service: This is how you scale n8n with Redis worker nodes. Increasing this number adds more parallel execution capacity without touching the main process.
Step 3: Securing with NGINX and SSL
Webhooks will silently fail without HTTPS — most third-party services (Stripe, GitHub, Slack, etc.) refuse to deliver webhook payloads to unencrypted endpoints, and n8n's own webhook URLs are generated using the https:// scheme once configured. This is the step that makes your n8n nginx reverse proxy setup functional, not optional.
Install NGINX and Certbot on the host (outside Docker):
sudo apt install -y nginx certbot python3-certbot-nginx
Create the NGINX server block:
sudo nano /etc/nginx/sites-available/n8n.yourdomain.com
Add the following configuration:
server {
listen 80;
server_name n8n.yourdomain.com;
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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
Enable the site and reload NGINX:
sudo ln -s /etc/nginx/sites-available/n8n.yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Generate a free SSL certificate with Certbot, which will automatically edit the NGINX config to redirect HTTP to HTTPS:
sudo certbot --nginx -d n8n.yourdomain.com
Certbot's certificates renew automatically via a systemd timer, but it's worth confirming the renewal job is active:
sudo systemctl status certbot.timer
Step 4: Booting Up and Creating the Owner Account
With the compose file and NGINX config in place, bring the stack up:
docker compose up -d
docker compose ps
Check that all containers report as healthy, then check the logs if anything looks off:
docker compose logs -f n8n-main
Once running, visit https://n8n.yourdomain.com in your browser. On first load, n8n presents an owner account setup screen where you set your admin email, name, and password — this account is stored in the users table in PostgreSQL and becomes your instance administrator. After that, you'll land on the main workflow canvas, ready to build your first automation.
Step 5: Disaster Recovery and Backups
This is the step most tutorials skip, and it's the one that actually saves your business when a disk fails or an upgrade goes wrong. You need backups of two things: your PostgreSQL database (workflows, credentials, execution history) and your .env file (your encryption key and secrets).
Create a backup script:
sudo nano /opt/n8n-backup.sh
Add the backup script contents:
#!/bin/bash
# n8n PostgreSQL + .env backup script
BACKUP_DIR="/opt/n8n-backups"
DATE=$(date +%F_%H%M)
PROJECT_DIR="/home/$(whoami)/n8n-production"
mkdir -p "$BACKUP_DIR"
# Dump the PostgreSQL database from inside the running container
docker exec $(docker compose -f "$PROJECT_DIR/docker-compose.yml" ps -q postgres) \
pg_dump -U n8n_admin -d n8n > "$BACKUP_DIR/n8n_db_$DATE.sql"
# Back up the .env file (contains N8N_ENCRYPTION_KEY and DB credentials)
cp "$PROJECT_DIR/.env" "$BACKUP_DIR/env_$DATE.bak"
# Compress and remove backups older than 14 days
find "$BACKUP_DIR" -type f -mtime +14 -delete
Make it executable and schedule it with cron:
sudo chmod +x /opt/n8n-backup.sh
crontab -e
Add a daily backup at 3 AM:
0 3 * * * /opt/n8n-backup.sh
Store a copy of the .env file off-server in a password manager or encrypted cloud storage since a local-only backup won't help if the entire server is lost. This single habit is what separates an n8n self host security and encryption key backup strategy that actually works from one that only looks complete.
Frequently Asked Questions
What is n8n queue mode?
n8n queue mode is a distributed execution architecture where a main n8n process handles the UI, API, and incoming webhooks, while separate worker processes execute the actual workflows. The main process pushes execution jobs into a Redis-backed queue, and available workers pull jobs from that queue, execute them, and write the results back to the PostgreSQL database. This setup lets you scale execution capacity by adding worker containers rather than upgrading a single server.
How much RAM does n8n need?
n8n's documented minimum is 1–2 vCPUs and 2 GB of RAM, which is enough to launch the application but not to run it reliably under real workloads. For a small business production setup with PostgreSQL and Redis, 4 GB of RAM is a realistic starting point. Teams running frequent workflows, large payloads, or AI-driven automations should plan for 8 GB or more.
Can I run n8n without Docker?
Yes, n8n can be installed directly via npm on a server running Node.js, without Docker. However, Docker is the deployment method n8n officially recommends for most self-hosting scenarios, since it isolates dependencies, simplifies upgrades, and makes it far easier to run the multi-container Postgres + Redis + worker architecture this guide covers.
Why shouldn't I use SQLite for a production n8n instance?
SQLite locks the database file during write operations, which causes conflicts when multiple workflows execute concurrently. n8n's own documentation states that queue mode is not supported with SQLite, since a single database file cannot be reliably shared across a main process and multiple worker containers. PostgreSQL is the recommended database for any production or scaling scenario.
What happens if I lose my N8N_ENCRYPTION_KEY?
Every credential stored inside n8n — API keys, OAuth tokens, database passwords — is encrypted using this key. If it's lost and you don't have a backup, those credentials cannot be decrypted or recovered, and you'll need to re-enter every credential manually across every workflow. Back up the key immediately after generating it, ideally in a secrets manager separate from the server itself.
How do I scale n8n with Redis worker nodes?
Once queue mode is enabled with EXECUTIONS_MODE=queue, you scale horizontally by increasing the number of worker containers connected to the same Redis instance and PostgreSQL database. In Docker Compose, this means raising the replicas count on the worker service, or running docker compose up -d --scale n8n-worker=4 to add capacity without changing the main process.
Conclusion and Next Steps
You now have a complete, production-grade self-hosted n8n deployment stack:
- Docker Compose orchestrates PostgreSQL, Redis, n8n main, and worker containers smoothly.
- Queue mode separates UI triggers from heavy workflow executions for horizontal scalability.
- NGINX and Certbot handle SSL termination and WebSocket/webhook traffic requirements.
- Automated backups safeguard your relational database and encryption keys against failure.
Deploy This Stack on a BytesRack Dedicated Server: Everything in this guide assumes one thing: a server with full root access, predictable performance, and enough headroom to run PostgreSQL, Redis, and multiple n8n worker containers without resource contention. That's precisely what BytesRack's bare metal dedicated servers are built for — no noisy neighbors, no shared vCPU throttling, and NVMe storage as standard, so PostgreSQL write performance never becomes your bottleneck. Explore BytesRack Dedicated Servers and get a plan sized correctly for a production n8n stack from day one, with room to add worker replicas as your automation workload grows.
Discover BytesRack Dedicated Server Locations
BytesRack servers are available around the world, providing diverse options for hosting websites. Each region offers unique advantages, making it easier to choose a location that best suits your specific hosting needs.

Media Stream Solutions
Gaming Solutions
E-Commerce Solutions
VPN Server Solutions
GPU Server Solutions
Financial Solutions
Security Solutions