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:
75
05-troubleshooting/docker/n8n-proxy-trust-x-forwarded-for.md
Normal file
75
05-troubleshooting/docker/n8n-proxy-trust-x-forwarded-for.md
Normal 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.
|
||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user