security: bind Caddy admin API to loopback, split metrics to :2020
The flagship Caddy ran its admin API on 0.0.0.0:2019, reachable by every container on the Docker network. The admin API can rewrite routes and proxy targets, so a journal/planner RCE could repoint traffic with no further auth. (The brouter-host Caddyfile already binds admin to localhost; the flagship didn't.) The admin endpoint also served Prometheus metrics (global `metrics` option → admin endpoint), and Prometheus scrapes caddy:2019 cross-container — so admin couldn't just move to loopback without breaking metrics. Split them: - admin localhost:2019 (loopback only). All reloads are in-container (`docker compose exec caddy caddy reload`) so they use this endpoint unaffected. - a dedicated `:2020` server exposes the read-only metrics handler; prometheus.yml now scrapes caddy:2020. Validated with `caddy validate` + `caddy adapt` against caddy:2: admin.listen=localhost:2019, srv on :2020 carries the metrics handler, the :443 site is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
55f8758c70
commit
d8fd4ff655
2 changed files with 16 additions and 3 deletions
|
|
@ -1,6 +1,17 @@
|
|||
{
|
||||
metrics
|
||||
admin 0.0.0.0:2019
|
||||
# Admin API on loopback only. It can reconfigure the proxy, so it must
|
||||
# not be reachable by other containers on the Docker network (a journal
|
||||
# / planner RCE could otherwise rewrite routes). Reloads run in-container
|
||||
# (`docker compose exec caddy caddy reload`) over this loopback endpoint,
|
||||
# matching infrastructure/brouter-host/Caddyfile.
|
||||
admin localhost:2019
|
||||
}
|
||||
|
||||
# Read-only Prometheus metrics on a dedicated network-reachable port,
|
||||
# split off the admin endpoint above so scraping doesn't require exposing
|
||||
# the admin API. Prometheus scrapes caddy:2020 (see prometheus.yml).
|
||||
:2020 {
|
||||
metrics /metrics
|
||||
}
|
||||
|
||||
(security_headers) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ scrape_configs:
|
|||
|
||||
- job_name: "caddy"
|
||||
static_configs:
|
||||
- targets: ["caddy:2019"]
|
||||
# Caddy's admin API is loopback-only; metrics are served on a
|
||||
# dedicated port (see infrastructure/caddy/Caddyfile).
|
||||
- targets: ["caddy:2020"]
|
||||
|
||||
# Self-monitoring. Prometheus did not scrape its own /metrics, so TSDB
|
||||
# health (compaction failures, WAL corruption, head series, retention
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue