AI for Work
How to Self-Host n8n: A Docker Compose Setup Guide

Image: Flickr / Wikimedia Commons / Unsplash

How to Self-Host n8n: A Docker Compose Setup Guide

Run n8n self-hosted for free with Docker Compose and HTTPS, plus the community edition limits and backup steps most tutorials skip.

September 16, 202645 minutes

n8n self-hosted lets you run unlimited automation workflows on your own server instead of paying per execution on n8n Cloud, using the same free Community edition n8n itself recommends for expert users. This guide covers the official n8n docker compose setup with HTTPS, what the community edition includes versus Enterprise, and the two mistakes that cause the most damage: losing the encryption key and skipping backups.

Best For

  • Developers and ops folks who want automation without SaaS lock-in or per-execution pricing
  • Teams hitting n8n Cloud's execution limits who want full control over their data
  • Self-hosters comfortable with a VPS, Docker, and basic DNS/SSL setup
  • Anyone comparing n8n self-hosted vs n8n Cloud before committing to either

Requirements

  • A VPS or server with at least 2GB RAM (Hetzner, DigitalOcean, Contabo, or similar)
  • Docker and Docker Compose installed on that server
  • A domain name with DNS access, to point a subdomain at your server
  • Basic command line comfort: SSH, editing text files, running commands

Why self-host n8n instead of paying for Cloud

n8n Cloud bills by plan tier and execution volume. Self-hosting the same platform on a $5 to $10 a month VPS removes that ceiling entirely, because the Community edition you run is the free, full-featured build of n8n, not a stripped-down trial.

The tradeoff is that n8n's own documentation is direct about who this is for: self-hosting requires setting up and securing servers, managing resources, and configuring the application yourself. n8n recommends self-hosting for expert users, and recommends n8n Cloud if you are not experienced at managing servers. Read that as a real filter, not boilerplate. Every step past this point assumes you are comfortable in a terminal.

Sources for this section

What the free Community edition includes, and where it stops

The Community edition is not a limited trial. It includes the full node and integration library, unlimited workflows and executions, custom JavaScript and Python code nodes, webhooks, cron scheduling, credential management, and error workflows. For a single builder or a small team, that is a complete production automation platform.

Where it stops is team governance, not automation capability. SSO through SAML or LDAP, external secrets stores, log streaming, environments, and fine-grained project roles all sit behind the Business and Enterprise plans. The sharing model is the limit teams hit first without realizing it: on Community, only the instance owner and whoever created a given workflow or credential can open it. A second teammate cannot open someone else's workflow inside the editor without a shared login.

Point a subdomain at your server

n8n only serves traffic over HTTPS once it is reachable from the internet, so DNS comes first. Create an A record on your domain pointing a subdomain (n8n.yourdomain.com, for example) at your server's IP address before you touch Docker.

  1. 1.Record type: A
  2. 2.Name: the subdomain you want, e.g. n8n
  3. 3.Destination: your server's public IP address

Create the project folder and the .env file

Everything for this deployment lives in one directory so it is easy to back up and move later.

Create a project directory and move into it:

mkdir n8n-compose && cd n8n-compose

Create a .env file with your domain, timezone, and a random encryption key. Generate the key once here and never let it change without a deliberate export/rotate process, covered later in this guide:

DOMAIN_NAME=yourdomain.com SUBDOMAIN=n8n GENERIC_TIMEZONE=America/New_York SSL_EMAIL=you@yourdomain.com N8N_ENCRYPTION_KEY=REPLACE_WITH_A_RANDOM_64_CHAR_STRING

Generate a random 64-character string for the encryption key with openssl, rather than leaving it blank and letting n8n auto-generate one you haven't recorded anywhere:

openssl rand -hex 32

Write the Docker Compose file

This stack runs two containers: n8n itself, and Traefik as a reverse proxy that requests and renews a free TLS certificate automatically. n8n's own hosting docs use this same Traefik pattern, and it is the path with the least manual certificate babysitting.

