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:
