Files
reverse-proxy/docs/architecture/decisions/022-health-check-scope.md
T
glm-5.1 161049a17d Add ADR-029/030, implementation tasks, and spec updates for admin socket removal
Security review #005 identified critical vulnerabilities in the Unix domain
socket admin API (C1 symlink race, C2 no auth, C3 info leak, W1-W7, S1-S6).
ADR-028 (already accepted) replaces the socket with an authenticated HTTP
admin API on the health check port. This commit adds the remaining spec work:

- ADR-029: Config file TOCTOU mitigation (mtime check on reload)
- ADR-030: Store cli_allow_wildcard_bind in ConfigReloadHandle for consistent
  reload validation
- Implementation tasks for the admin HTTP migration (fix/admin-http-api),
  TOCTOU fix (fix/config-reload-toctou), and wildcard flag fix
  (fix/wildcard-flag-reload)
- Updated review #005 status to resolved with per-finding disposition
- Resolved OQ-16: POST for state-changing admin endpoints, GET for read-only
- Updated all architecture docs to reference new ADRs, use admin_key_path
  instead of admin_socket_path, and reflect POST method for /admin/reload
2026-06-15 05:19:42 +00:00

2.3 KiB

ADR-022: Health Check Scope — Local Port and Admin HTTP Endpoint Only

Status

Accepted

Context

The implementation served a GET /health route on the main HTTPS listener that returned 200 OK regardless of the Host header. This route was evaluated before host-based routing, meaning any upstream application using /health for its own health checks would have those requests silently intercepted by the proxy and never reach the upstream (implementation review finding W5).

The architecture already specified a separate local health check port (9900, bound to 127.0.0.1 only) via ADR-013. The question was whether to keep the main-listener /health route alongside the dedicated port (and possibly make the path configurable), or to remove it entirely.

Decision

The main HTTPS listener does not serve a /health route. Health checking is handled exclusively by:

  1. Local health check port (default: 9900, bound to 127.0.0.1) — serves GET /health → 200 OK. This is the primary health check mechanism for container orchestration, load balancers, and monitoring systems.
  2. Admin HTTP endpoint (GET /admin/status with Bearer token) — returns process information including uptime and site count. See ADR-028.

The /health route is removed from the main listener entirely. No configurable path is needed because the route simply does not exist on the public listener.

Consequences

Positive:

  • No collision with upstream applications that use /health for their own health checks
  • The main listener's routing logic is simpler — all requests go through host-based routing, no special cases
  • Clear separation of concerns: the main listener proxies, the local port answers health checks
  • No configurable path needed — the problem disappears entirely

Negative:

  • External monitoring that needs to verify TLS is working must connect to the HTTPS port directly and check for a successful TLS handshake or a 404 response, rather than getting a 200 from /health. This is a minor inconvenience — any successful TLS response (even 404) confirms the proxy is serving TLS correctly.

References

  • ADR-013: Health check on separate local port
  • ADR-028: Authenticated HTTP admin API (admin socket replaced by HTTP endpoint)
  • OQ-08: Resolved by this ADR
  • Implementation review finding W5 (hardcoded /health path)