services: postgres: image: postgres:17-alpine restart: unless-stopped environment: - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_DB=${POSTGRES_DB} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] start_period: 30s interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine restart: unless-stopped command: redis-server --requirepass ${REDIS_PASSWORD} environment: - REDIS_PASSWORD=${REDIS_PASSWORD} volumes: - redis_data:/data healthcheck: test: ["CMD-SHELL", "redis-cli -a \"$$REDIS_PASSWORD\" ping | grep PONG"] start_period: 20s interval: 10s timeout: 5s retries: 5 # Main instance: serves the editor UI and webhooks, publishes executions # to the Redis (Bull) queue instead of running them itself. n8n: image: n8nio/n8n:2.30.4 restart: unless-stopped environment: # PostgreSQL - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=postgres - DB_POSTGRESDB_PORT=5432 - DB_POSTGRESDB_DATABASE=${POSTGRES_DB} - DB_POSTGRESDB_USER=${POSTGRES_USER} - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD} # Queue mode (Redis / Bull) - EXECUTIONS_MODE=queue - QUEUE_BULL_REDIS_HOST=redis - QUEUE_BULL_REDIS_PORT=6379 - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD} - QUEUE_HEALTH_CHECK_ACTIVE=true - OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true # Encryption key shared between the main instance and the workers - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} # Networking - N8N_HOST=${N8N_HOST} - N8N_PORT=5678 - N8N_PROTOCOL=http - N8N_PROXY_HOPS=1 - NODE_ENV=production - N8N_WEBHOOK_URL=https://${N8N_HOST}/ - N8N_EDITOR_BASE_URL=https://${N8N_HOST}/ - GENERIC_TIMEZONE=${GENERIC_TIMEZONE} - N8N_SECURE_COOKIE=false volumes: - n8n_data:/home/node/.n8n depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD-SHELL", "wget --spider -q http://127.0.0.1:5678/healthz"] start_period: 60s interval: 10s timeout: 5s retries: 10 # Queue workers: pull executions from Redis and run them. Scale them by # changing the N8N_WORKER_REPLICAS environment variable and redeploying. n8n-worker: image: n8nio/n8n:2.30.4 restart: unless-stopped command: worker deploy: replicas: ${N8N_WORKER_REPLICAS:-2} environment: # PostgreSQL - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=postgres - DB_POSTGRESDB_PORT=5432 - DB_POSTGRESDB_DATABASE=${POSTGRES_DB} - DB_POSTGRESDB_USER=${POSTGRES_USER} - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD} # Queue mode (Redis / Bull) - EXECUTIONS_MODE=queue - QUEUE_BULL_REDIS_HOST=redis - QUEUE_BULL_REDIS_PORT=6379 - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD} - QUEUE_HEALTH_CHECK_ACTIVE=true # Must be the same key as the main instance - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} - NODE_ENV=production - GENERIC_TIMEZONE=${GENERIC_TIMEZONE} depends_on: n8n: condition: service_healthy healthcheck: test: ["CMD-SHELL", "wget --spider -q http://127.0.0.1:5678/healthz"] start_period: 60s interval: 10s timeout: 5s retries: 10 volumes: postgres_data: redis_data: n8n_data: