From 889a46729bb7b5eb8b7c44c1afadddd3b9f90f0a Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 7 Sep 2026 20:20:41 +0200 Subject: [PATCH] swarm: move both authelia packages to deploy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `package` (which authelia build runs in the container) and `bridgePackage` (which `swarm-authelia-bridge` build writes the users file) are both host decisions, so they join the `deploy.authelia` block that already holds `enable`, `usersFile` and the two host-side paths. Six readers, and one of them is why this commit touches a second module: `swarm-controller.nix` reads `autheliaCfg.package` for `SWARMCTL_AUTHELIA_BIN`. A per-module sweep never sees that — it is a cross-reference between two movers, and whichever landed second would have inherited a dangling alias. The alias itself stays: it still has three live uses for `url` and `bridgeUrl`. Two comments needed real edits rather than a rename: - The `deploy.authelia` header said "all three of these are the same kind of thing — a filesystem path". It is five options now and two are packages, so the sentence distinguishes the builds from the paths, and keeps "a hive that does not run it has nothing at any of those paths" scoped to the paths it is true of. - `module-eval.nix` said "Only `usersFile` has a rename entry", explaining that authelia's other slice-7 movers are `readOnly` and a rename module cannot contribute a definition to those. That reasoning is worth keeping, but the claim stopped being true one line above the two entries this commit adds. The fixture gains both old paths; no new case. `autheliaOldPath`'s existing arms already fail the eval if either shim goes missing. --- flake.nix | 2 +- nix/host-modules/deploy.nix | 8 +++ nix/host-modules/swarm-authelia.nix | 78 +++++++++++++-------------- nix/host-modules/swarm-controller.nix | 2 +- nix/module-eval.nix | 10 ++-- 5 files changed, 56 insertions(+), 44 deletions(-) diff --git a/flake.nix b/flake.nix index 2fbdd495..2d0b2f46 100644 --- a/flake.nix +++ b/flake.nix @@ -154,7 +154,7 @@ services.hyperhive.deploy.nats.authPackage = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.swarm-nats-auth; - services.hyperhive.swarm.authelia.bridgePackage = + services.hyperhive.deploy.authelia.bridgePackage = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.swarm-authelia-bridge; services.hyperhive.gateway.swaggerUiTheme = diff --git a/nix/host-modules/deploy.nix b/nix/host-modules/deploy.nix index 45d0836f..b1c36f90 100644 --- a/nix/host-modules/deploy.nix +++ b/nix/host-modules/deploy.nix @@ -373,6 +373,14 @@ in [ "services" "hyperhive" "swarm" "nats" "authPackage" ] [ "services" "hyperhive" "deploy" "nats" "authPackage" ] ) + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "authelia" "package" ] + [ "services" "hyperhive" "deploy" "authelia" "package" ] + ) + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "authelia" "bridgePackage" ] + [ "services" "hyperhive" "deploy" "authelia" "bridgePackage" ] + ) ]; # ⚠️ `deploy.forgejo` is declared in ./hive-ci.nix, not here, and it is the diff --git a/nix/host-modules/swarm-authelia.nix b/nix/host-modules/swarm-authelia.nix index 0c0e7e30..a2309257 100644 --- a/nix/host-modules/swarm-authelia.nix +++ b/nix/host-modules/swarm-authelia.nix @@ -320,22 +320,12 @@ let ''; in { - # `enable` moved to `services.hyperhive.deploy.authelia.enable` — see - # ./deploy.nix. Whether this host runs the swarm's SSO provider is a - # deployment decision; what stays here is what authelia IS, including - # `url` and the OIDC client registry every hive needs as a *client* - # whether or not it runs the container. + # `enable` and both packages moved to `services.hyperhive.deploy.authelia` + # — see ./deploy.nix. Whether this host runs the swarm's SSO provider, and + # which build it runs, are deployment decisions; what stays here is what + # authelia IS, including `url` and the OIDC client registry every hive needs + # as a *client* whether or not it runs the container. options.services.hyperhive.swarm.authelia = { - package = lib.mkOption { - type = lib.types.package; - default = pkgs.authelia; - defaultText = lib.literalExpression "pkgs.authelia"; - description = '' - authelia package to run in the container. Defaults to - nixpkgs's; override to pin a specific upstream. - ''; - }; - port = lib.mkOption { type = lib.types.port; default = 9091; @@ -699,17 +689,6 @@ in ''; }; - bridgePackage = lib.mkOption { - type = lib.types.package; - defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarm-authelia-bridge"; - description = '' - `swarm-authelia-bridge` package — the only process allowed to - write `usersFile`. Wired by default from this flake's own - package set (see `flake.nix`); override to run a different - build. - ''; - }; - bridgePort = lib.mkOption { type = lib.types.port; default = 9092; @@ -750,16 +729,37 @@ in # What stays above is what authelia IS to every hive: where it answers # (`url`), the OIDC register every service checks itself against, its port. - # What the host running the container decides is here, and all three of - # these are the same kind of thing — a filesystem path that only exists on - # the machine that runs `swarm-authelia`. A hive that does not run it has - # nothing at any of them. `enable` already lives in ./deploy.nix, which - # also carries the renames. + # What the host running the container decides is here — which two builds it + # runs, and three filesystem paths that only exist on the machine running + # `swarm-authelia`. A hive that does not run it has nothing at any of those + # paths. `enable` already lives in ./deploy.nix, which also carries the + # renames. # # ⚠️ `usersFile` is a path *inside* the container and still belongs here: # a path's scope is the scope of the filesystem it names, and that # filesystem is this host's container root. options.services.hyperhive.deploy.authelia = { + package = lib.mkOption { + type = lib.types.package; + default = pkgs.authelia; + defaultText = lib.literalExpression "pkgs.authelia"; + description = '' + authelia package to run in the container. Defaults to + nixpkgs's; override to pin a specific upstream. + ''; + }; + + bridgePackage = lib.mkOption { + type = lib.types.package; + defaultText = lib.literalExpression "hyperhive.packages.\${system}.swarm-authelia-bridge"; + description = '' + `swarm-authelia-bridge` package — the only process allowed to + write `usersFile`. Wired by default from this flake's own + package set (see `flake.nix`); override to run a different + build. + ''; + }; + usersFile = lib.mkOption { type = lib.types.str; default = "${stateDir}/users.yml"; @@ -1111,7 +1111,7 @@ in # password for the users file. Without it the container runs # authelia and cannot invoke it: the unit's ExecStart resolves # through the store path, and nothing puts the CLI on PATH. - environment.systemPackages = [ cfg.package ]; + environment.systemPackages = [ deployCfg.authelia.package ]; # This container shares the host netns, so its own # firewall.service would rewrite the HOST ruleset at every @@ -1140,16 +1140,16 @@ in wantedBy = [ "multi-user.target" ]; before = [ "${unitName}.service" ]; requiredBy = [ "${unitName}.service" ]; - # `cfg.package` is here for its CLI, not its daemon: the - # client secrets are minted with `authelia crypto hash - # generate`, which is the only way to produce a digest in + # `deployCfg.authelia.package` is here for its CLI, not its + # daemon: the client secrets are minted with `authelia crypto + # hash generate`, which is the only way to produce a digest in # the exact form authelia will later verify. path = [ pkgs.coreutils ] ++ lib.optionals oidcEnabled [ pkgs.openssl - cfg.package + deployCfg.authelia.package ]; serviceConfig = { Type = "oneshot"; @@ -1216,7 +1216,7 @@ in "${unitName}.service" ]; serviceConfig = { - ExecStart = "${cfg.bridgePackage}/bin/swarm-authelia-bridge"; + ExecStart = "${deployCfg.authelia.bridgePackage}/bin/swarm-authelia-bridge"; User = unitName; Group = unitName; Restart = "on-failure"; @@ -1235,7 +1235,7 @@ in # argon2 parameters baked into a hash have to match the # verifier's — same reasoning as `swarmctl`'s own # `SWARMCTL_AUTHELIA_BIN`. - SWARM_AUTHELIA_BRIDGE_AUTHELIA_BIN = "${cfg.package}/bin/authelia"; + SWARM_AUTHELIA_BRIDGE_AUTHELIA_BIN = "${deployCfg.authelia.package}/bin/authelia"; # By name through the gateway, not loopback. A loopback # literal encodes "authelia is in my netns" at the call site, # and authelia's OIDC endpoints are https-only in effect — @@ -1255,7 +1255,7 @@ in services.authelia.instances.${instance} = { enable = true; - package = cfg.package; + package = deployCfg.authelia.package; # Merged at RUNTIME alongside the nix-generated config, which # is the whole reason the client digests can exist at all: diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index 85d9bee6..c9a939e5 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -28,7 +28,7 @@ let autheliaEnv = lib.optionalAttrs deployCfg.authelia.enable { # The CONFIGURED authelia, not whatever is on PATH: the argon2 # parameters baked into a hash have to match the verifier's. - SWARMCTL_AUTHELIA_BIN = "${autheliaCfg.package}/bin/authelia"; + SWARMCTL_AUTHELIA_BIN = "${deployCfg.authelia.package}/bin/authelia"; SWARMCTL_AUTHELIA_USERS_FILE = deployCfg.authelia.hostUsersFile; }; diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 7e9dd190..71598d6a 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -124,9 +124,11 @@ let swarm.nats.authPackage = pkgs.emptyDirectory; }; - # Seventh split slice. Only `usersFile` has a rename entry: the other two - # movers are `readOnly`, and a rename module contributes a definition, which - # a read-only option refuses — see ./host-modules/deploy.nix. So the two arms + # Seventh split slice, plus slice 10's two authelia packages. Of slice 7's + # movers only `usersFile` has a rename entry — the other two are `readOnly`, + # and a rename module contributes a definition, which a read-only option + # refuses; see ./host-modules/deploy.nix. `package` and `bridgePackage` are + # ordinary options, so they do carry one. The two arms # below have different jobs. `usersFile` tests the rename; the nats one tests # that a reader repointed to the new namespace still renders the derived # path, which is the failure this slice could actually have shipped — seven @@ -135,6 +137,8 @@ let deploy.authelia.enable = true; deploy.nats.enable = true; swarm.authelia.usersFile = "/var/lib/test-authelia/users.yml"; + swarm.authelia.package = pkgs.emptyDirectory; + swarm.authelia.bridgePackage = pkgs.emptyDirectory; swarm.nats.autoGenerateCallout = false; swarm.nats.calloutUserPublicKey = "UTESTUSERPUBKEYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; swarm.nats.calloutIssuerPublicKey = "ATESTISSUERPUBKEYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";