# Glue: register the swarm's collector as an OIDC client wherever authelia # runs. # # ONE PAIRING PER FILE — swarm-otel ← authelia, and nothing else. Deleting # this leaves a swarm whose collector is not a client authelia has ever heard # of, so no token it presents is ever accepted and authelia mints no secret # for the publisher to send on. # # ⚠️ Gated on authelia being HERE, and deliberately NOT on this host running # the collector. A client is a row in THIS host's provider config, so it can # only be declared where that config is rendered — and ./swarm-otel.nix's # whole `config` block hangs off `deploy.swarm-otel.enable`, so a swarm with # the collector and authelia on different hosts registered the client # nowhere at all. Same bug, same fix, as ./glue-grafana-oidc-client.nix one # module over — read that file's own comment for the property this one # shares with it. # # ⚠️ Registered whether or not the swarm has a collector, for the same # reason as Grafana's: nothing in `swarm.*` records that one exists, # `deploy.swarm-otel.enable` only answers "does THIS host run it". The cost # is one unused client and one unused minted secret in a swarm with no # collector — the same trade ./swarm-otel.nix already made for this exact # client when it dropped the published-scrape-target guard on registering it. { lib, config, ... }: let hyperhiveCfg = config.services.hyperhive; deployCfg = hyperhiveCfg.deploy; otelCfg = hyperhiveCfg.swarm.otel; in { config = lib.mkIf (hyperhiveCfg.enable && deployCfg.authelia.enable) { # One declaration, two readers: `clientId` and `audience` are read-only # options ./swarm-otel.nix derives from the scrape/push targets it owns, # so this file states neither formula a second time. services.hyperhive.swarm.authelia.oidc.clients = [ { id = otelCfg.clientId; description = "HyperHive swarm collector"; kind = "machine"; # Grants `authelia.bearer.authz`, without which the authz endpoint # refuses an otherwise valid token and blames the token rather than # the missing grant. bearerAuthz = true; audience = otelCfg.audience; # Stated rather than left on authelia's default, because the two # agreeing today is not the same as this being the required value: # authelia permits only basic / JWT methods for a confidential # client holding this scope, and enforces it in the startup # validator. tokenEndpointAuthMethod = "client_secret_basic"; } ]; }; }