Fix Authelia protection being dead code — reverse_proxy ran before the auth check

Both Caddy site block generators (the shared configure_caddy_for_service
helper, and asterisk-digital-ocean.sh's own inline template) wrote
reverse_proxy before the forward_auth/import authelia block. Caddy
doesn't reorder repeats of the same directive within a block — forward_auth
and reverse_proxy are the same directive family internally, so they run in
the order written. With reverse_proxy first, it handled and terminated
every request immediately; the auth check written after it never ran at
all. Full bypass on every domain using either generator with Authelia
protection, regardless of how correct the Authelia access_control rules
themselves were — confirmed live against a config that was otherwise
completely correct (default_policy: deny, explicit wildcard rule covering
the affected domain).

Affects every service that's ever passed `import authelia` or a
forward_auth block through configure_caddy_for_service (asterisk.sh,
wolf-pair.sh, and any future caller), plus asterisk-digital-ocean.sh's
own site block.

Moved the auth block before reverse_proxy in both generators.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015X1jRGHwrvovz2qkhKfDZi
This commit is contained in:
Claude
2026-07-20 19:29:26 +00:00
parent 104fd26b6d
commit 861b4478a8
3 changed files with 30 additions and 2 deletions
+14
View File
@@ -159,6 +159,20 @@ reloads Caddy. No-ops silently if Caddy isn't installed. The fourth argument
is an optional string inserted verbatim inside the Caddy site block (use it is an optional string inserted verbatim inside the Caddy site block (use it
for `import authelia` or custom matchers). for `import authelia` or custom matchers).
The function places that block **before** `reverse_proxy` in the generated
site block — don't reorder this. `forward_auth` (what `import authelia`
expands to) is the same directive family as `reverse_proxy` internally, and
Caddy doesn't reorder repeats of the same directive within a block; it runs
them in the order they're written. `reverse_proxy` written first would
handle and terminate every request immediately, making an auth check
written after it dead code that never runs — full bypass regardless of what
the auth server's own access-control rules say. Confirmed live: this was
the actual cause of a "Caddy proxies fine but Authelia never prompts for
login" bug, on a site block that otherwise looked completely correct. If a
service builds its own site block instead of using this helper (e.g.
`services/asterisk-digital-ocean.sh` does, deliberately, see its own
comment for why), put its auth block first there too.
Sets two out-params (not `local` — read them after the call returns) so the Sets two out-params (not `local` — read them after the call returns) so the
caller can tell whether Caddy actually ended up fronting the service: caller can tell whether Caddy actually ended up fronting the service:
+8 -1
View File
@@ -573,6 +573,14 @@ configure_caddy_for_service() {
# $SERVICE_NAME # $SERVICE_NAME
${SERVICE_DOMAIN} { ${SERVICE_DOMAIN} {
# Auth (if any) must come before reverse_proxy — forward_auth is the
# same directive family as reverse_proxy internally, and Caddy doesn't
# reorder repeats of the same directive within a block; it runs them in
# the order they're written. With reverse_proxy first, it would handle
# and terminate every request immediately, so an auth check written
# after it would be dead code that never runs — full bypass regardless
# of what the auth server's own rules say.
${EXTRA_CONFIG}
reverse_proxy ${_BLOCK_UPSTREAM} reverse_proxy ${_BLOCK_UPSTREAM}
# Security headers # Security headers
@@ -588,7 +596,6 @@ ${SERVICE_DOMAIN} {
output file /var/log/caddy/${SERVICE_DOMAIN}.log output file /var/log/caddy/${SERVICE_DOMAIN}.log
format json format json
} }
${EXTRA_CONFIG}
} }
CADDY_BLOCK CADDY_BLOCK
)" )"
+8 -1
View File
@@ -628,6 +628,14 @@ ENV
# Asterisk Web Admin # Asterisk Web Admin
${DOMAIN_NAME} { ${DOMAIN_NAME} {
# Auth (if any) must come before reverse_proxy — forward_auth is the
# same directive family as reverse_proxy internally, and Caddy doesn't
# reorder repeats of the same directive within a block; it runs them in
# the order they're written. With reverse_proxy first, it would handle
# and terminate every request immediately, so an auth check written
# after it would be dead code that never runs — full bypass regardless
# of what the auth server's own rules say.
${EXTRA_BLOCK}
reverse_proxy ${_PROXY_TARGET} reverse_proxy ${_PROXY_TARGET}
header { header {
@@ -641,7 +649,6 @@ ${DOMAIN_NAME} {
output file /var/log/caddy/${DOMAIN_NAME}.log output file /var/log/caddy/${DOMAIN_NAME}.log
format json format json
} }
${EXTRA_BLOCK}
} }
CADDY_BLOCK CADDY_BLOCK
)" )"