$npx -y skills add czlonkowski/n8n-skills --skill n8n-self-hostingDeploy a production self-hosted n8n end-to-end to a fresh Linux VM over SSH, using Docker Compose behind a Caddy reverse proxy with automatic HTTPS. Use whenever the user wants to self-host, install, set up, provision, or deploy n8n on their own server/VPS/box (Hetzner, DigitalOc
| 1 | # Deploying self-hosted n8n |
| 2 | |
| 3 | This skill takes a **fresh Linux VM** (Ubuntu/Debian, root or sudo SSH) to a **running, |
| 4 | HTTPS, production n8n** via Docker Compose behind **Caddy** (automatic Let's Encrypt TLS). |
| 5 | It is for **self-hosted n8n on Docker** — not n8n Cloud, and not for building workflows |
| 6 | (that's the rest of this pack). |
| 7 | |
| 8 | Two deployment modes. The architectures differ, so **pick the mode before doing anything**. |
| 9 | |
| 10 | You drive this end-to-end over SSH: preflight → install Docker → lay down the project → |
| 11 | generate secrets → launch → verify TLS → hand off. The template files live in `assets/`; |
| 12 | the per-mode and security depth live in the reference files named below. |
| 13 | |
| 14 | ## Rule 0 — choose the mode (ask the user) |
| 15 | |
| 16 | Do not guess. Ask, then commit to one: |
| 17 | |
| 18 | | | **Single / regular** | **Queue** | |
| 19 | |---|---|---| |
| 20 | | Processes | one n8n | main + N workers | |
| 21 | | Extra services | none (SQLite) | Redis (queue) + Postgres (DB) | |
| 22 | | Executes workflows | in the main process | on workers, in parallel | |
| 23 | | Good for | 1 user, light/moderate load, simplest ops | high volume, heavy/long executions, horizontal scale | |
| 24 | | Compose | `assets/docker-compose.single.yml` | `assets/docker-compose.queue.yml` | |
| 25 | | Deep dive | **`SINGLE_MODE.md`** | **`QUEUE_MODE.md`** | |
| 26 | |
| 27 | If unsure, start **single** — it's the simplest correct thing and covers most needs. Moving |
| 28 | to queue later means swapping the compose file and migrating SQLite→Postgres, so if the user |
| 29 | already expects real volume, start **queue**. |
| 30 | |
| 31 | ## Rule 1 — secret hygiene (non-negotiable) |
| 32 | |
| 33 | A misstep here leaks client credentials. Be diligent: |
| 34 | |
| 35 | 1. **Generate every secret fresh, on the target box.** Never copy an encryption key, DB |
| 36 | password, or `.env` from another n8n instance into this one. See `SECURITY.md` for the |
| 37 | `openssl` commands. |
| 38 | 2. **Secrets live only in `.env`** (mode 600), referenced by the compose as `${VAR}`. Never |
| 39 | inline a secret into `docker-compose.yml`, the Caddyfile, or anything you commit. |
| 40 | 3. **The `N8N_ENCRYPTION_KEY` is sacred.** It encrypts every stored credential. If it's lost |
| 41 | or changes, all saved credentials become undecryptable. Set it explicitly, and tell the |
| 42 | user to back it up **off the box**. Don't echo it into long-lived logs or chat history |
| 43 | beyond what's needed to hand it over. |
| 44 | 4. **Never expose internal services.** Only Caddy (80/443) is public. n8n (5678), Postgres |
| 45 | (5432), Redis (6379) stay on the private Docker network — the templates already omit their |
| 46 | host port mappings. Don't add them. |
| 47 | 5. **`.env` and Caddy's `caddy_data` volume (the issued certs + ACME account key) are not |
| 48 | artifacts to share.** If you're working inside a git repo, confirm `.env` is git-ignored |
| 49 | before any commit. |
| 50 | |
| 51 | ## Inputs to collect up front |
| 52 | |
| 53 | - **SSH target** — `user@host` and how you authenticate (key path or the user confirms the agent already has access). Root or a sudo user. |
| 54 | - **Domain** — the full hostname n8n will live at, e.g. `n8n.example.com` (→ `SUBDOMAIN=n8n`, `DOMAIN_NAME=example.com`). The user must control its DNS. |
| 55 | - **TLS email** — for Let's Encrypt (`SSL_EMAIL`). |
| 56 | - **Timezone** — IANA name for Schedule/Cron nodes (e.g. `Europe/Warsaw`), else `Etc/UTC`. |
| 57 | - **Mode** — single or queue (Rule 0). Queue → confirm the box has enough RAM (rough floor ~4 GB; each worker wants ~1–2 GB). |
| 58 | |
| 59 | ## The deploy flow |
| 60 | |
| 61 | Work through these in order. `SINGLE_MODE.md` / `QUEUE_MODE.md` give the mode-specific command |
| 62 | detail; `SECURITY.md` covers secret generation and hardening; `DAY2.md` covers update/backup/restore. |
| 63 | |
| 64 | ### 1. Preflight (the cheapest failure is the one you catch here) |
| 65 | - SSH in; confirm the OS is Debian/Ubuntu-like (`. /etc/os-release`). |
| 66 | - **DNS must already point at the box.** Compare the box's public IP (`curl -s ifconfig.me`) |
| 67 | with `dig +short <fqdn>` (run it from the box AND ideally your laptop). If they don't match, |
| 68 | **stop** — Caddy's ACME challenge will fail. Have the user create the A record, wait for it |
| 69 | to propagate, then continue. |
| 70 | - Ports **80 and 443** must be reachable from the internet. Check the host firewall AND any |
| 71 | cloud security group / network firewall |