Watch
0
0
Fork
You've already forked hyperhive
0

glue: hive-otel's ordering after authelia moves out of the otel module

The hive collector's secret-wait unit read deploy.authelia.enable to
order itself after authelia's container. That ordering is now set by
glue-hive-otel-authelia.nix, which restates the unit's own gate (otel's
`waits`). The rendered unit is unchanged.

The hive-otel module-eval fixture `hiveOtel` gains authelia, and a case
pins the edge with authelia here and its absence without.

Part of #3742.
This commit is contained in:
atlas 2026-10-13 10:35:25 +02:00 • committed by mara
commit 40ebd45c66
4 changed files with 64 additions and 5 deletions

View file

@ -32,6 +32,7 @@
./glue-controller-oidc-client.nix
./glue-forge-oidc-client.nix
./glue-grafana-oidc-client.nix
./glue-hive-otel-authelia.nix
./glue-hive-tls-bao-identity.nix
./glue-logs-auth-bao-identity.nix
./glue-matrix-ctl-bao-identity.nix

View file

@ -0,0 +1,40 @@
# Glue: where authelia runs on this host, the hive collector's wait for its
# client secret file is ordered after authelia's container, because the
# named file may be one authelia mints.
#
# ONE PAIRING PER FILE — the hive collector's secret-wait unit ← authelia's
# container, and nothing else. Deleting this leaves a wait that polls for the
# file without ordering against anything, which is what a host without
# authelia already gets.
#
# ⚠️ Gated on the unit existing, not only on authelia being here: setting
# `systemd.services.hive-otel-client-secret.after` on a host without the unit
# would define one with no ExecStart. The gate restates ./otel.nix's `waits`
# (a sender identity, and a secret file that is not the one the store fetch
# writes); a change to `waits` must change it here too.
{
lib,
config,
...
}:
let
hyperhiveCfg = config.services.hyperhive;
otel = hyperhiveCfg.otel;
autheliaMachine = hyperhiveCfg.swarm.authelia.machine;
# ./otel.nix: `senderAuth`, `hiveLeaf`, `fetches`, `fetchedSecretPath`.
senderAuth = otel.clientSecretFile != null && hyperhiveCfg.hiveName != null;
hiveLeaf =
hyperhiveCfg.deploy.bao.clientCertFile != null && hyperhiveCfg.deploy.bao.clientKeyFile != null;
fetchedSecretPath = "/var/lib/hive-otel-oidc/${hyperhiveCfg.swarm.authelia.hiveClientPrefix}${toString hyperhiveCfg.hiveName}.secret";
fetches = senderAuth && hiveLeaf && otel.clientSecretFile == fetchedSecretPath;
waits = senderAuth && !fetches;
in
{
config = lib.mkIf (hyperhiveCfg.deploy.authelia.enable && otel.enable && waits) {
systemd.services.hive-otel-client-secret = {
after = [ "container@${autheliaMachine}.service" ];
requires = [ "container@${autheliaMachine}.service" ];
};
};
}

View file

@ -340,6 +340,7 @@ in
fetches = senderAuth && hiveLeaf && otel.clientSecretFile == fetchedSecretPath;
# An operator-delivered file has no unit that restarts the collector
# once it lands, so the collector waits for it instead.
# ./glue-hive-otel-authelia.nix restates this gate.
waits = senderAuth && !fetches;
secretWaitUnit = "hive-otel-client-secret";
# Written by swarm-secret-publish on authelia's host. The nix half of
@ -752,11 +753,9 @@ in
# transaction and gates on it. Stating the order from both sides too
# would be one more thing to keep consistent for no added guarantee.
#
# When authelia runs on this host the named file may be one it mints.
# Elsewhere there is no local unit to order against — naming one that
# does not exist orders nothing, silently.
after = lib.optional deployCfg.authelia.enable "container@${autheliaCfg.machine}.service";
requires = lib.optional deployCfg.authelia.enable "container@${autheliaCfg.machine}.service";
# Where authelia runs on this host the named file may be one it mints;
# ./glue-hive-otel-authelia.nix orders this unit after its container
# and restates `waits`.
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;

View file

@ -25,9 +25,12 @@ let
# This hive's own collector, which is a HOST service — unlike the swarm
# tier's, which lives in a container and is read through `otelSettings`.
# The IdP is here too, with a hand-named secret file: the collector's wait
# for that file exists beside authelia's container.
hiveOtel = hive {
otel.enable = true;
otel.clientSecretFile = "/var/lib/hive-otel-oidc/client.secret";
deploy.authelia.enable = true;
};
# A hive holding its own store leaf, placed by hand, and naming no secret
@ -299,6 +302,22 @@ let
&& waitsFor hiveOtel
&& waitsFor baoWithHiveOtel;
}
{
# ../host-modules/glue-hive-otel-authelia.nix orders the wait after
# authelia's container. `hiveOtel` has the IdP; `baoWithHiveOtel` waits
# on the same kind of file without it, and must not name a container
# that is not there — `Requires=` on an absent unit fails the job.
name = "the hive collector's secret wait is ordered after authelia's container only where authelia runs here";
ok =
let
container = "container@${hiveOtel.services.hyperhive.swarm.authelia.machine}.service";
wait = machine: machine.systemd.services.hive-otel-client-secret;
in
builtins.elem container (wait hiveOtel).after
&& builtins.elem container (wait hiveOtel).requires
&& !(builtins.elem container (wait baoWithHiveOtel).after)
&& !(builtins.elem container (wait baoWithHiveOtel).requires);
}
];
in
runGroup "hive-otel" cases