wiki: add n8n reverse proxy X-Forwarded-For trust fix article

Documents the N8N_PROXY_HOPS env var needed for n8n behind Caddy/Nginx
when N8N_TRUST_PROXY alone is insufficient in newer versions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 19:47:50 -04:00
parent 6dccc43d15
commit 0df5ace1a2
2 changed files with 76 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
# n8n Behind Reverse Proxy: X-Forwarded-For Trust Fix
## The Problem
When running n8n behind a reverse proxy (Caddy, Nginx, Traefik), the logs fill with:
```
ValidationError: The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default).
This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.
```
This means n8n's Express rate limiter sees every request as coming from the proxy's internal IP, not the real client. Rate limiting and audit logging both break.
## Why `N8N_TRUST_PROXY=true` Isn't Enough
Older n8n versions accepted `N8N_TRUST_PROXY=true` to trust proxy headers. Newer versions (1.x+) use Express's `trust proxy` setting, which requires knowing *how many* proxy hops to trust. Without `N8N_PROXY_HOPS`, Express ignores the `X-Forwarded-For` header entirely even if `N8N_TRUST_PROXY=true` is set.
## The Fix
Add `N8N_PROXY_HOPS=1` to your n8n environment:
### Docker Compose
```yaml
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
environment:
- N8N_HOST=n8n.example.com
- N8N_PROTOCOL=https
- N8N_TRUST_PROXY=true
- N8N_PROXY_HOPS=1 # <-- Add this
```
Set `N8N_PROXY_HOPS` to the number of reverse proxies between the client and n8n:
- **1** — single proxy (Caddy/Nginx directly in front of n8n)
- **2** — two proxies (e.g., Cloudflare → Caddy → n8n)
### Recreate the Container
```bash
cd /opt/n8n # or wherever your compose file lives
docker compose down
docker compose up -d
```
If you get a container name conflict:
```bash
docker rm -f n8n-n8n-1
docker compose up -d
```
## Verifying the Fix
Check the logs after restart:
```bash
docker logs --since 5m n8n-n8n-1 2>&1 | grep -i "forwarded\|proxy\|ValidationError"
```
If the fix worked, there should be zero `ValidationError` lines. A clean startup looks like:
```
n8n ready on ::, port 5678
Version: 2.14.2
Editor is now accessible via:
https://n8n.example.com
```
## Key Notes
- Keep `N8N_TRUST_PROXY=true` alongside `N8N_PROXY_HOPS` — both are needed.
- The `mount of type volume should not define bind option` warning from Docker Compose when using `:z` (SELinux) volume labels is cosmetic and can be ignored.
- If n8n reports "Last session crashed" after a `docker rm -f` recreation, this is expected — the old container was force-killed, so n8n sees it as a crash. It recovers automatically.

View File

@@ -49,6 +49,7 @@
* [Fail2ban & UFW Rule Bloat Cleanup](05-troubleshooting/networking/fail2ban-ufw-rule-bloat-cleanup.md) * [Fail2ban & UFW Rule Bloat Cleanup](05-troubleshooting/networking/fail2ban-ufw-rule-bloat-cleanup.md)
* [Custom Fail2ban Jail: Apache Directory Scanning](05-troubleshooting/security/apache-dirscan-fail2ban-jail.md) * [Custom Fail2ban Jail: Apache Directory Scanning](05-troubleshooting/security/apache-dirscan-fail2ban-jail.md)
* [Nextcloud AIO Unhealthy 20h After Nightly Update](05-troubleshooting/docker/nextcloud-aio-unhealthy-20h-stuck.md) * [Nextcloud AIO Unhealthy 20h After Nightly Update](05-troubleshooting/docker/nextcloud-aio-unhealthy-20h-stuck.md)
* [n8n Behind Reverse Proxy: X-Forwarded-For Trust Fix](05-troubleshooting/docker/n8n-proxy-trust-x-forwarded-for.md)
* [Docker & Caddy Recovery After Reboot (Fedora + SELinux)](05-troubleshooting/docker-caddy-selinux-post-reboot-recovery.md) * [Docker & Caddy Recovery After Reboot (Fedora + SELinux)](05-troubleshooting/docker-caddy-selinux-post-reboot-recovery.md)
* [ISP SNI Filtering with Caddy](05-troubleshooting/isp-sni-filtering-caddy.md) * [ISP SNI Filtering with Caddy](05-troubleshooting/isp-sni-filtering-caddy.md)
* [Obsidian Vault Recovery — Loading Cache Hang](05-troubleshooting/obsidian-cache-hang-recovery.md) * [Obsidian Vault Recovery — Loading Cache Hang](05-troubleshooting/obsidian-cache-hang-recovery.md)