From 6dccc43d151f06dccc20e50113ca1849a3fe3bd5 Mon Sep 17 00:00:00 2001 From: MajorLinux Date: Mon, 30 Mar 2026 15:08:17 -0400 Subject: [PATCH] Add n8n Docker update guide Covers version checking, pinned-tag update process, SQLite password reset, and why Arcane may not catch updates when the latest tag lags behind npm releases. Co-Authored-By: Claude Sonnet 4.6 --- .../services/updating-n8n-docker.md | 121 ++++++++++++++++++ SUMMARY.md | 1 + 2 files changed, 122 insertions(+) create mode 100644 02-selfhosting/services/updating-n8n-docker.md diff --git a/02-selfhosting/services/updating-n8n-docker.md b/02-selfhosting/services/updating-n8n-docker.md new file mode 100644 index 0000000..2f062ed --- /dev/null +++ b/02-selfhosting/services/updating-n8n-docker.md @@ -0,0 +1,121 @@ +--- +title: "Updating n8n Running in Docker" +domain: selfhosting +category: services +tags: [n8n, docker, update, self-hosting, automation] +status: published +created: 2026-03-30 +updated: 2026-03-30 +--- + +# Updating n8n Running in Docker + +n8n's in-app update notification checks against their npm release version, which often gets published before the `latest` Docker Hub tag is updated. This means you may see an update prompt in the UI even though `docker pull` reports the image as current. Pull a pinned version tag instead. + +## Check Current vs Latest Version + +```bash +# Check what's running +docker exec n8n-n8n-1 n8n --version + +# Check what npm (n8n's upstream) says is latest +docker exec n8n-n8n-1 npm show n8n version +``` + +If the versions differ, the Docker Hub `latest` tag hasn't caught up yet. Use the pinned version tag. + +## Get the Running Container's Config + +Before stopping anything, capture the full environment so you can recreate the container identically: + +```bash +docker inspect n8n-n8n-1 --format '{{json .Config.Env}}' +docker inspect n8n-n8n-1 --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}' +``` + +For MajorsHouse, the relevant env vars are: + +``` +N8N_EDITOR_BASE_URL=https://n8n.majorshouse.com/ +N8N_PORT=5678 +TZ=America/New_York +N8N_TRUST_PROXY=true +GENERIC_TIMEZONE=America/New_York +N8N_HOST=n8n.majorshouse.com +N8N_PROTOCOL=https +WEBHOOK_URL=https://n8n.majorshouse.com/ +``` + +Data volume: `n8n_n8n_data:/home/node/.n8n` + +## Perform the Update + +```bash +# 1. Pull the specific version (replace 2.14.2 with target version) +docker pull docker.n8n.io/n8nio/n8n:2.14.2 + +# 2. Stop and remove the old container +docker stop n8n-n8n-1 && docker rm n8n-n8n-1 + +# 3. Start fresh with the new image and same settings +docker run -d \ + --name n8n-n8n-1 \ + --restart unless-stopped \ + -p 5678:5678 \ + -v n8n_n8n_data:/home/node/.n8n \ + -e N8N_EDITOR_BASE_URL=https://n8n.majorshouse.com/ \ + -e N8N_PORT=5678 \ + -e TZ=America/New_York \ + -e N8N_TRUST_PROXY=true \ + -e GENERIC_TIMEZONE=America/New_York \ + -e N8N_HOST=n8n.majorshouse.com \ + -e N8N_PROTOCOL=https \ + -e WEBHOOK_URL=https://n8n.majorshouse.com/ \ + docker.n8n.io/n8nio/n8n:2.14.2 + +# 4. Verify +docker exec n8n-n8n-1 n8n --version +docker ps --filter name=n8n-n8n-1 --format '{{.Status}}' +``` + +No restart of Caddy or other services required. Workflows, credentials, and execution history are preserved in the data volume. + +## Reset a Forgotten Admin Password + +n8n uses SQLite at `/home/node/.n8n/database.sqlite` (mapped to `n8n_n8n_data` on the host). Use Python to generate a valid bcrypt hash and update it directly — do **not** use shell variable interpolation, as `$` characters in bcrypt hashes will be eaten. + +```bash +python3 -c " +import bcrypt, sqlite3 +pw = b'your-new-password' +h = bcrypt.hashpw(pw, bcrypt.gensalt(rounds=10)).decode() +db = sqlite3.connect('/var/lib/docker/volumes/n8n_n8n_data/_data/database.sqlite') +db.execute(\"UPDATE user SET password=? WHERE email='marcus@majorshouse.com'\", (h,)) +db.commit() +db.close() +db2 = sqlite3.connect('/var/lib/docker/volumes/n8n_n8n_data/_data/database.sqlite') +row = db2.execute(\"SELECT password FROM user WHERE email='marcus@majorshouse.com'\").fetchone() +print('Valid:', bcrypt.checkpw(pw, row[0].encode())) +" +``` + +`Valid: True` confirms the hash is correct. No container restart needed. + +## Why Arcane Doesn't Always Catch It + +[Arcane](https://getarcaneapp.com) watches Docker Hub for image digest changes. When n8n publishes a new release, there's often a delay before the `latest` tag on Docker Hub is updated to match. During that window: + +- n8n's in-app updater (checks npm) reports an update available +- `docker pull latest` and Arcane both report the image as current + +Once Docker Hub catches up, Arcane will notify normally. For immediate updates, use pinned version tags as shown above. + +## Troubleshooting + +**Password still rejected after update:** Shell variable interpolation (`$2b`, `$10`, etc.) silently truncates bcrypt hashes when passed as inline SQL strings. Always use the Python script approach above. + +**Container exits immediately after recreate:** Check `docker logs n8n-n8n-1`. Most commonly a missing env var or a volume permission issue. + +**Webhooks not firing after update:** Verify `N8N_TRUST_PROXY=true` is set. Without it, Caddy's `X-Forwarded-For` header causes n8n's rate limiter to drop webhook requests before parsing the body. + +**`npm show n8n version` returns old version:** npm registry cache inside the container. Run `docker exec n8n-n8n-1 npm show n8n version --no-cache` to force a fresh check. diff --git a/SUMMARY.md b/SUMMARY.md index dc0300d..a5c468e 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -24,6 +24,7 @@ * [Deploying Netdata to a New Server](02-selfhosting/monitoring/netdata-new-server-setup.md) * [Netdata SELinux AVC Denial Monitoring](02-selfhosting/monitoring/netdata-selinux-avc-chart.md) * [Netdata n8n Enriched Alert Emails](02-selfhosting/monitoring/netdata-n8n-enriched-alerts.md) + * [Updating n8n Running in Docker](02-selfhosting/services/updating-n8n-docker.md) * [Linux Server Hardening Checklist](02-selfhosting/security/linux-server-hardening-checklist.md) * [Standardizing unattended-upgrades with Ansible](02-selfhosting/security/ansible-unattended-upgrades-fleet.md) * [Fail2ban Custom Jail: Apache 404 Scanner Detection](02-selfhosting/security/fail2ban-apache-404-scanner-jail.md)