You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Give the observability containers least privilege #443
Two observability containers can reach the Docker socket, and the Postgres exporter holds the application's full database URL. A bug in any of them would give much more than monitoring needs: the Docker socket means root on the host, and the database URL means full read and write on application data.
Severity: Low (needs a bug in a monitoring container first)
Area:docker-compose.observability.yml
Source: security review of 2026-10-06, finding L17
Where
Alloy mounts the socket: docker-compose.observability.yml:26 (/var/run/docker.sock:/var/run/docker.sock:ro). :ro does not limit the Docker API.
cAdvisor mounts all of /var/run: docker-compose.observability.yml:67.
postgres-exporter uses the application URL: docker-compose.observability.yml:248 (DATA_SOURCE_NAME: ${DATABASE_URL}).
The compose comment near :62-64 calls these mounts read-only and safe, and cites docs/observability.md, which does not exist.
Fix plan
Add a Docker socket proxy (for example tecnativa/docker-socket-proxy, pinned by digest like the other images) that allows only the read endpoints Alloy and cAdvisor use (containers, info). Point both at it, and remove their socket mounts.
Create a pg_monitor login role for the exporter in a migration or the deploy setup, and give the exporter its own POSTGRES_EXPORTER_DSN env var.
Correct the compose comment and remove the dead docs/observability.md reference.
Acceptance criteria
No observability container mounts /var/run/docker.sock or /var/run.
Container metrics and logs still arrive in Grafana.
postgres-exporter connects as a pg_monitor role, not the application role, and its metrics still arrive.
Verify
docker compose -f docker-compose.observability.yml config shows no socket mounts and the new DSN.
On the server: Grafana dashboards for containers and Postgres still update after deploy.
Code is live (73e5bd972): Alloy reads the Docker API through docker-socket-proxy (GET only), and node-exporter no longer sees the host socket. postgres-exporter prefers POSTGRES_EXPORTER_DSN.
Left before closing (maintainer): create a pg_monitor login role on the DigitalOcean cluster and set POSTGRES_EXPORTER_DSN in .env.observability. Keep DATABASE_URL there until a follow-up moves the deploy check.
Activity
fix(ops): run prod jobs only from main and narrow monitoring access
docs(hocuspocus): sync server docs with the 9 October fixes
docs(repo): record the 9 Oct security and email batch in the changelo…
HMarzban commentedon Oct 9, 2026
Code is live (
73e5bd972): Alloy reads the Docker API throughdocker-socket-proxy(GET only), and node-exporter no longer sees the host socket.postgres-exporterprefersPOSTGRES_EXPORTER_DSN.Left before closing (maintainer): create a
pg_monitorlogin role on the DigitalOcean cluster and setPOSTGRES_EXPORTER_DSNin.env.observability. KeepDATABASE_URLthere until a follow-up moves the deploy check.