n8n

Self-Host n8n in Docker: Production Setup Guide

Learn to self-host n8n in Docker with a production-ready setup: persistent volumes, Postgres, HTTPS, and updates. Deploy your own automation engine today.

S
Santhej Kallada
Founder, TaskifyLabs
Updated June 21, 2026
9 min read
Featured image for: Self-Host n8n in Docker: Production Setup Guide

Running n8n in Docker is the fastest, most reproducible way to self-host the open-source workflow automation tool on your own server. With one container, a persistent volume, and a reverse proxy, you get a private automation engine you fully control — no per-task billing, no execution caps, no vendor lock-in. This guide walks through a production-grade setup from a clean Linux box to a secured, HTTPS-enabled instance, plus the trade-offs you should weigh before you commit.

We deploy n8n this way for clients constantly, so the steps below reflect what actually survives contact with real workloads, not a toy docker run that falls over the first time the host reboots.

What is the fastest way to run n8n in Docker?

The fastest reliable way to run n8n in Docker is to pull the official n8nio/n8n image, mount a named volume for /home/node/.n8n so your credentials and workflows persist, set a few environment variables for host and timezone, and put the whole thing behind a reverse proxy for TLS. That gets you a self-hosted n8n instance you can reach over HTTPS in under fifteen minutes.

A bare smoke test is one command:

docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  docker.n8n.io/n8nio/n8n

Open http://localhost:5678, create the owner account, and you have a working editor. The -v n8n_data:/home/node/.n8n flag is the part most first-timers skip — without it, every workflow and saved credential evaporates the moment the container is recreated.

That command is fine for kicking the tires. It is not fine for production: it uses SQLite, has no encryption-key persistence guarantees across hosts, and exposes the port in plain HTTP. The rest of this guide fixes each of those.

Why self-host n8n instead of using n8n Cloud?

Choosing to self host n8n is mostly a question of control, cost shape, and data residency.

  • Cost predictability. Self-hosting on a small VPS is a flat monthly server bill regardless of how many workflow executions you run. Managed plans bill by executions or active workflows, which can spike unpredictably for high-volume automations. We break down the managed tiers in our guide to n8n Cloud pricing.
  • Data residency and privacy. Sensitive data — customer records, API keys, internal documents — never leaves infrastructure you own. For regulated industries this is often non-negotiable.
  • No execution ceilings. A self-hosted instance runs as many executions as your hardware allows. There is no artificial throttle.
  • Full feature access. The community edition unlocks the same node library and lets you install community nodes the managed product may restrict.

The trade-off is that you are now the ops team. You own backups, updates, TLS renewal, and uptime. If your team has no appetite for that, managed hosting is the honest choice. If you want the upside without the babysitting, that is exactly the kind of work our AI automation service handles for clients.

What do you need before you start the n8n Docker setup?

Before the first docker run, line up these prerequisites so the n8n docker setup does not stall halfway:

  • A Linux host (Ubuntu 22.04 LTS or Debian 12 is a safe default) with at least 1 vCPU and 2 GB RAM. n8n is light at rest but spikes during heavy executions.
  • Docker Engine and the Docker Compose plugin installed.
  • A domain or subdomain (for example n8n.yourcompany.com) with a DNS A record pointing at the server's public IP. You need this for valid HTTPS.
  • Ports 80 and 443 open in your firewall and reachable from the internet.

Install Docker quickly on Ubuntu:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# log out and back in so the group change takes effect
docker --version

Confirm the Compose plugin is present with docker compose version. If it prints a version, you are ready.

How do you run n8n in Docker with persistent data?

The single most important rule when you run n8n in Docker is: persist /home/node/.n8n. That directory holds the SQLite database, the encryption key, and saved binary data. Lose it and you lose every credential.

  1. Create a named Docker volume so the data lives outside the container lifecycle:

``bash docker volume create n8n_data ``

  1. Start the container with the volume attached and the host details set:

``bash docker run -d --restart unless-stopped \ --name n8n \ -p 5678:5678 \ -e N8N_HOST=n8n.yourcompany.com \ -e N8N_PROTOCOL=https \ -e WEBHOOK_URL=https://n8n.yourcompany.com/ \ -e GENERIC_TIMEZONE=America/New_York \ -v n8n_data:/home/node/.n8n \ docker.n8n.io/n8nio/n8n ``

  1. The --restart unless-stopped flag means n8n comes back automatically after a host reboot. The WEBHOOK_URL must be your public HTTPS address, or webhook-triggered workflows will register the wrong callback URL and silently fail.

Back up the volume regularly. A cron job that runs docker run --rm -v n8n_data:/data -v $(pwd):/backup alpine tar czf /backup/n8n-$(date +%F).tgz /data gives you a restorable snapshot.

What does a production n8n Docker Compose file look like?

For anything beyond a quick test, define the stack declaratively. A Compose file makes the n8n self hosted deployment reproducible and version-controllable. We pair n8n with PostgreSQL because SQLite struggles once you have many concurrent executions.

services:
  postgres:
    image: postgres:16
    restart: unless-stopped
    environment:
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=change_this_password
      - POSTGRES_DB=n8n
    volumes:
      - pg_data:/var/lib/postgresql/data

  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=change_this_password
      - N8N_HOST=n8n.yourcompany.com
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.yourcompany.com/
      - N8N_ENCRYPTION_KEY=set_a_long_random_string_here
      - GENERIC_TIMEZONE=America/New_York
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres

volumes:
  pg_data:
  n8n_data:

Bring it up with docker compose up -d. The N8N_ENCRYPTION_KEY is critical: set it explicitly so you can move the stack between hosts without orphaning your encrypted credentials. We go much deeper on the Postgres pairing and scaling options in our dedicated n8n Docker Compose guide.

How do you secure a self-hosted n8n instance with HTTPS?

Never expose n8n on plain HTTP. Put a reverse proxy in front to terminate TLS. Caddy is the lightest option because it provisions and renews Let's Encrypt certificates automatically.

A minimal Caddyfile:

n8n.yourcompany.com {
    reverse_proxy localhost:5678
}

Run Caddy as a second container or system service on the same host. With a valid DNS record pointing at your server, Caddy fetches a certificate on first request and your instance is live on https://n8n.yourcompany.com.

Beyond TLS, harden the instance:

  • Set owner credentials immediately. n8n's first-run setup creates an owner account; never leave it open.
  • Restrict the editor. If only your team needs the UI, firewall port 5678 to internal IPs and let webhooks flow through the proxy only.
  • Rotate the encryption key carefully. Changing N8N_ENCRYPTION_KEY after credentials exist makes them unreadable. Set it once, store it in a secrets manager.

How do you update n8n running in Docker?

Updating is one of the real advantages of the n8n docker approach — it is a pull-and-restart, not a migration project.

  1. Pull the newer image:

``bash docker compose pull n8n ``

  1. Recreate the container with the new image while keeping volumes intact:

``bash docker compose up -d ``

  1. Verify the version in the n8n UI footer, then confirm a couple of critical workflows still execute.

Pin to a specific tag (for example n8nio/n8n:1.65.0) in production rather than tracking latest. That way an update is a deliberate, tested act instead of a surprise the next time Docker pulls a fresh image. Always snapshot your Postgres database and the n8n_data volume before a major version jump, in case a breaking change requires a rollback.

What are common n8n Docker problems and how do you fix them?

A handful of issues account for most support questions we see around the n8n docker setup.

Webhooks return the wrong URL

If a webhook node registers http://localhost:5678 instead of your domain, you forgot to set WEBHOOK_URL (and usually N8N_HOST/N8N_PROTOCOL). Set all three to your public HTTPS address and restart.

Lost credentials after moving hosts

This is the encryption-key problem. When you migrate the n8n_data volume to a new host but n8n generates a new encryption key, every saved credential becomes undecryptable. Always carry over the same N8N_ENCRYPTION_KEY.

"Permission denied" on the volume

The official image runs as the node user (UID 1000). If you bind-mount a host directory instead of using a named volume, fix ownership with sudo chown -R 1000:1000 ./n8n-data. Named volumes avoid this class of problem entirely, which is why we prefer them.

Container exits immediately

Check docker logs n8n. The usual culprit is a Postgres connection that is not yet ready; depends_on starts Postgres first but does not wait for it to accept connections, so a restart: unless-stopped policy lets n8n retry until the database is up.

What can you build once n8n is self-hosted?

Once your instance is live, the value comes from what you automate. A self-hosted box removes execution limits, so high-volume jobs that would blow a managed quota run freely.

  • Lead-capture pipelines that route form submissions into a CRM and fire instant notifications to Slack or WhatsApp.
  • Scheduled data syncs between SaaS tools that lack a native integration — for example pushing rows from an Airtable base into a Postgres reporting database every hour.
  • Internal back-office jobs like nightly invoice exports, report generation, and cleanup tasks that nobody wants to run by hand.
  • AI-augmented workflows that call an LLM to classify, summarize, or draft — the foundation for connecting n8n to the Model Context Protocol via our n8n MCP integration walkthrough.

Because the instance is yours, you can also install community nodes that extend n8n with integrations the managed product does not ship, and run long, heavy executions that a metered plan would throttle. That headroom is the whole point of self-hosting: the engine scales with your hardware, not your invoice.

If you would rather start from proven patterns than a blank canvas, browse our library of ready-made n8n templates and import one directly into your new instance. New to the tool entirely? Our primer on what n8n is and how it works covers the fundamentals before you wire up anything complex.

Should you self-host n8n or pay someone to run it?

Self-hosting n8n in Docker is genuinely accessible — the steps above are not exotic. But "accessible" and "worth your time" are different questions.

If you run a handful of internal automations and someone on your team is comfortable with Docker, self-hosting is a great call: low cost, full control, and total privacy. The maintenance burden is real but modest — occasional updates, backups, and certificate renewal that Caddy mostly handles for you.

If automation is business-critical and downtime costs you revenue, the calculus shifts. You now need monitoring, alerting, a backup-restore drill you have actually tested, and someone on call when a workflow breaks at 2 a.m. That is an ops function, not a weekend project.

Self-hosting n8n in Docker hands you a private, unmetered automation engine for the price of a small server — and the setup is a one-evening job, not a migration epic. The discipline that separates a hobby instance from a dependable one is unglamorous: persist the data volume, pin the encryption key, run behind real TLS, and back up before every update. Get those four things right and your self-hosted n8n will quietly run thousands of executions a month without ever asking for your attention.

S
Written by
Founder, TaskifyLabs
Read more from Santhej

Questions

People also ask

For ops teams

Ready to ship in 14 days?

20-minute scoping call. Fixed-price quote on the call. Live software in 14 days.

Or read more for ops teams