#71 names read_only as absent and "worth deciding on separately". #184 took the
task and retention bounds and left this. It is separable for a specific reason:
cap_drop and no-new-privileges (tracked separately) are verifiable by reading
the config, whereas read_only is only verifiable from a running stack — a
missing tmpfs: entry is a crash loop that restart: unless-stopped retries
forever.
Per service, from reading the configs:
| service |
verdict |
snmp-exporter, blackbox-exporter |
trivially safe — config in, metrics out, nothing written |
prometheus |
safe — everything goes to the /prometheus volume, which stays writable |
alertmanager |
safe — same, /alertmanager |
loki |
safe, and anticipated: loki-config.yaml puts rule_path: /loki/rules-temp inside the data volume on purpose, with a comment saying so |
grafana |
needs a soak. Data, plugins, PNGs and CSVs land in /var/lib/grafana, but Grafana touches os.TempDir() for SQLite spill and some export paths. Probably fine with tmpfs: ["/tmp"], and "probably" is the problem — this is the one service whose breakage means no dashboard and no login |
alloy |
skip — read_only on a privileged container with /:/rootfs is performative, it can remount anything it likes |
Done when
Found while doing #71 / #184.
#71 names
read_onlyas absent and "worth deciding on separately". #184 took thetask and retention bounds and left this. It is separable for a specific reason:
cap_dropandno-new-privileges(tracked separately) are verifiable by readingthe config, whereas
read_onlyis only verifiable from a running stack — amissing
tmpfs:entry is a crash loop thatrestart: unless-stoppedretriesforever.
Per service, from reading the configs:
snmp-exporter,blackbox-exporterprometheus/prometheusvolume, which stays writablealertmanager/alertmanagerlokiloki-config.yamlputsrule_path: /loki/rules-tempinside the data volume on purpose, with a comment saying sografana/var/lib/grafana, but Grafana touchesos.TempDir()for SQLite spill and some export paths. Probably fine withtmpfs: ["/tmp"], and "probably" is the problem — this is the one service whose breakage means no dashboard and no loginalloyread_onlyon aprivilegedcontainer with/:/rootfsis performative, it can remount anything it likesDone when
read_only: trueon the five safe services, with anytmpfs:each needsgrafanaeither included with atmpfslist, or excluded with the reasonwritten down — after a real deploy plus: log in, load all five dashboards,
save an alert rule, write an annotation, run
make screenshotsunder thecaptureprofiledocs/security.mdhardening list updatedFound while doing #71 / #184.