From c92bb0dce77997e20985d76bc2c6572ffe16fe8e Mon Sep 17 00:00:00 2001 From: atlas Date: Thu, 24 Sep 2026 13:07:18 +0200 Subject: [PATCH] nix: order each swarm-bao secret reader after the policy unit writing its role The four readers (matrix-token, queue-agent, grafana-oidc, otel-oidc) log in against a cert-auth role that their own swarm-bao-*-policy unit writes. They were ordered after swarm-bao-pki and the store's container but not after that unit, so on an apply a reader could log in before its role existed and be refused by `allowed_common_names` until a retry landed after the role did. After= plus Wants= on the policy unit, never Requires=: the policy unit skips by ConditionPathExists once the bootstrap token is gone, and a skipped unit counts as done for ordering. --- nix/host-modules/glue-matrix-bao-token.nix | 10 +++++++++- nix/host-modules/glue-queue-agent-credential.nix | 10 +++++++++- nix/host-modules/swarm-grafana.nix | 10 +++++++++- nix/host-modules/swarm-otel.nix | 10 +++++++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/nix/host-modules/glue-matrix-bao-token.nix b/nix/host-modules/glue-matrix-bao-token.nix index 3c0afcb6..07c429ce 100644 --- a/nix/host-modules/glue-matrix-bao-token.nix +++ b/nix/host-modules/glue-matrix-bao-token.nix @@ -136,11 +136,19 @@ in # `Requires=` on an absent unit fails the job outright, so the ordering is # conditional even though the read is not: off-host there is nothing local # to wait for, and the timeout below is what bounds the attempt instead. + # + # The policy unit writes the role this reader logs in with. Ordering + # only: it skips once the bootstrap token is gone, and a skipped unit + # counts as done. after = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" "container@${baoCfg.machine}.service" + "swarm-bao-matrix-token-policy.service" + ]; + wants = lib.optionals baoDeploy.enable [ + "container@${baoCfg.machine}.service" + "swarm-bao-matrix-token-policy.service" ]; - wants = lib.optionals baoDeploy.enable [ "container@${baoCfg.machine}.service" ]; requires = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" ]; before = [ "container@${matrixMachine}.service" ]; wantedBy = [ "container@${matrixMachine}.service" ]; diff --git a/nix/host-modules/glue-queue-agent-credential.nix b/nix/host-modules/glue-queue-agent-credential.nix index 8fa2dc06..e2894e35 100644 --- a/nix/host-modules/glue-queue-agent-credential.nix +++ b/nix/host-modules/glue-queue-agent-credential.nix @@ -161,11 +161,19 @@ in # `Requires=` on an absent unit fails the job outright, so the ordering is # conditional even though the read is not: off-host there is nothing local # to wait for, and the timeout below is what bounds the attempt instead. + # + # The policy unit writes the role this reader logs in with. Ordering + # only: it skips once the bootstrap token is gone, and a skipped unit + # counts as done. after = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" "container@${baoCfg.machine}.service" + "swarm-bao-queue-agent-policy.service" + ]; + wants = lib.optionals baoDeploy.enable [ + "container@${baoCfg.machine}.service" + "swarm-bao-queue-agent-policy.service" ]; - wants = lib.optionals baoDeploy.enable [ "container@${baoCfg.machine}.service" ]; requires = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" ]; # Ordered before hive-c0re, so no agent container renders ahead of an # attempt at its credential. `Wants=`, not `Requires=`: a store this diff --git a/nix/host-modules/swarm-grafana.nix b/nix/host-modules/swarm-grafana.nix index 85e5a2d1..1ebac1f3 100644 --- a/nix/host-modules/swarm-grafana.nix +++ b/nix/host-modules/swarm-grafana.nix @@ -583,11 +583,19 @@ in # `Requires=` on an absent unit fails the job outright, so the ordering # is conditional even though the read is not: off-host there is nothing # local to wait for, and the timeout below bounds the attempt instead. + # + # The policy unit writes the role this reader logs in with. Ordering + # only: it skips once the bootstrap token is gone, and a skipped unit + # counts as done. after = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" "container@${baoCfg.machine}.service" + "swarm-bao-grafana-oidc-policy.service" + ]; + wants = lib.optionals baoDeploy.enable [ + "container@${baoCfg.machine}.service" + "swarm-bao-grafana-oidc-policy.service" ]; - wants = lib.optionals baoDeploy.enable [ "container@${baoCfg.machine}.service" ]; requires = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" ]; before = [ "container@${cfg.machine}.service" ]; wantedBy = [ diff --git a/nix/host-modules/swarm-otel.nix b/nix/host-modules/swarm-otel.nix index 0b5cc904..51605ba8 100644 --- a/nix/host-modules/swarm-otel.nix +++ b/nix/host-modules/swarm-otel.nix @@ -766,11 +766,19 @@ in # `Requires=` on an absent unit fails the job outright, so the ordering # is conditional even though the read is not: off-host there is nothing # local to wait for, and the timeout below bounds the attempt instead. + # + # The policy unit writes the role this reader logs in with. Ordering + # only: it skips once the bootstrap token is gone, and a skipped unit + # counts as done. after = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" "container@${baoCfg.machine}.service" + "swarm-bao-otel-oidc-policy.service" + ]; + wants = lib.optionals baoDeploy.enable [ + "container@${baoCfg.machine}.service" + "swarm-bao-otel-oidc-policy.service" ]; - wants = lib.optionals baoDeploy.enable [ "container@${baoCfg.machine}.service" ]; requires = lib.optionals baoDeploy.enable [ "swarm-bao-pki.service" ]; before = [ "container@${cfg.machine}.service" ]; wantedBy = [