diff --git a/nix/host-modules/swarm-authelia.nix b/nix/host-modules/swarm-authelia.nix index 09c7c5f5..b3c9a027 100644 --- a/nix/host-modules/swarm-authelia.nix +++ b/nix/host-modules/swarm-authelia.nix @@ -43,6 +43,7 @@ let swarmDomain = hyperhiveCfg.swarm.domain; uiCfg = hyperhiveCfg.swarm.ui; forgeCfg = hyperhiveCfg.swarm.forge; + otelCfg = hyperhiveCfg.swarm.otel; # Group an account must hold to reach operator-only surfaces. Named # here because this module writes the rule that enforces it and @@ -356,6 +357,16 @@ in two services defaulting to the same port do not conflict at build time — one simply loses at runtime, with nothing in any log. Check a new value against the others before changing this. + + ::: {.note} + Loopback means this endpoint is only reachable by a collector on + the *same host*, so the scrape target is declared only when one is + enabled here. Run the swarm's collector elsewhere and authelia's + metrics are simply not collected — no error, and nothing in a log + to say so. Making them reachable across hosts is a different piece + of work: the endpoint would have to be published under a name, + with a certificate and an audience. + ::: ''; }; @@ -825,10 +836,24 @@ in services.hyperhive.gateway.localNames = [ cfg.domain ]; # Declared here rather than in the collector's module, per the option's - # own rule: an entry exists only where the service that named it runs, - # which is what keeps scraper and target on one host by construction - # rather than by the all-local deployment happening to co-locate them. - services.hyperhive.swarm.otel.scrapeTargets.authelia = "127.0.0.1:${toString cfg.metricsPort}"; + # own rule: an entry exists only where the service that named it runs. + # + # Gated on the collector's `enable` as well, and that second condition is + # what makes the loopback address honest. Both services default from + # `swarm.enableRequiredServices` — but `mkDefault` is an invitation to + # override, not a guarantee, so "they are on the same host" is a property + # of the auto-deployed topology rather than of the module. Without this + # gate, a host running authelia and no collector would declare a target + # nothing can read, and the absence would be silent: no error, no metrics, + # nothing to notice. + # + # It does not make authelia scrapeable from ANOTHER host — that needs the + # endpoint published under a name with a cert and an audience, which is a + # different piece of work. This only stops the config asserting a + # collection that is not happening. + services.hyperhive.swarm.otel.scrapeTargets = lib.mkIf otelCfg.enable { + authelia = "127.0.0.1:${toString cfg.metricsPort}"; + }; # This swarm-ui quick-links entry, same guard as the vhost/DNS name # above (only the host actually running the container claims it —