swarm-secret-publish: drop RemainAfterExit so the path unit re-runs it
swarm-secret-publish.service was Type=oneshot with RemainAfterExit=true. After its first successful run it stayed active (exited), so every later start from swarm-secret-publish.path (PathChanged on authelia's client secret dir) was a no-op: a secret minted or replaced after that first run never reached the store, and nothing logged it. Without RemainAfterExit the unit goes inactive after each run, so each PathChanged event starts a fresh publish. Same shape as swarm-bao-forge-publisher in hive-forge/default.nix. No unit requires, wants, orders after, binds to or is part of swarm-secret-publish.service, so nothing depended on it staying active. This also covers the first-boot race where the publisher runs before authelia's first mint: the mint writes the file, and the path unit now starts the publisher again. A module-eval case pins it: the path unit targets the service, the service is a oneshot, and RemainAfterExit is unset or false. Closes #5032
This commit is contained in:
parent
5658361096
commit
6982b2ec14
2 changed files with 16 additions and 1 deletions
|
|
@ -177,9 +177,10 @@ in
|
||||||
baoDeploy.package
|
baoDeploy.package
|
||||||
pkgs.coreutils
|
pkgs.coreutils
|
||||||
];
|
];
|
||||||
|
# ⚠️ No `RemainAfterExit`. A oneshot that stays `active (exited)` turns
|
||||||
|
# every later start from the path unit above into a no-op.
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
|
||||||
# Bounded here rather than left to systemd's default, so the number a
|
# Bounded here rather than left to systemd's default, so the number a
|
||||||
# boot waits on is in the file that waits. A sealed store answers on
|
# boot waits on is in the file that waits. A sealed store answers on
|
||||||
# the port and never answers the write.
|
# the port and never answers the write.
|
||||||
|
|
|
||||||
|
|
@ -379,6 +379,20 @@ let
|
||||||
&& !(m.systemd.services ? swarm-secret-publish)
|
&& !(m.systemd.services ? swarm-secret-publish)
|
||||||
&& !(m.systemd.paths ? swarm-secret-publish);
|
&& !(m.systemd.paths ? swarm-secret-publish);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# The path unit's start is a no-op while its target is `active (exited)`,
|
||||||
|
# so a secret minted after the first run would never be published.
|
||||||
|
# `Type` is read too, so a missing `serviceConfig` cannot pass the arm.
|
||||||
|
name = "the publisher's path unit starts a oneshot that does not remain active";
|
||||||
|
ok =
|
||||||
|
let
|
||||||
|
m = secretPublisherHere;
|
||||||
|
sc = m.systemd.services.swarm-secret-publish.serviceConfig;
|
||||||
|
in
|
||||||
|
m.systemd.paths.swarm-secret-publish.pathConfig.Unit == "swarm-secret-publish.service"
|
||||||
|
&& sc.Type == "oneshot"
|
||||||
|
&& !(sc.RemainAfterExit or false);
|
||||||
|
}
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
runGroup "secret-publisher" cases
|
runGroup "secret-publisher" cases
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue