Self-Hosting n8n: Complete Setup Guide
TLDR: Self-hosting n8n gives you unlimited workflow executions, full data control, and zero per-task fees — all for the cost of a basic server ($5-20/month). This guide walks through the complete setup: Docker Compose deployment with PostgreSQL, nginx reverse proxy, SSL certificates, environment configuration, backups, and production hardening. By the end, you will have a production-ready n8n instance accessible via HTTPS on your own domain.
Why Self-Host n8n?
Self-hosting n8n is the most popular deployment option for good reason. Compared to n8n Cloud, you get:
- No execution limits — run as many workflows as your server handles
- Full data sovereignty — credentials and workflow data never leave your infrastructure
- Cost savings — a $10/month server replaces a $50-300/month cloud subscription
- Customization — configure memory limits, execution timeouts, and queue modes
- Compliance — meet GDPR, HIPAA, or internal security requirements
The trade-off is responsibility: you handle updates, backups, and uptime. This guide covers all of that.
Step 1: Server Setup
Start with a VPS from any provider. We recommend at least 2GB RAM for comfortable operation. SSH into your server and install Docker:
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Install Docker Compose plugin
sudo apt install docker-compose-plugin -y
# Verify installation
docker --version
docker compose version
Log out and back in for the group change to take effect.
Step 2: Docker Compose Configuration
Create a project directory and the compose file:
mkdir -p /opt/n8n && cd /opt/n8n
Create docker-compose.yml:
version: '3.8'
services:
n8n:
image: n8nio/n8n:latest
restart: always
ports:
- "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_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://${N8N_HOST}/
- GENERIC_TIMEZONE=UTC
- N8N_LOG_LEVEL=info
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: always
environment:
- POSTGRES_DB=n8n
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n"]
interval: 10s
timeout: 5s
retries: 5
volumes:
n8n_data:
postgres_data:
Create the .env file with your secrets:
# Generate secure values
POSTGRES_PASSWORD=$(openssl rand -hex 24)
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
cat > .env << EOF
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
N8N_HOST=n8n.yourdomain.com
EOF
Important: The N8N_ENCRYPTION_KEY encrypts stored credentials. Back it up securely — losing it means losing access to all saved credentials.
Step 3: Nginx Reverse Proxy with SSL
Install nginx and Certbot:
sudo apt install nginx certbot python3-certbot-nginx -y
Create the nginx configuration at /etc/nginx/sites-available/n8n:
server {
listen 80;
server_name n8n.yourdomain.com;
location / {
proxy_pass http://localhost: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;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
}
}
Enable the site and get SSL:
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
# Get SSL certificate (replace with your domain)
sudo certbot --nginx -d n8n.yourdomain.com
Certbot automatically configures HTTPS and sets up auto-renewal.
Step 4: Launch and Verify
Start the stack:
cd /opt/n8n
docker compose up -d
# Check logs
docker compose logs -f n8n
Wait for the message n8n ready on 0.0.0.0, port 5678. Navigate to https://n8n.yourdomain.com in your browser. You should see the n8n setup screen where you create your admin account.
Step 5: Automated Backups
Create a backup script at /opt/n8n/backup.sh:
#!/bin/bash
BACKUP_DIR="/opt/n8n/backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
# Backup PostgreSQL
docker compose exec -T postgres pg_dump -U n8n n8n | gzip > "$BACKUP_DIR/n8n_db_$DATE.sql.gz"
# Backup n8n data volume
docker run --rm -v n8n_n8n_data:/data -v "$BACKUP_DIR":/backup alpine \
tar czf "/backup/n8n_data_$DATE.tar.gz" -C /data .
# Keep only last 30 days
find "$BACKUP_DIR" -name "*.gz" -mtime +30 -delete
echo "Backup completed: $DATE"
Schedule it with cron:
chmod +x /opt/n8n/backup.sh
echo "0 3 * * * /opt/n8n/backup.sh >> /var/log/n8n-backup.log 2>&1" | crontab -
Production Hardening Checklist
Before running critical workflows, address these items:
Security:
- Change the default n8n port or restrict access via firewall (
ufw allow from YOUR_IP to any port 5678) - Set
N8N_BASIC_AUTH_ACTIVE=truewith a strong password if not using n8n’s built-in user management - Keep Docker images updated (
docker compose pull && docker compose up -dweekly) - Restrict the
.envfile permissions:chmod 600 .env
Reliability:
- Set
N8N_DEFAULT_BINARY_DATA_MODE=filesystemto avoid storing large files in the database - Configure execution timeout:
EXECUTIONS_TIMEOUT=600(10 minutes max per workflow) - Enable execution pruning:
EXECUTIONS_DATA_PRUNE=trueandEXECUTIONS_DATA_MAX_AGE=168(7 days) - Monitor disk space — execution logs and binary data can grow fast
Performance:
- For high-throughput setups, enable queue mode with Redis for horizontal scaling
- Increase PostgreSQL
shared_buffersandwork_memfor large datasets - Consider separate servers for n8n and PostgreSQL if running 100+ active workflows
Self-hosted n8n is a reliable automation platform that teams at FlipFactory and thousands of others depend on daily. With this setup, you have a production-grade instance that costs a fraction of cloud alternatives while giving you full control over your automation infrastructure.
Frequently Asked Questions
What are the minimum server requirements for self-hosting n8n?
n8n runs comfortably on a server with 1 CPU core, 2GB RAM, and 20GB storage. This handles dozens of active workflows and thousands of daily executions. For heavier loads (100+ workflows, high-frequency triggers), we recommend 2 cores and 4GB RAM. A $5-10/month VPS from Hetzner, DigitalOcean, or Contabo is sufficient for most teams.
How do I update n8n when a new version is released?
With Docker Compose, updating is two commands: `docker compose pull` to download the latest image, then `docker compose up -d` to restart with the new version. Your data persists in the PostgreSQL database and Docker volumes. We recommend testing updates on a staging instance first if you run critical production workflows.