DEV Community

Nevik Schmidt
Nevik Schmidt

Posted on

Self-Hosting n8n: Complete Setup Guide (2026)

Self-Hosting n8n: Complete Setup Guide (2026)

Self-hosting n8n eliminates the $20-500/month cost of cloud automation platforms and gives you complete control over your workflows and data.

This is the complete guide to getting n8n running on your own server in 2026.

Prerequisites

  • A server with at least 2GB RAM (DigitalOcean, Linode, Hetzner, or your own hardware)
  • SSH access to the server
  • Basic Linux command line knowledge
  • Docker installed (easiest path)
  • A domain name (optional but recommended)

Option 1: Docker Compose (Recommended)

This is the fastest and most reliable way to self-host n8n.

Step 1: Create Directory Structure

mkdir -p ~/n8n-docker
cd ~/n8n-docker
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Docker Compose File

cat > docker-compose.yml << 'EOF'
version: "3"

services:
  postgres:
    image: postgres:15-alpine
    container_name: n8n-db
    restart: always
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: your-secure-password-here
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - n8n-network

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: always
    ports:
      - "5678:5678"
    environment:
      - DB_TYPE=postgres
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=your-secure-password-here
      - N8N_HOST=your-domain.com
      - N8N_PORT=443
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_TUNNEL_URL=https://your-domain.com/
      - GENERIC_TIMEZONE=Europe/Berlin
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres
    networks:
      - n8n-network

  nginx:
    image: nginx:alpine
    container_name: n8n-nginx
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - n8n
    networks:
      - n8n-network

volumes:
  postgres_data:
  n8n_data:

networks:
  n8n-network:
    driver: bridge
EOF
Enter fullscreen mode Exit fullscreen mode

Step 3: Create Nginx Configuration

cat > nginx.conf << 'EOF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
  worker_connections 1024;
}

http {
  upstream n8n_backend {
    server n8n:5678;
  }

  server {
    listen 80;
    server_name your-domain.com;

    location / {
      return 301 https://$server_name$request_uri;
    }
  }

  server {
    listen 443 ssl http2;
    server_name your-domain.com;

    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    client_max_body_size 50M;

    location / {
      proxy_pass http://n8n_backend;
      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;
    }
  }
}
EOF
Enter fullscreen mode Exit fullscreen mode

Step 4: Generate SSL Certificate

Using Let's Encrypt:

# Install certbot
sudo apt-get install certbot python3-certbot-nginx

# Generate certificate
sudo certbot certonly --standalone -d your-domain.com

# Create ssl directory and copy certificates
mkdir -p ssl
sudo cp /etc/letsencrypt/live/your-domain.com/fullchain.pem ssl/
sudo cp /etc/letsencrypt/live/your-domain.com/privkey.pem ssl/
sudo chown -R $USER:$USER ssl/
Enter fullscreen mode Exit fullscreen mode

Step 5: Start n8n

# Update docker-compose.yml with your actual domain and password
# Then start the containers
docker-compose up -d

# Check status
docker-compose ps

# View logs
docker-compose logs -f n8n
Enter fullscreen mode Exit fullscreen mode

Wait 2-3 minutes for n8n to start. Access it at https://your-domain.com

Step 6: Create Initial Admin User

When you first access n8n, you'll be prompted to create an admin account. Do this immediately.

# Verify n8n is running
curl -s https://your-domain.com/api/v1/credentials | head
Enter fullscreen mode Exit fullscreen mode

Option 2: Native Installation (Advanced)

If you prefer not to use Docker:

Install Node.js 18+

# Using NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
Enter fullscreen mode Exit fullscreen mode

Install n8n Globally

sudo npm install -g n8n

# Verify installation
n8n --version
Enter fullscreen mode Exit fullscreen mode

Create Service File

sudo cat > /etc/systemd/system/n8n.service << 'EOF'
[Unit]
Description=n8n Workflow Automation
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=simple
User=n8n
WorkingDirectory=/home/n8n/.n8n
ExecStart=/usr/bin/n8n start
Restart=on-failure
RestartSec=10

Environment="NODE_ENV=production"
Environment="N8N_HOST=your-domain.com"
Environment="DB_TYPE=postgres"
Environment="DB_POSTGRESDB_HOST=localhost"
Environment="DB_POSTGRESDB_USER=n8n"
Environment="DB_POSTGRESDB_PASSWORD=your-secure-password"

[Install]
WantedBy=multi-user.target
EOF

# Enable and start
sudo systemctl enable n8n
sudo systemctl start n8n
sudo systemctl status n8n
Enter fullscreen mode Exit fullscreen mode

Post-Installation Setup

1. Enable 2FA

# In n8n UI: Settings → Security → Enable Two-Factor Authentication
Enter fullscreen mode Exit fullscreen mode

2. Configure Backup Strategy

# Backup n8n data weekly
0 2 * * 0 docker-compose exec -T postgres pg_dump -U n8n n8n > ~/n8n-backups/backup-$(date +\%Y\%m\%d).sql
Enter fullscreen mode Exit fullscreen mode

