A working production-style n8n setup on a Linux VPS: Docker Compose, Postgres, automatic HTTPS and the settings people most often get wrong.
Running n8n yourself is not hard, but a casual docker run is not a production setup. This guide builds one you can actually rely on: n8n and Postgres in Docker Compose, a reverse proxy with automatic HTTPS, and the environment variables that keep webhooks and credentials working.
If you would rather skip the server work, managed n8n hosting gives you the same dedicated instance with backups and monitoring handled for you.
n8n.yourdomain.com, with an A record pointing at the VPS IP.sudo apt update && sudo apt upgrade -y
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
# log out and back in so the group change applies
mkdir -p ~/n8n && cd ~/n8n
Create a .env file for your secrets. Generate long random values (for example with openssl rand -hex 32) and keep a copy somewhere safe.
N8N_HOST=n8n.yourdomain.com
TZ=Asia/Kolkata
POSTGRES_PASSWORD=change-this-to-a-long-random-password
N8N_ENCRYPTION_KEY=change-this-to-a-long-random-string
services:
postgres:
image: postgres:16
restart: always
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
volumes:
- postgres_data:/var/lib/postgresql/data
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_HOST: ${N8N_HOST}
N8N_PORT: 5678
N8N_PROTOCOL: https
WEBHOOK_URL: https://${N8N_HOST}/
GENERIC_TIMEZONE: ${TZ}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
volumes:
postgres_data:
n8n_data:
Two details matter here. n8n is bound to 127.0.0.1, so it is only reachable through the reverse proxy, not directly from the internet. And N8N_ENCRYPTION_KEY is set explicitly, so your saved credentials stay readable if you ever rebuild the container.
docker compose up -d
docker compose logs -f n8n
Caddy obtains and renews certificates automatically. Install it from its official package repository, then put this in /etc/caddy/Caddyfile:
n8n.yourdomain.com {
reverse_proxy 127.0.0.1:5678
}
sudo systemctl reload caddy
Open https://n8n.yourdomain.com and create the owner account. Nginx with Certbot works just as well if you prefer it.
sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable
cd ~/n8n
docker compose pull
docker compose up -d
Take a backup first (see our n8n backup and restore guide) and read the release notes before jumping several versions.
Want a dedicated n8n server with backups, monitoring and SSL already handled? Order in minutes and we provision it for you.
See Managed n8n Hosting Plans