The other half of what #71 calls "absent, and worth deciding on separately". Both
are free here, and unlike read_only (tracked separately) both are verifiable
from the config without a deploy.
security_opt: ["no-new-privileges:true"] — blocks setuid escalation. No
service here execs a setuid binary. No cost, no verification burden beyond the
stack starting.
cap_drop: [ALL] — every service either already runs non-root or needs
nothing:
| service |
user |
port |
needs a capability? |
| prometheus |
65534 |
9090 |
no |
| alertmanager |
${RENDER_UID} |
9093 |
no |
| loki |
10001 |
3100 |
no |
| grafana |
472 + group_add |
3000 |
no |
| snmp-exporter |
${RENDER_UID} |
9116 |
no — outbound UDP/161 needs nothing |
| blackbox-exporter |
image nobody |
9115 |
no — blackbox.yaml defines only http_2xx, http_2xx_plain and tcp_connect, so there is no ICMP prober and no CAP_NET_RAW |
Every published port is above 1024 — Alloy's syslog listener is on 1514
precisely so it needs no NET_BIND_SERVICE, per the comment already in
compose.yaml — so no cap_add is needed anywhere.
Be honest in the comment about the marginal value: these already run non-root,
and a non-root process with no file capabilities has an empty effective set
already. cap_drop: ALL clears the bounding set, so a setuid-root binary
arriving in a future image bump still could not gain capabilities. Belt and
braces, worth the lines, but the comment should not imply it is load-bearing.
Not on alloy. privileged: true grants all capabilities regardless, so a
cap_drop: [ALL] line sitting next to it would read as protection and provide
none. This repository's editorial line is that a control which cannot act is
worse than no control (ups.rules.yaml:6, #63); writing one that can never
act would be the same mistake deliberately. Reducing Alloy's privilege is
tracked separately.
Found while doing #71 / #184.
The other half of what #71 calls "absent, and worth deciding on separately". Both
are free here, and unlike
read_only(tracked separately) both are verifiablefrom the config without a deploy.
security_opt: ["no-new-privileges:true"]— blocks setuid escalation. Noservice here execs a setuid binary. No cost, no verification burden beyond the
stack starting.
cap_drop: [ALL]— every service either already runs non-root or needsnothing:
${RENDER_UID}group_add${RENDER_UID}nobodyblackbox.yamldefines onlyhttp_2xx,http_2xx_plainandtcp_connect, so there is no ICMP prober and noCAP_NET_RAWEvery published port is above 1024 — Alloy's syslog listener is on 1514
precisely so it needs no
NET_BIND_SERVICE, per the comment already incompose.yaml— so nocap_addis needed anywhere.Be honest in the comment about the marginal value: these already run non-root,
and a non-root process with no file capabilities has an empty effective set
already.
cap_drop: ALLclears the bounding set, so a setuid-root binaryarriving in a future image bump still could not gain capabilities. Belt and
braces, worth the lines, but the comment should not imply it is load-bearing.
Not on
alloy.privileged: truegrants all capabilities regardless, so acap_drop: [ALL]line sitting next to it would read as protection and providenone. This repository's editorial line is that a control which cannot act is
worse than no control (
ups.rules.yaml:6, #63); writing one that can neveract would be the same mistake deliberately. Reducing Alloy's privilege is
tracked separately.
Found while doing #71 / #184.