diff --git a/docs/agent-lifecycle/persistence.md b/docs/agent-lifecycle/persistence.md index 93dc3be79..a35e7ac49 100644 --- a/docs/agent-lifecycle/persistence.md +++ b/docs/agent-lifecycle/persistence.md @@ -418,10 +418,7 @@ until the next collection. A drop-in written by an older hive-priv has no **Hyperhive's platform containers: warn only.** The forge, the matrix server and the swarm services (15 containers, declared by their own modules) run the same check as `hive-priv check-rootfs --warn-only `, from `ExecStartPre=` on -their own `container@` unit, through the symlink `/run/hive-rootfs-check` -that `hive-priv.nix` points at the current build, so a new hyperhive build does -not change the unit or restart the container. It evaluates every rule, logs each -violation +their own `container@` unit. It evaluates every rule, logs each violation as a warning, and exits 0, so the container starts either way. The line reads `rootfs check (warn-only): : ` with journald's warning priority. Strict refusal needs the live roots of all 15 to pass first, and the warnings diff --git a/nix/host-modules/hive-priv.nix b/nix/host-modules/hive-priv.nix index 2a5261474..3975e9266 100644 --- a/nix/host-modules/hive-priv.nix +++ b/nix/host-modules/hive-priv.nix @@ -9,21 +9,8 @@ }: let controllerCfg = config.services.hyperhive.deploy.hive-controller; - rootfsCheck = import ./lib/container-rootfs-check.nix { inherit config; }; in { - # The platform containers run their warn-only root check by this path - # (`lib/container-rootfs-check.nix`), so their units carry no store path. - # Declared outside the controller toggle below: a host that runs platform - # containers but no hive carries the check too. - imports = [ - { - systemd.tmpfiles.rules = [ - "L+ ${rootfsCheck.hivePriv} - - - - ${controllerCfg.package}/bin/hive-priv" - ]; - } - ]; - config = lib.mkIf config.services.hyperhive.deploy.hive-controller.enable { # The parent of every agent socket dir. hive-priv is its only writer # (`EnsureAgentSocketDir`), and its unit lists it in `ReadWritePaths`, diff --git a/nix/host-modules/lib/container-rootfs-check.nix b/nix/host-modules/lib/container-rootfs-check.nix index f125b405e..6f9382b43 100644 --- a/nix/host-modules/lib/container-rootfs-check.nix +++ b/nix/host-modules/lib/container-rootfs-check.nix @@ -23,19 +23,12 @@ # `container@` unit (`nixos-containers.nix`, the `mapAttrsToList` that # builds `container@${name}`), so a setting on that unit reaches that # container only. -# -# The binary is run through `hivePriv`, a path that does not change with the hyperhive -# build. `hive-priv.nix` points the symlink at the current package, so the -# unit text is the same across builds and a switch does not restart the -# container for it. -{ ... }: -rec { - hivePriv = "/run/hive-rootfs-check"; - +{ config }: +{ # Attributes for `systemd.services."container@"`. warnOnly = name: { serviceConfig.ExecStartPre = [ - "-${hivePriv} check-rootfs --warn-only ${name}" + "-${config.services.hyperhive.deploy.hive-controller.package}/bin/hive-priv check-rootfs --warn-only ${name}" ]; }; } diff --git a/nix/module-eval/core-toggle.nix b/nix/module-eval/core-toggle.nix index ea25aa283..a9b5a805f 100644 --- a/nix/module-eval/core-toggle.nix +++ b/nix/module-eval/core-toggle.nix @@ -1814,7 +1814,7 @@ let # their own unit, warn-only. Every container in these fixtures is one of # hyperhive's, so the names are read off the fixture: a container added # without the check breaks the list, which is the point. The unit's own - # pre-start script is not a `check-rootfs` entry, so the count is the check + # pre-start script is not a `hive-priv` entry, so the count is the check # alone. name = "every hyperhive container runs the root check warn-only from its own unit, and no hyperhive container is left out"; ok = @@ -1824,13 +1824,13 @@ let let pre = m.systemd.services."container@${name}".serviceConfig.ExecStartPre or [ ]; in - builtins.filter (lib.hasInfix "check-rootfs") ( + builtins.filter (lib.hasInfix "hive-priv") ( map (p: builtins.unsafeDiscardStringContext (toString p)) pre ); carries = m: name: checks m name == [ - "-/run/hive-rootfs-check check-rootfs --warn-only ${name}" + (builtins.unsafeDiscardStringContext "-${m.services.hyperhive.deploy.hive-controller.package}/bin/hive-priv check-rootfs --warn-only ${name}") ]; names = lib.attrNames allLocal.containers; in @@ -1853,13 +1853,6 @@ let && lib.all (carries allLocal) names && withCi.containers ? swarm-ci-runner && lib.all (carries withCi) (lib.attrNames withCi.containers) - # The line holds no store path, so a new hyperhive build leaves the - # unit text alone. Presence control: the lookup does find the line, - # and a line with a store path is caught by the same test. - && lib.all (n: !(lib.hasInfix "/nix/store" (lib.head (checks allLocal n)))) names - && lib.hasInfix "/nix/store" "-/nix/store/x-hyperhive/bin/hive-priv check-rootfs --warn-only x" - # The stable path is a link to the current package's hive-priv. - && lib.elem "L+ /run/hive-rootfs-check - - - - ${allLocal.services.hyperhive.deploy.hive-controller.package}/bin/hive-priv" allLocal.systemd.tmpfiles.rules # Control: a name with no unit finds nothing. && checks allLocal "swarm-nope" == [ ]; } @@ -1875,7 +1868,7 @@ let let hivePrivLines = m: name: - builtins.filter (lib.hasInfix "check-rootfs") ( + builtins.filter (lib.hasInfix "hive-priv") ( map (p: builtins.unsafeDiscardStringContext (toString p)) ( m.systemd.services."container@${name}".serviceConfig.ExecStartPre or [ ] ) @@ -1888,7 +1881,7 @@ let && lib.all ignored (allLines allLocal) && lib.all ignored (allLines withCi) # Control: the test discriminates, a line without the prefix is not ignored. - && !(ignored "/run/hive-rootfs-check check-rootfs --warn-only x"); + && !(ignored "/nix/store/x-hyperhive/bin/hive-priv check-rootfs --warn-only x"); } { # The operator's other containers are not hyperhive's to touch: a @@ -1900,7 +1893,7 @@ let let checks = name: - builtins.filter (lib.hasInfix "check-rootfs") ( + builtins.filter (lib.hasInfix "hive-priv") ( map (p: builtins.unsafeDiscardStringContext (toString p)) ( withForeignContainer.systemd.services."container@${name}".serviceConfig.ExecStartPre or [ ] ) diff --git a/nix/module-eval/swarm-services-switch.nix b/nix/module-eval/swarm-services-switch.nix index 2f52c9ce4..d372845e8 100644 --- a/nix/module-eval/swarm-services-switch.nix +++ b/nix/module-eval/swarm-services-switch.nix @@ -616,16 +616,7 @@ let && (s.hive-c0re.wantedBy or [ ]) == [ ] && !(swarmServicesOnly.systemd.sockets ? hive-c0re) && !(swarmServicesOnly.systemd.sockets ? hive-priv) - && !(s ? swarm-bao-queue-agent) - # The root check the platform containers carry runs through a link - # this host still declares, since no controller module does. Presence - # control: the unit and the rule are both found. - && lib.any ( - r: lib.hasPrefix "L+ /run/hive-rootfs-check " r - ) swarmServicesOnly.systemd.tmpfiles.rules - && lib.any ( - p: lib.hasPrefix "-/run/hive-rootfs-check check-rootfs --warn-only " (toString p) - ) s."container@swarm-bao".serviceConfig.ExecStartPre; + && !(s ? swarm-bao-queue-agent); } { # On a controller that runs none of them, so the link cannot come from