fix(swarm-otel): stop re-granting the journal group upstream already grants

nixpkgs' collector unit already sets SupplementaryGroups to systemd-journal
unconditionally, with a comment saying why. Systemd list options concatenate,
so this module's copy rendered ["systemd-journal" "systemd-journal"] and made
this a second owner of a fact upstream may later change.

The bind mount stays, since that half is genuinely ours.
This commit is contained in:
atlas 2026-08-24 17:27:47 +02:00
commit 012ab5bb37

View file

@ -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" ];
};
};
};