Most n8n problems on a server come from a few environment variables. Learn what each important one does and how to set it safely in Docker Compose.
Docker Compose lets you describe your whole n8n setup in one file. Most of the behaviour is controlled by environment variables. This guide explains the ones you will use most often. Names and defaults can change between n8n versions, so confirm them in the official n8n documentation for the version you run.
services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
volumes:
- db_data:/var/lib/postgresql/data
n8n:
image: docker.n8n.io/n8nio/n8n:latest
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
N8N_HOST: n8n.example.com
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.example.com/
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
GENERIC_TIMEZONE: Asia/Karachi
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: "336"
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
volumes:
db_data:
n8n_data:
For production, pin a specific n8n version instead of latest, so an update never happens by surprise. See how to update n8n without losing data.
| Variable | What it does | Common mistake |
|---|---|---|
| N8N_HOST | The hostname n8n is served on. | Leaving it as localhost on a public server. |
| N8N_PROTOCOL | http or https for generated URLs. | Using http behind an HTTPS proxy. |
| WEBHOOK_URL | The public base URL that webhook nodes show and register. | Missing it, so webhook URLs show localhost. |
| N8N_ENCRYPTION_KEY | Encrypts the credentials stored in the database. | Losing it or letting it change between restarts. |
| DB_TYPE and DB_POSTGRESDB_* | Switch the database from SQLite to Postgres. | Wrong host name. Inside Compose, use the service name. |
| GENERIC_TIMEZONE | Sets the timezone for scheduled workflows. | Forgetting it, so schedules run at UTC time. |
| EXECUTIONS_DATA_PRUNE and EXECUTIONS_DATA_MAX_AGE | Delete old execution data after a set number of hours. | Never pruning, so the disk fills up. |
n8n creates an encryption key if you do not set one, and stores it in its data folder. Set it yourself in a .env file, keep a copy somewhere safe, and never change it. Without the same key, a restored database cannot decrypt its credentials. This is the most common reason restores fail, and it is covered in our backup guide.
# .env (do not commit this file)
POSTGRES_PASSWORD=use-a-long-random-password
N8N_ENCRYPTION_KEY=use-a-long-random-string
Compose reads .env automatically. Restrict the file so only your user can read it, and bind n8n to 127.0.0.1 so only your reverse proxy can reach it.
Run Caddy or Nginx in front of n8n to handle HTTPS. Make sure the proxy forwards the original host and protocol headers. If webhook URLs or logins misbehave behind a proxy, read n8n webhook not working: common fixes.
When one process is not enough, n8n can run in queue mode with Redis and workers. That adds more variables. We explain it in n8n queue mode explained.
Do not want to maintain compose files? Managed n8n hosting gives you a ready, secured instance.
See Managed n8n Plans