Create compose.yaml in the same directory:

services: traefik: image: traefik:v3.1 restart: unless-stopped command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.n8ncert.acme.tlschallenge=true" - "--certificatesresolvers.n8ncert.acme.email=${SSL_EMAIL}" - "--certificatesresolvers.n8ncert.acme.storage=/letsencrypt/acme.json" ports: - "80:80" - "443:443" volumes: - traefik_data:/letsencrypt - /var/run/docker.sock:/var/run/docker.sock:ro n8n: image: n8nio/n8n:latest restart: unless-stopped ports: - "127.0.0.1:5678:5678" labels: - traefik.enable=true - traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`) - traefik.http.routers.n8n.entrypoints=websecure - traefik.http.routers.n8n.tls.certresolver=n8ncert environment: - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME} - N8N_PROTOCOL=https - N8N_PORT=5678 - NODE_ENV=production - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/ - GENERIC_TIMEZONE=${GENERIC_TIMEZONE} - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} volumes: - n8n_data:/home/node/.n8n volumes: n8n_data: traefik_data:

The n8n_data volume holds n8n's SQLite database and its settings file, including the encryption key if you didn't set one explicitly. traefik_data holds the TLS certificate Traefik requests from Let's Encrypt. For a SQLite-free setup or Caddy instead of Traefik, n8n's own hosting repository has variants for both.

Start n8n and create your admin account

Bring the stack up in the background:

docker compose up -d

Give Traefik a minute to request the certificate, then confirm both containers are healthy:

docker compose ps

Visit https://n8n.yourdomain.com (your actual subdomain and domain). n8n prompts you to create an owner account on first load. Do this immediately; an unclaimed instance sitting open on the internet is the setup mistake that shows up most often in n8n's own community forum.

Protect the one file that can't be recovered

The encryption key you set in your .env file is what n8n uses to encrypt every credential in its database: API keys, OAuth tokens, database passwords, everything a workflow authenticates with. If that key is lost, those credentials do not become hard to recover. They become permanently unreadable. The workflow logic itself survives as plain JSON, but every stored connection has to be rebuilt by hand.

This is why setting N8N_ENCRYPTION_KEY explicitly in step 4 mattered, instead of leaving n8n to auto-generate one. An explicit key is one you can verify you actually have a copy of. Store that copy somewhere with a different failure mode than the server itself: a password manager, or a secrets manager like Vault or AWS Secrets Manager. A backup that lives on the same disk as the server it protects is not a backup.

Back up more than the database

A complete n8n backup has three parts, and most self-hosted setups only cover the first one.

When self-hosting isn't worth the operations overhead

Self-hosting stops making sense the moment the ops work costs you more than n8n Cloud would. If your team needs SSO on day one for compliance reasons, the Community edition fails that requirement immediately, and Business or Enterprise is a faster path than trying to bolt SSO on yourself. If nobody on your team wants to own patching, certificate renewal, and disaster recovery, that ongoing cost is real even though the software itself is free.

A useful gut check: if you would not know how to restore this instance from backup at 2am without help, either fix that before going further, or use n8n Cloud and let someone else carry that risk.

Before you flip this into production

Brian Weerasinghe

Founder and Editor

Brian Weerasinghe is the founder and editor of AI Eating The World, where he covers artificial intelligence, tech companies, layoffs, startups, and the future of work. His reporting focuses on how AI is transforming businesses, products, and the global workforce. He writes about major developments across the AI industry, from enterprise adoption and funding trends to the real-world impact of automation and emerging technologies.

Trusted AI LeaderTrusted AI LeaderTrusted AI LeaderTrusted AI Leader
Trusted by 10,000+ builders

The AI brief for builders, operators, and leaders

Follow the AI developments reshaping work and the world, with practical context for what to do next.

Free, no spam, unsubscribe anytime.