# Glue: register the swarm's homeserver as an OIDC client wherever authelia # runs. # # ONE PAIRING PER FILE — matrix ← authelia, and nothing else. Deleting this # leaves a homeserver whose SSO login authelia has never heard of, and no # minted secret for swarm-secret-publish to put in the store. # # ⚠️ Gated on authelia being HERE, and NOT on this host running the # homeserver. A client is a row in THIS host's provider config, so it is # declared where that config is rendered; ./hive-matrix.nix's `config` hangs # off `deploy.matrix.enable`, which answers a question about a different host. # Same shape as ./glue-grafana-oidc-client.nix. # # Registered whether or not the swarm runs a homeserver: nothing in `swarm.*` # records that. The one swarm-level fact that rules a login out is a null # `gatewayHost`, which leaves no callback a browser can reach, so that alone # skips the client. { lib, config, ... }: let hyperhiveCfg = config.services.hyperhive; deployCfg = hyperhiveCfg.deploy; matrixCfg = hyperhiveCfg.swarm.matrix; in { config = lib.mkIf (deployCfg.authelia.enable && matrixCfg.sso.redirectUri != null) { # One declaration, two readers: the callback is the read-only option the # homeserver's own config renders, so it is spelled once. services.hyperhive.swarm.authelia.oidc.clients = [ { id = matrixCfg.sso.clientId; description = "HyperHive matrix"; redirectUris = [ matrixCfg.sso.redirectUri ]; # tuwunel authenticates at the token endpoint by putting the secret in # the POST body. Authelia enforces the *registered* method, and its # default is `client_secret_basic` — so without this the browser flow # completes, consent is granted, and the last hop fails with a 401 # that names neither the secret nor the redirect. tokenEndpointAuthMethod = "client_secret_post"; } ]; }; }