# Glue: register the swarm's Grafana as an OIDC client wherever authelia runs. # # ONE PAIRING PER FILE — grafana ← authelia, and nothing else. Deleting this # leaves a swarm whose metrics UI is not a client authelia has ever heard of, so # no login against it can complete and nothing minted its secret either. # # ⚠️ Gated on authelia being HERE, and deliberately NOT on this host running # Grafana. A client is a row in THIS host's provider config, so it can only be # declared where that config is rendered — and ./swarm-grafana.nix's whole # `config` block hangs off `deploy.grafana.enable`, so a swarm with Grafana and # authelia on different hosts registered the client nowhere at all. # ./hive-forge/default.nix is already on the right side of that line: its module # is gated on `hyperhive.enable` and only the registration asks about authelia. # This file puts Grafana there without moving the rest of its module. # # ⚠️ Registered whether or not the swarm has a Grafana, because nothing in # `swarm.*` records that — `deploy.grafana.enable` answers "does THIS host run # it", and a swarm-wide answer does not exist. The cost is one unused client # and one unused minted secret in a swarm with no metrics UI. The alternative # was a new swarm-wide option an operator must set before a split deployment # works, which leaves the reported failure in place for everyone who does not # know to set it. ./swarm-otel.nix made the same call for its own client when it # dropped the published-scrape-target guard: a client that may go unused beats a # guard that reads as done and renders nothing. { lib, config, ... }: let hyperhiveCfg = config.services.hyperhive; deployCfg = hyperhiveCfg.deploy; grafanaCfg = hyperhiveCfg.swarm.grafana; in { config = lib.mkIf (hyperhiveCfg.enable && deployCfg.authelia.enable) { # One declaration, two readers. Grafana's callback URL is format-locked to # its own root URL, and the read-only option it is taken from is where that # format is spelled — restating it here would be a second source of truth # for a string whose mismatch is a silently rejected login. # # `kind` is left at its `interactive` default: a person logs in here. services.hyperhive.swarm.authelia.oidc.clients = [ { id = grafanaCfg.oidc.clientId; description = "HyperHive swarm metrics"; redirectUris = [ grafanaCfg.oidc.redirectUri ]; } ]; }; }