Back to All Guides
Tutorials Published: 2026-02-25· Last Updated: 2026-10-03· By Nawanjana Dilshan

Self-Hosting n8n with Docker Compose: Production Setup Guide

A battle-tested production guide to deploying n8n on Docker Compose with PostgreSQL, automated SSL via Traefik or Caddy, persistent volumes, and queue workers.

Prerequisites & Server Sizing

Running n8n in production requires stability. While SQLite is suitable for testing, a production installation must use PostgreSQL as the backend database to prevent database locking during parallel workflow executions.

  • Recommended Server: 2 vCPU, 4GB RAM (e.g. Hetzner CPX21 or DigitalOcean 4GB Droplet, ~$12–$15/mo).
  • OS: Ubuntu 24.04 LTS or Debian 12.
  • Domain: A pointed DNS A record (e.g., n8n.yourdomain.com).

Production docker-compose.yml

Below is the battle-tested Compose configuration featuring PostgreSQL, persistent named volumes, and automated container restarts:

version: '3.8'

services:
  postgres:
    image: postgres:16-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 -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: n8nio/n8n:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - 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}
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - GENERIC_TIMEZONE=UTC
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:
  n8n_data:

Essential Production Configurations

  1. Prune Execution History (EXECUTIONS_DATA_PRUNE=true): If left unpruned, executions data will quickly bloat your database to tens of gigabytes within months.
  2. Reverse Proxy (Nginx / Caddy): Terminate SSL using Let's Encrypt certificates before forwarding traffic to port 5678.
  3. Automated Backups: Run a nightly cron script creating a compressed pg_dump backup transferred to an off-site S3 bucket.
ND

Written by Nawanjana Dilshan

Freelance n8n, Agentic AI, and Local LLM Specialist based in Sri Lanka. Designing private, production-grade automation systems for businesses in the US, UK, EU, and Australia.

Need assistance implementing this?

Hire Nawanjana for Docker & Cloud Deployment Services

Fixed-price packages with discovery calls and 30-day post-launch warranties.

Explore Services & Pricing