Files
MajorWiki/05-troubleshooting/docker/n8n-proxy-trust-x-forwarded-for.md
MajorLinux 6592eb4fea wiki: audit fixes — broken links, wikilinks, frontmatter, stale content (66 files)
- Fixed 4 broken markdown links (bad relative paths in See Also sections)
- Corrected n8n port binding to 127.0.0.1:5678 (matches actual deployment)
- Updated SnapRAID article with actual majorhome paths (/majorRAID, disk1-3)
- Converted 67 Obsidian wikilinks to relative markdown links or plain text
- Added YAML frontmatter to 35 articles missing it entirely
- Completed frontmatter on 8 articles with missing fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:16:29 -04:00

2.6 KiB

title, domain, category, tags, status, created, updated
title domain category tags status created updated
n8n Behind Reverse Proxy: X-Forwarded-For Trust Fix troubleshooting docker
n8n
caddy
reverse-proxy
docker
express
published 2026-04-02 2026-04-02

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

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

cd /opt/n8n  # or wherever your compose file lives
docker compose down
docker compose up -d

If you get a container name conflict:

docker rm -f n8n-n8n-1
docker compose up -d

Verifying the Fix

Check the logs after restart:

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.