Setting up n8n with Docker requires Docker Engine, a docker-compose.yml file connecting n8n to a PostgreSQL database, and a minimum of four correctly set environment variables including your encryption key and webhook URL. The full setup takes two to four hours on a clean VPS. SQLite is not safe for production. PostgreSQL is the correct database from day one.
Self-hosting n8n gives you unlimited workflow executions at the cost of a VPS, typically $5 to $12 per month, compared to €24 per month minimum on n8n Cloud with a 2,500 execution limit. For businesses running automation at volume, or for businesses that need data to stay within a specific infrastructure for compliance reasons, the self-hosted path is the right one. You can check our post on n8n self hosted vs cloud.
Docker is the standard deployment method for self-hosted n8n. It packages n8n and all its dependencies into a container that runs consistently across any server environment. This guide covers the complete n8n docker setup process for a production-ready instance using Docker Compose, PostgreSQL, and Cloudflare Tunnel for SSL, written for operators who are comfortable with a terminal but are not full-time server administrators.
At BK Web Designs we run n8n in production daily on a self-hosted stack using this exact setup. We have built over 150 automations on it including AI agent workflows, CRM integrations, WhatsApp automation, and email management systems. Check our n8n Automation Services.
Before You Start: What You Actually Need
The official n8n documentation notes that n8n recommends self-hosting for expert users. Mistakes can lead to data loss, security issues, and downtime. This is accurate and worth taking seriously. The most common mistakes are covered in this guide specifically to prevent them.
What you need before starting:
A VPS running Ubuntu 22.04 LTS. The recommended minimum for light production use is 2GB RAM and 1 to 2 vCPU. For 20 to 100 active workflows, use 4GB RAM and 2 vCPU. Hetzner Cloud is the most widely recommended provider in the n8n community. DigitalOcean is a solid alternative. Expected cost is €5 to €15 per month depending on spec.
Docker Engine installed on the VPS. Not Docker Desktop. Docker Engine is the server-side component. Docker Compose is installed alongside it.
A domain name pointed at your VPS IP address. n8n webhooks require HTTPS in production. You need a domain to configure SSL. Without it, external services cannot send webhook data to your n8n instance.
A Cloudflare account with your domain managed through Cloudflare. This is used for the tunnel-based SSL approach in Step 4.
Step 1: Install Docker and Docker Compose on Your VPS
Connect to your VPS via SSH. Run the official Docker installation script for Ubuntu:
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp dockerVerify Docker is running:
docker --version
docker compose versionBoth commands should return version numbers. If docker compose returns an error, install the plugin separately:
sudo apt-get install docker-compose-pluginStep 2: Create Your Directory Structure and Environment File
Create the directory where n8n data will be stored:
sudo mkdir -p /opt/n8n/data
sudo mkdir -p /opt/n8n/postgres
sudo chown -R 1000:1000 /opt/n8n/data
sudo chown -R 999:999 /opt/n8n/postgresThe user IDs 1000 and 999 correspond to the node user and PostgreSQL user inside their containers. Setting these correctly prevents the EACCES permission denied error that breaks many n8n setups on first run.
Create your environment file:
nano /opt/n8n/.envAdd the following variables, replacing the placeholder values:
POSTGRES_USER=n8n
POSTGRES_PASSWORD=your_strong_password_here
POSTGRES_DB=n8n
N8N_ENCRYPTION_KEY=your_32_character_random_string_here
N8N_WEBHOOK_URL=https://your-domain.com
GENERIC_TIMEZONE=America/New_YorkThe N8N_ENCRYPTION_KEY is the most critical variable in your entire setup. This key encrypts every credential stored in n8n. If you lose it, every stored credential becomes unrecoverable. Generate a random 32 character string and store it in a password manager immediately. Never store it only in the .env file.
The N8N_WEBHOOK_URL must be set to your full domain with HTTPS before any workflow uses webhooks. Without this, webhook URLs generated inside n8n will be wrong and external services will not be able to reach them.
Step 3: Create the docker-compose.yml File
nano /opt/n8n/docker-compose.ymlPaste the following configuration:
version: '3.8'
services:
postgres:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- /opt/n8n/postgres:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER}']
interval: 5s
timeout: 5s
retries: 10
n8n:
image: n8nio/n8n
restart: always
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: 0.0.0.0
N8N_PORT: 5678
N8N_PROTOCOL: https
WEBHOOK_URL: ${N8N_WEBHOOK_URL}
GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
ports:
- "5678:5678"
volumes:
- /opt/n8n/data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthyCritical note: DB_TYPE must be set to postgresdb, not postgres. This is the most common environment variable mistake and the error it produces, connection to database failed, does not make the cause obvious.
Step 4: Configure SSL With Cloudflare Tunnel
Cloudflare Tunnel creates an encrypted connection between your VPS and Cloudflare’s network without requiring you to open inbound ports on your server or configure Nginx or Traefik. For operators who are not server administrators, this is the lowest-complexity path to HTTPS for n8n.
Install the Cloudflare Tunnel daemon on your VPS:
curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.debAuthenticate with your Cloudflare account:
cloudflared tunnel loginCreate a tunnel:
cloudflared tunnel create n8n-tunnelCreate the tunnel configuration file:
nano ~/.cloudflared/config.ymlAdd:
tunnel: your-tunnel-id-here
credentials-file: /root/.cloudflared/your-tunnel-id.json
ingress:
- hostname: your-domain.com
service: http://localhost:5678
- service: http_status:404Route your domain through the tunnel:
cloudflared tunnel route dns n8n-tunnel your-domain.comStart the tunnel as a system service:
sudo cloudflared service install
sudo systemctl start cloudflared
sudo systemctl enable cloudflaredYour n8n instance is now accessible at your domain via HTTPS with no reverse proxy configuration required. This is the setup BK Web Designs uses in production.
Step 5: Start n8n and Verify the Setup
Navigate to your n8n directory and start the containers:
cd /opt/n8n
docker compose --env-file .env up -dCheck that both containers started correctly:
docker compose psBoth the postgres and n8n services should show status Up. If either shows Exit or Restarting, check the logs:
docker compose logs n8n
docker compose logs postgresAccess your n8n instance at your domain. Complete the initial setup by creating your owner account. Verify that the instance URL shown in Settings matches your domain with HTTPS.
The 8 Most Common n8n Docker Setup Mistakes
Every mistake below has caused data loss or broken production setups in the n8n community.
DB_TYPE set to postgres instead of postgresdb causes a silent connection failure with a misleading error message. The correct value is exactly postgresdb.
Forgetting to persist the /home/node/.n8n volume means restarting the container destroys your encryption key metadata. Even with PostgreSQL handling your workflow data, n8n writes critical files to this directory. Always mount it as a named volume or a host path.
Losing the N8N_ENCRYPTION_KEY makes every stored credential permanently unrecoverable. n8n generates a new key on startup if none is found and your existing credentials cannot be decrypted with the new key. Store this key externally in a password manager immediately after setup.
Wrong directory ownership causes permission denied errors on startup. The /opt/n8n/data directory must be owned by user ID 1000. The /opt/n8n/postgres directory must be owned by user ID 999. Use chown to set these before first run.
Missing N8N_WEBHOOK_URL means webhook URLs generated inside n8n are incorrect. External services cannot reach them. Set this variable to your full HTTPS domain before creating any webhook-triggered workflow.
Using SQLite in production causes data loss under concurrent load. SQLite locks under multiple simultaneous webhook calls and can silently drop data. PostgreSQL is the correct database from the first day of production use.
Port conflict on 5678 prevents n8n from starting. Check whether another service is using the port with lsof -i :5678 before running docker compose.
Storing credentials in a plain-text .env file is a security risk in shared or multi-user environments. Use Docker secrets or n8n’s external secrets manager for production deployments.
Hosting Options and Expected Costs
| Provider | Spec | Monthly Cost | Notes |
|---|---|---|---|
| Hetzner CX22 | 4GB RAM, 2 vCPU | €5 to €7 | Best value, EU and US data centers |
| Hetzner CX32 | 8GB RAM, 4 vCPU | €12 to €15 | For 50+ active workflows with AI nodes |
| DigitalOcean Basic | 2GB RAM, 1 vCPU | $12 | Straightforward setup, good documentation |
| DigitalOcean Standard | 4GB RAM, 2 vCPU | $24 | Production comfortable |
| Railway | Managed containers | From $5 | No server management, less control |
Hetzner is the most frequently recommended VPS for n8n in the community. Production testing documented at n8nlogic.com used Hetzner CX42 with Docker 26.1.4 and Ubuntu 22.04 LTS. Note that Hetzner updated pricing effective April 1, 2026, so check current rates at hetzner.com/cloud before provisioning.
How BK Web Designs Runs n8n in Production
AI SaaS Client: n8n Self-Hosted Supporting 2x Demo Requests
An AI SaaS client needed automation infrastructure that could scale with their business without the execution limits of n8n Cloud constraining their workflow volume. We set up a self-hosted n8n instance on Hetzner using the Docker Compose plus Cloudflare Tunnel stack described in this guide.
The instance runs their complete automation stack including lead qualification, demo follow-up sequences, CRM synchronisation, and AI-powered email triage. No execution limits means workflows run as frequently as needed without additional cost. The infrastructure cost is approximately €12 per month. The automation work on this platform contributed to demo requests doubling and conversion reaching 4.2 percent within six weeks of deployment. The full story is in our AI SaaS case study.
Manufacturing Company: n8n Self-Hosted for CRM and Lead Routing
A B2B manufacturing client required automation that kept their CRM data and lead information within a controlled environment rather than passing through third-party cloud services. Self-hosted n8n was the correct solution.
We deployed n8n on a dedicated VPS with PostgreSQL and Cloudflare Tunnel. The instance handles all lead routing, follow-up automation, and CRM synchronisation for their business. The setup eliminated $300 per month in Zapier costs while giving the client unlimited executions for their growing workflow volume. The automation outcomes for this client including 43 leads in 90 days and cost per lead dropping from $340 to $147 are documented in our manufacturing case study.
BK WEB DESIGNS PERSPECTIVE
The n8n docker setup is the easy part. The hard part is what you do on day 31.
We have set up n8n in production more times than we can count. The initial deployment following the steps above reliably works. The problems appear later. A dependency update breaks a node. A Cloudflare certificate needs renewal. A workflow starts failing silently because an API the workflow calls changed its response format. A database starts growing and nobody notices until performance degrades.
Self-hosting is the right choice for businesses that need unlimited executions, data sovereignty, or cost control at scale. It is not the right choice for businesses that want zero infrastructure overhead. That second group should be on n8n Cloud.
If you are in the first group and want the cost benefit of self-hosting without the maintenance responsibility, we offer managed n8n setup and ongoing infrastructure maintenance. We configure the initial instance, handle updates, monitor uptime, and respond when something breaks. The setup is yours. The maintenance is ours.
Deep, Founder, BK Web Designs
FAQ: n8n Docker Setup
How much RAM does a VPS need to run n8n with Docker?
The minimum for testing and light production use is 2GB RAM with 1 to 2 vCPU. For 20 to 100 active workflows including AI agent nodes, 4GB RAM with 2 vCPU is the practical minimum. For heavy production with 100 plus workflows, concurrent executions, and AI model calls, use 8GB RAM with 4 vCPU. Hetzner CX22 at approximately €5 to €7 per month handles light production. Hetzner CX32 at €12 to €15 handles moderate production comfortably.
Should I use SQLite or PostgreSQL for n8n in production?
Always use PostgreSQL in production. SQLite is not safe for production use according to n8n’s official documentation. It can lock under concurrent webhook calls and silently drop data. The docker-compose.yml configuration in this guide uses PostgreSQL from the start. The performance and reliability difference is significant for any deployment handling more than a few simultaneous workflow executions.
What is the N8N_ENCRYPTION_KEY and what happens if I lose it?
The N8N_ENCRYPTION_KEY is used to encrypt every credential stored in n8n including API keys, OAuth tokens, and database passwords. If you lose this key, every stored credential becomes permanently unrecoverable. n8n generates a new key on startup if none is found, which means existing credentials cannot be decrypted. Store this key in a password manager immediately after setup and never rely on the .env file as your only copy.
Do I need Nginx to run n8n with Docker?
No, not if you use Cloudflare Tunnel for SSL. The official n8n Docker Compose guide uses Traefik as the reverse proxy and SSL handler. Cloudflare Tunnel is an alternative that eliminates the need for any reverse proxy by routing HTTPS traffic from Cloudflare’s network directly to your local n8n port without opening inbound server ports. For operators who are not server administrators, Cloudflare Tunnel is the simpler path to a production-ready HTTPS setup.
How do I update n8n in Docker?
Pull the latest n8n image and restart the containers. From your n8n directory run: docker compose pull followed by docker compose up -d. n8n releases a new minor version most weeks. The stable tag on Docker Hub tracks the latest stable release. Always check the n8n release notes for breaking changes before updating a production instance, particularly for major version increments.
What is the n8n docker setup cost including VPS and database?
A complete self-hosted n8n production setup costs $5 to $12 per month for the VPS depending on the provider and specification. The n8n software itself is free under the fair-code license. PostgreSQL is free. Cloudflare Tunnel is free for the tunnel functionality. The total monthly infrastructure cost for a light to moderate production instance is $5 to $15. Compare this to n8n Cloud Starter at €24 per month with a 2,500 execution limit. For businesses running more than 2,500 workflow executions per month, self-hosting saves money from the first month.
What should I do if n8n will not start after docker compose up?
Check the container logs first with docker compose logs n8n and docker compose logs postgres. The most common causes are: DB_TYPE set to postgres instead of postgresdb, wrong directory ownership on the data volume, a port conflict on 5678, or a missing environment variable in the .env file. Verify all environment variables are correctly set, confirm directory permissions with ls -la /opt/n8n, and check whether port 5678 is in use with lsof -i :5678.
Ready to Build a n8n System That Actually Works?
If you followed this guide and n8n is running on your VPS, you now have unlimited workflow executions at infrastructure cost only. The ongoing work is keeping the instance updated, monitoring uptime, and handling the occasional configuration issue when a dependency changes.
If you want the cost benefit of self-hosting without the maintenance responsibility, we set up and maintain n8n instances for clients. You get the infrastructure, we handle everything after the first deployment.
Get Your Free Audit — We review your current automation setup, recommend whether self-hosted or Cloud is the right fit for your volume, and give you a clear cost comparison. 24 hour response guaranteed.