fix(http): let operators name their proxy, and survive a bad TRUST_PROXY_HOPS

Forwarding headers were believed from any connection on a private address.
Behind Docker Desktop, OrbStack and docker-proxy every connection to a
published port arrives from the gateway, a private address, so a caller
reaching the port directly could again choose the client address that rate
limits, the audit log and sign-in notices record. TRUSTED_PROXY_CIDRS
(comma-separated CIDRs) now names the proxies: when set, only those peers may
report a client address. The private-range default stays when it is unset,
the boot log states the rule in force in one line, and the reverse-proxy
guide says what to set for a proxy on the same host, on a Docker network, or
on a public address (which, unlisted, puts all clients in one bucket).

An invalid TRUST_PROXY_HOPS threw on every request that resolved the client
address, so every route answered 500, the health probe included. It now
resolves no address, warns once, and is named at boot.
This commit is contained in:
Marc-André Bombeck committed 2026-10-25 17:44:31 +01:00
1 parent 0b830e6b02
commit d87718407e
10 files changed
+501 -38

No files matched your search

+6
View File
@@ -234,6 +234,12 @@ API_TOKEN_HMAC_KEY="REPLACE-WITH-OUTPUT-OF-openssl-rand-hex-32"
# refuse the headers, log one warning, and share one rate-limit bucket across
# all anonymous callers.
# TRUST_PROXY_HOPS="1"
# The addresses the reverse proxy connects from (comma-separated CIDRs). Set,
# only those connections may report the client's address; unset, any private
# address may, which behind Docker Desktop, OrbStack or docker-proxy includes
# every caller of the published port. Same host: 127.0.0.1/32,::1/128; Docker
# network: the proxy's subnet. See docs/self-hosting/reverse-proxy.md.
# TRUSTED_PROXY_CIDRS=""
# TRUST_CF_CONNECTING_IP=""