From 07f093c4007089b17afc090d4401c7915f339988 Mon Sep 17 00:00:00 2001 From: atlas Date: Wed, 14 Oct 2026 10:28:48 +0200 Subject: [PATCH] swarm-otel: authelia is no longer declared as both a loopback and a published scrape target #5215 moved authelia's scrape to `publishedScrapeTargets` and removed its loopback entry from the authelia module. It was rebased at merge onto c06aa78b6, which had already moved that loopback entry into glue-otel-scrape-targets.nix, so the entry survived there. Every host running authelia and the collector, `singleHostSwarm` included, then failed swarm-otel.nix's job-name assertion. The glue now declares only grafana and nats. forge-placement's case that pinned authelia on loopback now pins its absence, and swarm-otel-identity gains a case reading the assertion itself on the single-host fixture, since the option-level case cannot fail a rebuild the way the assertion does. Fixes #5247 --- nix/host-modules/glue-otel-scrape-targets.nix | 9 +++++---- nix/host-modules/swarm-otel-service.nix | 2 +- nix/module-eval/forge-placement.nix | 9 +++++---- nix/module-eval/swarm-otel-identity.nix | 6 ++++++ 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/nix/host-modules/glue-otel-scrape-targets.nix b/nix/host-modules/glue-otel-scrape-targets.nix index a105a279..520864bf 100644 --- a/nix/host-modules/glue-otel-scrape-targets.nix +++ b/nix/host-modules/glue-otel-scrape-targets.nix @@ -1,7 +1,9 @@ -# Glue: declare the loopback scrape targets of authelia, grafana and nats on the -# swarm's OTEL collector, wherever one of them shares a host with it. +# Glue: declare the loopback scrape targets of grafana and nats on the swarm's +# OTEL collector, wherever one of them shares a host with it. Authelia is a +# `publishedScrapeTargets` job (./swarm-otel-service.nix); a loopback job of +# the same name fails ./swarm-otel.nix's job-name assertion. # -# ONE FILE, THREE PAIRINGS — each service ← the collector, with the same shape. +# ONE FILE, TWO PAIRINGS — each service ← the collector, with the same shape. # Deleting this leaves the collector scraping none of them: no error, no # metrics. # @@ -31,7 +33,6 @@ let in { config.services.hyperhive.swarm.otel.scrapeTargets = { - authelia = withCollector "authelia" "127.0.0.1:${toString swarmCfg.authelia.metricsPort}"; grafana = withCollector "grafana" "127.0.0.1:${toString swarmCfg.grafana.metricsPort}"; nats = withCollector "nats" "127.0.0.1:${toString swarmCfg.nats.metricsPort}"; }; diff --git a/nix/host-modules/swarm-otel-service.nix b/nix/host-modules/swarm-otel-service.nix index 086e72d8..c63fe78b 100644 --- a/nix/host-modules/swarm-otel-service.nix +++ b/nix/host-modules/swarm-otel-service.nix @@ -240,7 +240,7 @@ in declared on a host that does not serve it. An entry that also needs the collector on the same host (the loopback address is only honest then) is declared from a glue module instead, which reads both - switches: authelia, grafana and nats are declared by + switches: grafana and nats are declared by `glue-otel-scrape-targets.nix`. ⚠️ **That constrains the TARGET, not the SCRAPER, and the difference diff --git a/nix/module-eval/forge-placement.nix b/nix/module-eval/forge-placement.nix index cf0fc743..cb085e75 100644 --- a/nix/module-eval/forge-placement.nix +++ b/nix/module-eval/forge-placement.nix @@ -138,15 +138,16 @@ let && !(refusedOver bare "deploy.forgejo.sso.clientSecretFile"); } { - name = "a host running the collector and authelia, grafana and nats scrapes all three on loopback"; + # Authelia is a published target; ./swarm-otel-identity.nix covers it. + name = "a host running the collector, authelia, grafana and nats scrapes grafana and nats on loopback, authelia not"; ok = let t = servicesHere.services.hyperhive.swarm.otel.scrapeTargets; port = n: toString servicesHere.services.hyperhive.swarm.${n}.metricsPort; in - t.authelia == "127.0.0.1:${port "authelia"}" - && t.grafana == "127.0.0.1:${port "grafana"}" - && t.nats == "127.0.0.1:${port "nats"}"; + t.grafana == "127.0.0.1:${port "grafana"}" + && t.nats == "127.0.0.1:${port "nats"}" + && !(t ? authelia); } { name = "hosting the swarm's shared services runs the forge"; diff --git a/nix/module-eval/swarm-otel-identity.nix b/nix/module-eval/swarm-otel-identity.nix index bf666f9f..5303a992 100644 --- a/nix/module-eval/swarm-otel-identity.nix +++ b/nix/module-eval/swarm-otel-identity.nix @@ -367,6 +367,12 @@ let && lib.length jobs == 1 && (lib.head jobs).static_configs == [ { targets = [ "auth.t.local" ]; } ]; } + { + # The case above reads the options; this one reads the assertion they + # feed, which is what refuses an operator's `nixos-rebuild`. + name = "a single-host swarm passes the loopback-vs-published job name assertion"; + ok = !(refusedOver allLocal "is declared as both a loopback"); + } { # Read against the roster the fixture declares rather than against # names spelled here: an arm naming `h1` passes on a single-hive