Getting n8n running in Docker takes five minutes. Keeping it running for a year without losing credentials, webhooks or disk space takes a few extra settings that the quick-start skips. Here's a Compose setup with the five I'd set on day one.
The Compose file
services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${PG_PASSWORD}
POSTGRES_DB: n8n
volumes:
- pg_data:/var/lib/postgresql/data
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
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: ${PG_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: n8n.example.com
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.example.com/
GENERIC_TIMEZONE: Asia/Kolkata
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 168
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
volumes:
pg_data:
n8n_data:
Put PG_PASSWORD and N8N_ENCRYPTION_KEY in a .env file next to it (openssl rand -hex 32 makes a good key), then docker compose up -d.
1. Pin your own encryption key
n8n encrypts every saved credential with N8N_ENCRYPTION_KEY. If you don't set one, it generates a key inside the data volume. Rebuild the container without that volume and every credential becomes unreadable. Set it yourself and back it up somewhere other than the server.
2. Use Postgres, not the default SQLite
SQLite is fine for a test. Once you have busy webhooks and thousands of executions, Postgres handles concurrent writes better and is far easier to back up with pg_dump.
3. Tell n8n its public URL
Behind a reverse proxy, n8n doesn't know its own address, so webhook nodes show localhost:5678 URLs that nothing outside can reach. WEBHOOK_URL fixes that. Bind the port to 127.0.0.1 as above and let Caddy or Nginx handle HTTPS in front.
4. Prune old executions
Every run is stored with its input and output data. Without pruning, the database grows until the disk fills. EXECUTIONS_DATA_MAX_AGE: 168 keeps one week of history; raise it if you need longer audits.
5. Set the timezone
Schedule Trigger nodes use GENERIC_TIMEZONE. Leave it unset and your "9 AM" workflow runs at 9 AM UTC, which is 2:30 PM in India.
Backups and updates
A nightly pg_dump of the n8n database plus a copy of your .env is enough to rebuild the whole instance. To update, run docker compose pull && docker compose up -d, but read the n8n release notes first, because major versions sometimes change node behaviour.
If you'd rather skip the server work
All of the above is yours to maintain: OS patches, Docker updates, backups and HTTPS renewals. If you want a private n8n instance without looking after the box, ShoHost's managed n8n hosting runs each instance in isolated Docker on its own KVM plan, with no per-step execution limits. Support is on WhatsApp (+91 94880 91432) and email (support@shohost.com), 9 AM to 12 midnight IST.
Top comments (0)