Lesson 22 / 25

Self-Hosting with Docker Compose

Run n8n on a server with persistent data, a database and the right environment variables.

What production needs

For anything beyond a demo, run n8n with a persistent volume, a PostgreSQL database instead of the default SQLite for heavier use, the public WEBHOOK_URL and timezone set, HTTPS through a reverse proxy, and a fixed N8N_ENCRYPTION_KEY. For high volume, n8n has a queue mode with separate workers. Always check the official hosting docs for current settings.

From laptop to server

Run n8n with persistent storage and HTTPS, and manage workflows like code.

Three steps: run, protect, maintain.
Figure 7.1 — Run, protect and maintain.

A minimal Compose file

Keep real secrets in an .env file that is not committed. Variable names are from the n8n docs at the time of writing; verify them for your version.

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    ports: ["5678:5678"]
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - WEBHOOK_URL=https://n8n.example.com/
      - GENERIC_TIMEZONE=Asia/Kolkata
    volumes:
      - n8n_data:/home/node/.n8n
    restart: unless-stopped
volumes:
  n8n_data:

Set WEBHOOK_URL behind a proxy

Behind a reverse proxy n8n does not know its public address. Without WEBHOOK_URL, the webhook URLs it shows are wrong, and external services will call addresses that do not exist.

Quick check: Why set WEBHOOK_URL when n8n is behind a reverse proxy?

  • It is only cosmetic
  • To speed up the database
  • To disable authentication
  • So generated webhook URLs use the correct public address
Answer

So generated webhook URLs use the correct public address — n8n cannot guess its external address behind a proxy, so you tell it.