diff --git a/infra/caddy/Caddyfile b/infra/caddy/Caddyfile index fc6b02bb..2c0c0757 100644 --- a/infra/caddy/Caddyfile +++ b/infra/caddy/Caddyfile @@ -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) {