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";