swarm-bao-forge-publisher re-runs on container start and token writes
The publisher was a oneshot with RemainAfterExit=true, started only through `wantedBy = container@hive-forge.service`. Once it had run it stayed `active (exited)`, so a later container start made its start a no-op: a token re-minted without a host reboot or a unit change never reached the store. - RemainAfterExit is dropped, so each start runs the script again. - systemd.paths.swarm-bao-forge-publisher watches the token file in the container (PathChanged) and starts the publisher when the mint writes it, the same shape as swarm-secret-publish's path unit. - The code comment, secrets.md and credentials.md now name both triggers; forge-placement pins the missing RemainAfterExit and the path unit. Refs #4998
This commit is contained in:
parent
c45f7a5330
commit
2d2d7529fc
4 changed files with 41 additions and 6 deletions
|
|
@ -56,6 +56,9 @@ let
|
|||
# `forgeSecretPath` above.
|
||||
swarmControllerTokenPath = "/var/lib/forgejo/swarm-controller-token";
|
||||
|
||||
# The same file from the host, which is where its publisher reads and watches it.
|
||||
swarmControllerTokenHostPath = "/var/lib/nixos-containers/hive-forge${swarmControllerTokenPath}";
|
||||
|
||||
# Where `swarm-bao-forge-publisher` puts it: `controllerForgeTokenLeaf` in
|
||||
# ../swarm-bao.nix, under the KV mount.
|
||||
controllerTokenStorePath = "secret/swarm/controller/swarm-controller/forge/token";
|
||||
|
|
@ -1057,8 +1060,12 @@ in
|
|||
# It can only depend on the container being up, not on the in-container
|
||||
# oneshot that mints the token (containers run their own systemd instance,
|
||||
# invisible to this one by unit name), so it polls the same bounded way
|
||||
# `hive-forge-oidc-secret` does. `wantedBy` the container, so every
|
||||
# container start re-publishes whatever the mint unit left there.
|
||||
# `hive-forge-oidc-secret` does. It runs whenever the token can have
|
||||
# changed: each time the container starts (`wantedBy`), and each time the
|
||||
# file is written (`systemd.paths.swarm-bao-forge-publisher` below).
|
||||
#
|
||||
# ⚠️ No `RemainAfterExit`. A oneshot that stays `active (exited)` turns
|
||||
# every later start into a no-op, so neither trigger would run it again.
|
||||
#
|
||||
# Unconditional, like the in-container unit it publishes from: forge is a
|
||||
# swarm-wide singleton, so the token always gets minted and published,
|
||||
|
|
@ -1088,7 +1095,6 @@ in
|
|||
inherit (storeRetry) startLimitBurst startLimitIntervalSec;
|
||||
serviceConfig = storeRetry.serviceConfig // {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
SyslogIdentifier = "swarm-bao-forge-publisher";
|
||||
# Longer than the 120s bounded wait below. `DefaultTimeoutStartSec`
|
||||
# is 90s, so without this systemd kills the unit at 90 — before it
|
||||
|
|
@ -1115,7 +1121,7 @@ in
|
|||
''
|
||||
set -euo pipefail
|
||||
|
||||
src=${lib.escapeShellArg "/var/lib/nixos-containers/hive-forge${swarmControllerTokenPath}"}
|
||||
src=${lib.escapeShellArg swarmControllerTokenHostPath}
|
||||
|
||||
for _ in $(seq 1 60); do
|
||||
[ -s "$src" ] && break
|
||||
|
|
@ -1157,6 +1163,18 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
# Re-publish when the mint unit writes a token, which it can do without the
|
||||
# container restarting. The file is the event: the mint runs in the
|
||||
# container's own systemd, which this one cannot subscribe to.
|
||||
systemd.paths.swarm-bao-forge-publisher = {
|
||||
description = "watch the swarm-controller's forge token for a publish";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
pathConfig = {
|
||||
PathChanged = swarmControllerTokenHostPath;
|
||||
Unit = "swarm-bao-forge-publisher.service";
|
||||
};
|
||||
};
|
||||
|
||||
# Unused: nothing writes or reads this host path, and it may hold a copy of
|
||||
# the controller's forge token.
|
||||
systemd.tmpfiles.rules = [ "r /var/lib/hyperhive-forge/swarm-controller.token" ];
|
||||
|
|
|
|||
Loading…
Reference in a new issue