diff --git a/nix/host-modules/hive-matrix.nix b/nix/host-modules/hive-matrix.nix index 713269c8..c6a6aa01 100644 --- a/nix/host-modules/hive-matrix.nix +++ b/nix/host-modules/hive-matrix.nix @@ -585,9 +585,9 @@ in # The homeserver's OIDC client secret, out of the swarm secret store under # matrix-ctl's leaf — the one route, wherever authelia runs. Same shape as - # ./swarm-grafana.nix's `swarm-bao-grafana-oidc`: a login that fails - # loudly, since a retry fixes every state it fails on, then a read that - # degrades quietly, since an absent value is "not published yet". + # ./swarm-bao.nix's `swarm-bao-forwarder-oidc`: the login and the read both + # fail loudly, and `storeRetry` retries until the publisher on authelia's + # host has written the secret, because tuwunel does not start without it. # # ⚠️ tuwunel requires the file to exist and be non-empty, and its # `LoadCredential` source must exist for the unit to start, so a host with @@ -669,12 +669,12 @@ in else echo "bao failed without writing a diagnostic." >&2 fi - exit 0 + exit 1 fi if [ -z "$secret" ]; then - echo "swarm-bao returned an empty ${storeSecretPath}; leaving the file as it is." >&2 - exit 0 + echo "swarm-bao returned an empty ${storeSecretPath}; the homeserver has no OIDC client secret yet." >&2 + exit 1 fi # Root-owned 0400: tuwunel runs under `DynamicUser`, so there is no diff --git a/nix/host-modules/swarm-nats.nix b/nix/host-modules/swarm-nats.nix index ef8e8b59..439f2d33 100644 --- a/nix/host-modules/swarm-nats.nix +++ b/nix/host-modules/swarm-nats.nix @@ -921,9 +921,10 @@ in # The responder's OIDC client secret, out of the swarm secret store under # the responder's own leaf — the one route, wherever authelia runs. Same - # shape as ./swarm-grafana.nix's `swarm-bao-grafana-oidc`: a login that - # fails loudly, since a retry fixes every state it fails on, then a read - # that degrades quietly, since an absent value is "not published yet". + # shape as ./swarm-bao.nix's `swarm-bao-forwarder-oidc`: the login and the + # read both fail loudly, and `storeRetry` retries until the publisher on + # authelia's host has written the secret, because the responder has no + # mode that runs without it. # # ⚠️ Without the secret the responder does not start (its `LoadCredential` # source is missing), and `auth_callout` with no responder refuses every @@ -1008,12 +1009,12 @@ in else echo "bao failed without writing a diagnostic." >&2 fi - exit 0 + exit 1 fi if [ -z "$secret" ]; then - echo "swarm-bao returned an empty ${storeSecretPath}; leaving the file as it is." >&2 - exit 0 + echo "swarm-bao returned an empty ${storeSecretPath}; the queue responder has no OIDC client secret yet." >&2 + exit 1 fi # Root-owned 0400: `LoadCredential` reads it as root before the diff --git a/nix/module-eval/matrix-core.nix b/nix/module-eval/matrix-core.nix index 0c028435..9a2ccac0 100644 --- a/nix/module-eval/matrix-core.nix +++ b/nix/module-eval/matrix-core.nix @@ -90,6 +90,8 @@ let && lib.hasInfix "bao kv get -field=value secret/swarm/services/tuwunel/oidc/client" u.script && lib.hasInfix "/var/lib/nixos-containers/hive-matrix/var/lib/tuwunel-oidc/tuwunel.secret" u.script && lib.hasInfix "refresh_consumer hive-matrix tuwunel.service" u.script + # An unpublished or empty secret fails the unit, so `storeRetry` retries it. + && !(lib.hasInfix "exit 0" u.script) && lib.elem "container@hive-matrix.service" u.before && !(s ? hive-matrix-oidc-secret); } diff --git a/nix/module-eval/nats-authelia.nix b/nix/module-eval/nats-authelia.nix index 6bd1c5d8..bf7924a4 100644 --- a/nix/module-eval/nats-authelia.nix +++ b/nix/module-eval/nats-authelia.nix @@ -209,6 +209,8 @@ let && lib.hasInfix "bao kv get -field=value secret/swarm/services/swarm-nats/oidc/client" fetch.script && lib.hasInfix "/var/lib/nixos-containers/swarm-nats/var/lib/swarm-nats-auth/oidc-client.secret" fetch.script && lib.hasInfix "refresh_consumer swarm-nats swarm-nats-auth.service" fetch.script + # An unpublished or empty secret fails the unit, so `storeRetry` retries it. + && !(lib.hasInfix "exit 0" fetch.script) && lib.elem "container@swarm-nats.service" fetch.before && !(lib.hasInfix "oidc-client" copy) && !(lib.hasInfix "authelia" copy);