3. Set up Monitoring

# Monitor container health
docker-compose ps

# Monitor disk usage
du -sh ~/.n8n

# Monitor database size
docker-compose exec postgres psql -U n8n -d n8n -c "SELECT pg_size_pretty(pg_database_size('n8n'));"
Enter fullscreen mode Exit fullscreen mode

4. Configure Email Notifications

In n8n UI:

  • Settings → Mail
  • SMTP Host: smtp.your-provider.com
  • Port: 587
  • User: your-email@domain.com
  • Password: your-app-password

5. Webhook Configuration

For webhooks to work from external services:

# Ensure WEBHOOK_TUNNEL_URL is set correctly
export WEBHOOK_TUNNEL_URL=https://your-domain.com/

# Test webhook
curl -X GET https://your-domain.com/webhook/test
Enter fullscreen mode Exit fullscreen mode

Common Issues & Fixes

n8n won't start

# Check logs
docker-compose logs n8n

# Common causes:
# 1. Port 5678 already in use
sudo lsof -i :5678

# 2. Database not ready
docker-compose logs postgres

# 3. Insufficient disk space
df -h
Enter fullscreen mode Exit fullscreen mode

SSL Certificate Issues

# Verify certificate
openssl s_client -connect your-domain.com:443

# Check certificate expiration
sudo certbot certificates

# Renew certificate
sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

Database Corruption

# Check database
docker-compose exec postgres pg_isready

# Rebuild database (CAUTION: This deletes workflows!)
docker-compose exec n8n n8n start --tunnel
Enter fullscreen mode Exit fullscreen mode

Performance Optimization

Increase Worker Threads

# In docker-compose.yml, add:
environment:
  - EXECUTIONS_PROCESS=main
  - N8N_CONCURRENCY_QUEUE_SIZE=100
Enter fullscreen mode Exit fullscreen mode

Enable Caching

# Add Redis for better performance
redis:
  image: redis:7-alpine
  container_name: n8n-redis
  restart: always
  volumes:
    - redis_data:/data
Enter fullscreen mode Exit fullscreen mode

Database Indexing

# Optimize database
docker-compose exec postgres psql -U n8n -d n8n -c "VACUUM ANALYZE;"
Enter fullscreen mode Exit fullscreen mode

Upgrade n8n

# Stop containers
docker-compose down

# Pull latest image
docker-compose pull

# Start with new version
docker-compose up -d

# Verify
curl https://your-domain.com/api/v1/
Enter fullscreen mode Exit fullscreen mode

Backup & Restore Strategy

Automated Daily Backup

#!/bin/bash
BACKUP_DIR="$HOME/n8n-backups"
mkdir -p "$BACKUP_DIR"

# Backup database
docker-compose exec -T postgres pg_dump -U n8n n8n | \
  gzip > "$BACKUP_DIR/db-$(date +%Y%m%d-%H%M%S).sql.gz"

# Keep only last 30 days
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete

# Upload to S3 (optional)
# aws s3 cp "$BACKUP_DIR" s3://your-bucket/n8n/ --recursive
Enter fullscreen mode Exit fullscreen mode

Restore from Backup

# Restore database from backup
gunzip < "$BACKUP_DIR/db-20260322.sql.gz" | \
  docker-compose exec -T postgres psql -U n8n n8n
Enter fullscreen mode Exit fullscreen mode

Security Checklist

✓ SSH key authentication (disable password login)
✓ UFW firewall enabled
  ufw allow 22/tcp
  ufw allow 80/tcp
  ufw allow 443/tcp
  ufw enable
✓ Fail2Ban installed
✓ SSL certificate (auto-renew enabled)
✓ Admin account created
✓ 2FA enabled
✓ Database backups scheduled
✓ Regular security updates: apt update && apt upgrade
Enter fullscreen mode Exit fullscreen mode

Troubleshooting Commands

# Check service status
docker-compose status

# View recent errors
docker-compose logs --tail=50 n8n

# SSH into n8n container
docker-compose exec n8n sh

# Check disk usage
du -sh ~/.n8n
docker system df

# Reset admin password (if locked out)
docker-compose exec n8n n8n user-management:reset --email=admin@example.com
Enter fullscreen mode Exit fullscreen mode

Cost Analysis (2026)

Platform Cost/Month Setup
Zapier $50-500 5 min
Make $20-300 10 min
n8n Cloud $20-200 10 min
n8n Self-Hosted $3-10 20 min

Server cost: $3-6/month (DigitalOcean Droplet, VPS)

Conclusion

Self-hosting n8n gives you:

  • Cost savings: 90% cheaper than cloud alternatives
  • Data privacy: Everything stays on your server
  • Full control: No limits on operations or workflows
  • Reliability: Your infrastructure, your uptime guarantees

The setup takes 20 minutes. The savings are immediate.


🚀 Get my Free Workflow Templates → https://nevikschmidt.gumroad.com/l/uhrqpe

Top comments (0)