n8n Docker Setup: Complete Guide to Self-Hosting n8n in Production (2026)

Deep J Deep J 11 min read
n8n Docker setup diagram showing docker-compose configuration with PostgreSQL database and Cloudflare Tunnel SSL
In This Article

Table of Contents

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 docker

Verify Docker is running:

docker --version
docker compose version

Both commands should return version numbers. If docker compose returns an error, install the plugin separately:

sudo apt-get install docker-compose-plugin

Step 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/postgres

The 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/.env

Add 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_York

The 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.yml

Paste 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_healthy

Critical 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.deb

Authenticate with your Cloudflare account:

cloudflared tunnel login

Create a tunnel:

cloudflared tunnel create n8n-tunnel

Create the tunnel configuration file:

nano ~/.cloudflared/config.yml

Add:

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:404

Route your domain through the tunnel:

cloudflared tunnel route dns n8n-tunnel your-domain.com

Start the tunnel as a system service:

sudo cloudflared service install
sudo systemctl start cloudflared
sudo systemctl enable cloudflared

Your 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 -d

Check that both containers started correctly:

docker compose ps

Both 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 postgres

Access 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

ProviderSpecMonthly CostNotes
Hetzner CX224GB RAM, 2 vCPU€5 to €7Best value, EU and US data centers
Hetzner CX328GB RAM, 4 vCPU€12 to €15For 50+ active workflows with AI nodes
DigitalOcean Basic2GB RAM, 1 vCPU$12Straightforward setup, good documentation
DigitalOcean Standard4GB RAM, 2 vCPU$24Production comfortable
RailwayManaged containersFrom $5No 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.

Free Website Audit Worth $600

Get a personalized expert review of your current website with actionable recommendations — plus our 10 Critical Checkpoints guide that's helped 600+ business owners choose the right agency and avoid costly mistakes.

Trusted by 600+ businesses worldwide

Not sure what your business needs?

Fill out our quick request form and get a free business & website audit plus a 30-minute strategy consultation — no obligation, no sales pitch. Let's figure out your next move together.

Facebook
X
LinkedIn
WhatsApp
Telegram
Email
Scroll to Top