Docker & DevOps

Self-host n8n workflow automation with Docker Compose

Run n8n on your own VPS with Docker Compose and PostgreSQL behind HTTPS, set the webhook URL and encryption key correctly, secure access and back up your workflows.

IntermediateLinux VPS3 min read

n8n is a workflow automation tool, similar in spirit to Zapier, that you can run yourself. Self-hosting n8n on a VPS gives you unlimited workflows and keeps your data and credentials on your own server. This guide uses Docker Compose with PostgreSQL and HTTPS.

Before you start

  • A Linux VPS with 2 GB RAM or more, Docker and the Compose plugin.
  • A subdomain such as n8n.example.com pointing to the server.
  • Nginx with Certbot (or another reverse proxy) for HTTPS. Webhooks from services like Stripe or GitHub require a public HTTPS URL.
  • Check n8n's licence terms (Sustainable Use License) for your use case.

Create the project

mkdir -p /opt/n8n && cd /opt/n8n

Create .env (chmod 600 .env):

POSTGRES_PASSWORD=change-me-long-random
N8N_ENCRYPTION_KEY=generate-with-openssl-rand-hex-32
N8N_HOST=n8n.example.com
GENERIC_TIMEZONE=Europe/Berlin

Generate the key with openssl rand -hex 32 and store it in your password manager: n8n encrypts all saved credentials with it, and without it a restored backup cannot decrypt them.

Write docker-compose.yml

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_DATABASE: n8n
      DB_POSTGRESDB_USER: n8n
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_HOST: ${N8N_HOST}
      N8N_PROTOCOL: https
      WEBHOOK_URL: https://${N8N_HOST}/
      GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
      N8N_PROXY_HOPS: 1
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  pgdata:
  n8n_data:

For production, pin a specific n8n version tag instead of latest so updates happen when you choose. Start it:

docker compose up -d && docker compose logs -f n8n

Add HTTPS with Nginx

n8n's editor uses WebSockets, so include the upgrade headers:

server {
    server_name n8n.example.com;
    client_max_body_size 50m;
    location / {
        proxy_pass http://127.0.0.1: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-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }
}

Then run certbot --nginx -d n8n.example.com. Open the URL and create the owner account straight away.

Secure your instance

  • Create the owner account immediately; invite other users from Settings → Users.
  • Enable two-factor authentication for accounts in user settings.
  • Restrict the editor to your IP or a VPN in Nginx if only you use it, while leaving /webhook/ paths public.
  • Keep Postgres unexposed (no published port), as above.

Back up and update

docker compose exec -T postgres pg_dump -U n8n -Fc n8n > /backup/n8n-$(date +%F).dump

Also keep the encryption key. You can export workflows as JSON with docker compose exec n8n n8n export:workflow --all --output=/home/node/.n8n/workflows.json.

To update: read the release notes for breaking changes, back up, change the image tag, then docker compose pull && docker compose up -d.

Troubleshooting

  • Webhook URLs show localhost:5678: WEBHOOK_URL is not set to the public HTTPS address.
  • Editor shows "Connection lost": WebSocket headers are missing in the proxy.
  • Credentials could not be decrypted: the encryption key changed. Restore the original N8N_ENCRYPTION_KEY.
  • Workflows run at the wrong time: set GENERIC_TIMEZONE and the workflow's own time zone setting.

n8n FAQ

How much does a self-hosted n8n need?

2 GB RAM handles many light workflows. Heavy data processing or many parallel executions need more, or queue mode with workers.

SQLite or PostgreSQL?

SQLite works for testing; PostgreSQL is more robust for production and required for queue mode.

Can I run n8n on cPanel hosting?

Not reliably: it is a long-running Node.js service with WebSockets. Use a VPS.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.