diff --git a/nix/host-modules/deploy.nix b/nix/host-modules/deploy.nix index 83d1e732..b50032e5 100644 --- a/nix/host-modules/deploy.nix +++ b/nix/host-modules/deploy.nix @@ -97,14 +97,15 @@ in [ "services" "hyperhive" "swarm" "authelia" "usersFile" ] [ "services" "hyperhive" "deploy" "authelia" "usersFile" ] ) - (lib.mkRenamedOptionModule - [ "services" "hyperhive" "swarm" "authelia" "hostClientSecretDir" ] - [ "services" "hyperhive" "deploy" "authelia" "hostClientSecretDir" ] - ) - (lib.mkRenamedOptionModule - [ "services" "hyperhive" "swarm" "authelia" "hostUsersFile" ] - [ "services" "hyperhive" "deploy" "authelia" "hostUsersFile" ] - ) + # `hostClientSecretDir` and `hostUsersFile` moved in the same commit and + # deliberately have NO entry here. A rename module contributes a + # *definition* to its target, and both are `readOnly`, which refuses a + # second one — so a shim for either makes every evaluation fail with + # "set multiple times", naming the option's own default as the rival + # definition. Nothing could have set them anyway: both are derived and + # read-only, so the shim's only possible customer is a reader of the old + # path, and that reader now gets "option does not exist" instead, which + # says the same thing sooner. (lib.mkRenamedOptionModule [ "services" "hyperhive" "swarm" "nats" "enable" ] [ "services" "hyperhive" "deploy" "nats" "enable" ] diff --git a/nix/module-eval.nix b/nix/module-eval.nix index e61db7b4..712587c7 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -118,6 +118,24 @@ let swarm.nats.calloutIssuerSeedFile = "/run/secrets/nats-issuer.seed"; }; + # 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 + # 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 + # of those reads went through an alias a path-shaped grep cannot see. + autheliaOldPath = hive { + deploy.authelia.enable = true; + deploy.nats.enable = true; + swarm.authelia.usersFile = "/var/lib/test-authelia/users.yml"; + swarm.nats.autoGenerateCallout = false; + swarm.nats.calloutUserPublicKey = "UTESTUSERPUBKEYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + swarm.nats.calloutIssuerPublicKey = "ATESTISSUERPUBKEYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + swarm.nats.calloutUserSeedFile = "/run/secrets/nats-user.seed"; + swarm.nats.calloutIssuerSeedFile = "/run/secrets/nats-issuer.seed"; + }; + controllerOldPath = hive { deploy.swarm-controller.enable = true; swarm.controller.socketPath = "/run/test-ctrl/ctrl.sock"; @@ -351,6 +369,20 @@ let rule: lib.hasInfix "/run/test-grafana-sock" rule ) grafanaOldPath.systemd.tmpfiles.rules; } + { + name = "a config written against the pre-rename authelia usersFile still reaches the bridge"; + ok = + autheliaOldPath.containers.swarm-authelia.config.systemd.services.swarm-authelia-bridge.environment.SWARM_AUTHELIA_BRIDGE_USERS_FILE + == "/var/lib/test-authelia/users.yml"; + } + { + # Not a rename test. `hostClientSecretDir` is `readOnly`, so the fixture + # cannot define it; what can break is a reader left pointing at the + # namespace it moved out of. Five modules read this through an + # `autheliaCfg` alias, where a path-shaped grep does not see it. + name = "a consumer of authelia's host client-secret dir renders it from the deploy namespace"; + ok = lib.hasInfix "/var/lib/nixos-containers/swarm-authelia/var/lib/authelia-swarm/oidc-clients/" autheliaOldPath.systemd.services.swarm-nats-auth-secrets.script; + } { # The gateway's per-name issuer choice. If this ever collapses to a # constant, every swarm-service vhost serves a certificate its CA