diff --git a/nix/host-modules/swarm-otel.nix b/nix/host-modules/swarm-otel.nix index 153a6d85..f87d9c40 100644 --- a/nix/host-modules/swarm-otel.nix +++ b/nix/host-modules/swarm-otel.nix @@ -684,10 +684,23 @@ in # The public hive CA, read-only — only when something in here # actually verifies a swarm-service name. // caTrust.bindMount - # The host's journal, read-only, and only when there is a log store to - # write to. Read-only is the whole security posture of this mount: the - # collector has no business writing to a journal, and a collector that - # cannot write cannot corrupt the record it is reporting on. + # The host's journal, read-only, and only when something will read it. + # Read-only is the whole security posture of this mount: the collector + # has no business writing to a journal, and one that cannot write + # cannot corrupt the record it is reporting on. + # + # The mount is the only half we supply. Journal files are + # `0640 root:systemd-journal` and the unit runs `DynamicUser`, so + # reading them needs that group — which upstream's own collector unit + # already grants unconditionally. Adding it here again is not + # harmless: systemd list options CONCATENATE, so a second copy renders + # `[ "systemd-journal" "systemd-journal" ]` and quietly becomes a + # second owner of a fact upstream may later change. + # + # It works across the mount because that gid is FIXED at 62 in + # nixpkgs' `ids.nix`. A per-host allocation would leave the host's + # ownership naming a different group inside the container, and the + # failure would be a receiver that starts cleanly and reads nothing. // lib.optionalAttrs collectLogs { ${hostJournalDir} = { hostPath = hostJournalDir; @@ -1079,18 +1092,6 @@ in # scrapes nothing published — the empty case is the shipped one. // lib.optionalAttrs (cfg.publishedScrapeTargets != { }) { LoadCredential = [ "${collectorCredentialId}:${collectorSecretInContainer}" ]; - } - # Journal files are `0640 root:systemd-journal`, and this unit runs - # with upstream's `DynamicUser = true` — so there is no stable uid to - # grant, and the group is the only way in. - # - # 🔑 That works across the bind mount because `systemd-journal` is - # gid **62**, FIXED in nixpkgs' `ids.nix` rather than allocated per - # host. A dynamically allocated gid would mean the host's ownership - # named a different group inside the container, and the failure - # would be a receiver that starts cleanly and reads nothing. - // lib.optionalAttrs collectLogs { - SupplementaryGroups = [ "systemd-journal" ]; }; }; };