lb: trust the host Caddy's X-Forwarded-Proto #145

Merged
admin_emi merged 1 commit from fix/lb-forwarded-proto into dev 2026-08-01 16:25:16 +00:00
2 changed files with 39 additions and 0 deletions

View file

@ -13,6 +13,34 @@
{ {
auto_https off auto_https off
admin off admin off
# WITHOUT THIS, EVERY OAUTH REDIRECT URI THE BACKEND BUILDS IS http://.
#
# There are two Caddy hops in front of the app: the HOST Caddy terminates TLS
# and sets X-Forwarded-Proto: https, then proxies to 127.0.0.1:8137 over plain
# HTTP; this LB is the second hop. Caddy only preserves an incoming
# X-Forwarded-* header when the immediate peer is a TRUSTED proxy — otherwise
# it overwrites the header with the scheme of the connection it just received,
# which here is http. So the app saw http:// no matter how the user arrived.
#
# accounts/oauth.py:_redirect_uri builds the callback from x-forwarded-proto,
# and that URI must match what is registered in the provider's console.
# Discord tolerates the http:// form; GOOGLE REJECTS a non-HTTPS redirect URI
# for a web client outright, so Google sign-in could not work at all until
# this was fixed — independently of whether the credentials were configured.
#
# Measured on vps2 before the fix, same request to each hop:
# direct to web, XFP=https -> https://thermograph.org/api/v2/...
# through this LB, XFP=https -> http://thermograph.org/api/v2/...
#
# private_ranges covers 127.0.0.1/8 and the Docker bridge ranges, which is
# where the host Caddy reaches this container from. Nothing outside the box
# can connect here — the LB is bound to loopback precisely so it cannot be
# reached un-fronted (hazard #6, above) — so trusting the local peer does not
# widen anything: the only party that can set these headers is the host Caddy.
servers {
trusted_proxies static private_ranges
}
} }
:8137 { :8137 {

View file

@ -17,6 +17,17 @@
{ {
auto_https off auto_https off
admin off admin off
# Same reason as ./Caddyfile — see the long note there. Without it this second
# Caddy hop overwrites the host Caddy's X-Forwarded-Proto: https with http,
# and every OAuth redirect URI the backend builds comes out non-HTTPS, which
# Google rejects outright for a web client.
#
# Beta needs it as much as prod does, and arguably first: beta is where an
# OAuth provider change gets tested before it reaches thermograph.org.
servers {
trusted_proxies static private_ranges
}
} }
:8137 { :8137 {