diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index 3535284f..78c5a6f9 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -2652,6 +2652,22 @@ in RemainAfterExit = true; Restart = "on-failure"; RestartSec = 30; + # Runs only once the script above exits 0, which is when the + # granter may first configure `auth/oidc`; the viewer unit exits 0 + # without doing so before then, and nothing else re-runs it. A + # restart because it is `RemainAfterExit`, where a start is a + # no-op. + # + # `--no-block`: the viewer unit is ordered after this one, so a + # blocking restart waits on a job that cannot run until this unit + # is active, which it is not until this command returns. + # + # `postStart` can't carry the leading `-`, which is why this is + # `ExecStartPost` directly: without it, a viewer unit that is + # already running (or a `systemctl` that itself fails to enqueue + # the job) would mark the granter failed and trigger its own + # `Restart=on-failure` for a problem that isn't the granter's. + ExecStartPost = "-${pkgs.systemd}/bin/systemctl restart --no-block swarm-bao-operator-viewer-policy.service"; }; script = '' set -euo pipefail @@ -2717,17 +2733,6 @@ in token_ttl=15m \ token_max_ttl=15m ''; - # Runs only once the script above exits 0, which is when the granter - # may first configure `auth/oidc`; the viewer unit exits 0 without - # doing so before then, and nothing else re-runs it. A restart because - # it is `RemainAfterExit`, where a start is a no-op. - # - # `--no-block`: the viewer unit is ordered after this one, so a - # blocking restart waits on a job that cannot run until this unit is - # active, which it is not until this command returns. - postStart = '' - systemctl restart --no-block swarm-bao-operator-viewer-policy.service - ''; }; # The swarm's first grant, written from the HOST. Every API listener but diff --git a/nix/module-eval/bao-grants.nix b/nix/module-eval/bao-grants.nix index 9156f0c0..aa61b8a0 100644 --- a/nix/module-eval/bao-grants.nix +++ b/nix/module-eval/bao-grants.nix @@ -1492,14 +1492,18 @@ let # success restarts that unit: a restart since the unit is # `RemainAfterExit`, `--no-block` since it is ordered after the granter. # The ordering is one-way, so the viewer's retries never reach back. - name = "a successful granter step restarts the viewer unit without blocking"; + # `ExecStartPost` directly, not `postStart` (which can't carry a + # leading `-`), and the `-` is load-bearing: a failed enqueue must not + # mark the granter itself failed. + name = "a successful granter step restarts the viewer unit without blocking, and the enqueue can't fail the granter"; ok = let s = baoGrantHere.systemd.services; g = s.swarm-bao-granter-role; v = s.swarm-bao-operator-viewer-policy; in - lib.hasInfix "systemctl restart --no-block swarm-bao-operator-viewer-policy.service" g.postStart + lib.hasPrefix "-" g.serviceConfig.ExecStartPost + && lib.hasInfix "systemctl restart --no-block swarm-bao-operator-viewer-policy.service" g.serviceConfig.ExecStartPost && lib.elem "swarm-bao-granter-role.service" v.after && !(lib.elem "swarm-bao-operator-viewer-policy.service" g.after) && !(v ? postStart && lib.hasInfix "swarm-bao-granter-role" v.postStart);