fix(caddy): wrap actuator block in handle so it takes precedence over catch-all
Some checks failed
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / OCR Service Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / fail2ban Regex (pull_request) Has been cancelled
CI / Compose Bucket Idempotency (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / OCR Service Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / fail2ban Regex (push) Has been cancelled
CI / Compose Bucket Idempotency (push) Has been cancelled

Closes #512.

The previous `(block_actuator)` snippet emitted `respond @actuator 404`
at the top level of each archive vhost. But each vhost also has a
catch-all `handle { reverse_proxy ... }` that matches /actuator/*
too. Caddy's `handle` blocks are mutually exclusive — once one matches,
the request never reaches a top-level `respond`. So /actuator/health
was being proxied to the backend, which 302s to /login.

Wrap the actuator response in its own `handle /actuator/*` block.
Caddy sorts `handle` blocks by path specificity, so /actuator/* wins
over the catch-all and the 404 is actually returned.

Verified with `caddy validate` against the caddy:2 image.

Also unblocks the nightly.yml smoke test's `/actuator/health → 404`
assertion, which has been failing since the first staging deploy.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-11 17:12:09 +02:00
parent 5d2888e038
commit 2093fc0481

View File

@@ -31,8 +31,16 @@
# in application.yaml, /actuator/* is unreachable externally. The internal
# Prometheus scrape (future) talks to the backend directly on the docker
# network, not via Caddy.
@actuator path /actuator/*
respond @actuator 404
#
# Why a `handle` block and not a top-level `respond @matcher`: each archive
# vhost has a catch-all `handle { reverse_proxy ... }` that matches every
# path including /actuator/*, and Caddy's `handle` blocks are mutually
# exclusive. Without our own `handle /actuator/*` the catch-all wins, the
# request is proxied to the backend, and Spring Security 302s to /login
# instead of Caddy returning 404. See #512.
handle /actuator/* {
respond 404
}
}
(access_log) {