nix: inline the swarm sub-path aliases at their use sites

autheliaCfg/forgeCfg/vmCfg/vlCfg were local re-exports of
hyperhiveCfg.swarm.<subpath> — a shape that hides the full option
path from grep, the same hazard #4356 fixed for the tls alias.
Removed the six let-bindings and spelled the full
hyperhiveCfg.swarm.<subpath>.<field> path at every use site instead.

None of the read fields (url, machine, hiveClientPrefix,
agentClientSuffix, domain, port) sit on the old side of a
mkRenamedOptionModule in deploy.nix, so inlining the alias's own
current path is correct as-is.

Refs #4363

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
atlas 2026-09-13 20:02:20 +02:00
commit 276bf8531a
6 changed files with 21 additions and 28 deletions

View file

@ -35,7 +35,6 @@ let
hyperhiveDomain = hyperhiveCfg.domain;
swarmDomain = hyperhiveCfg.swarm.domain;
deployCfg = hyperhiveCfg.deploy;
forgeCfg = hyperhiveCfg.swarm.forge;
# Group an account must hold to reach operator-only surfaces. Named
# here because this module writes the rule that enforces it and
@ -78,7 +77,7 @@ let
# this data: `authn_strategies` on the authz endpoint also accepts
# `CookieSession`, and a cookie carries no audience at all.
metricsRule = {
domain = forgeCfg.domain;
domain = hyperhiveCfg.swarm.forge.domain;
resources = [ "^/metrics$" ];
}
// (

View file

@ -20,11 +20,8 @@ let
networkCfg = config.services.hyperhive.network;
hyperhiveCfg = config.services.hyperhive;
gatewayCfg = hyperhiveCfg.gateway;
autheliaCfg = hyperhiveCfg.swarm.authelia;
baoCfg = hyperhiveCfg.swarm.bao;
baoDeploy = deployCfg.bao;
vmCfg = hyperhiveCfg.swarm.victoriametrics;
vlCfg = hyperhiveCfg.swarm.victorialogs;
swarmDomain = hyperhiveCfg.swarm.domain;
caTrust = import ./lib/hive-ca-trust.nix {
@ -90,7 +87,7 @@ let
# is a Grafana with no login of any kind, arrived at silently. SSO is a
# requirement of running this service, so an unconfigured swarm fails to
# build and says which option to set.
ssoConfigured = autheliaCfg.url != null;
ssoConfigured = hyperhiveCfg.swarm.authelia.url != null;
# A reader of the store is defined by holding a certificate the store
# accepts, never by standing next to it — the rule
@ -104,7 +101,7 @@ let
# around by reaching into authelia's tree whenever it happens to be local.
haveClientIdentity = baoDeploy.clientCertFile != null && baoDeploy.clientKeyFile != null;
autheliaUrl = toString autheliaCfg.url;
autheliaUrl = toString hyperhiveCfg.swarm.authelia.url;
# Where the plaintext lands inside the container. Under /var/lib rather
# than /run: Grafana may start before the delivery unit on a later boot,
@ -304,7 +301,7 @@ in
datasourceUrl = lib.mkOption {
type = lib.types.str;
default = "http://127.0.0.1:${toString vmCfg.port}";
default = "http://127.0.0.1:${toString hyperhiveCfg.swarm.victoriametrics.port}";
defaultText = lib.literalExpression ''"http://127.0.0.1:''${toString services.hyperhive.swarm.victoriametrics.port}"'';
description = ''
Where the provisioned datasource points. Defaults to the metrics
@ -317,7 +314,7 @@ in
logsDatasourceUrl = lib.mkOption {
type = lib.types.str;
default = "http://127.0.0.1:${toString vlCfg.port}";
default = "http://127.0.0.1:${toString hyperhiveCfg.swarm.victorialogs.port}";
defaultText = lib.literalExpression ''"http://127.0.0.1:''${toString services.hyperhive.swarm.victorialogs.port}"'';
description = ''
Where the provisioned logs datasource points. Same reasoning as

View file

@ -30,8 +30,6 @@ let
# operator sees, not a coercion error from here.
domainBase = if swarmDomain == null then "invalid" else swarmDomain;
autheliaCfg = hyperhiveCfg.swarm.authelia;
# The collector names its components `<kind>/<owner>`, where `<owner>` is a
# hive name for the per-hive pipelines and this literal for the swarm tier's
# own. The two share one namespace and are merged with `//`, so a hive named
@ -647,8 +645,8 @@ in
systemd.services.swarm-otel-oidc-secret = lib.mkIf deployCfg.authelia.enable {
description = "deliver the swarm collector's OIDC client secret from authelia";
after = [ "container@${autheliaCfg.machine}.service" ];
requires = [ "container@${autheliaCfg.machine}.service" ];
after = [ "container@${hyperhiveCfg.swarm.authelia.machine}.service" ];
requires = [ "container@${hyperhiveCfg.swarm.authelia.machine}.service" ];
before = [ "container@${cfg.machine}.service" ];
wantedBy = [ "container@${cfg.machine}.service" ];
serviceConfig = {
@ -855,7 +853,7 @@ in
# there is no version of this collector that runs without one.
# Stated as an assertion rather than a fallback because a guessed
# issuer URL evaluates cleanly and refuses every hive at runtime.
assertion = autheliaCfg.url != null;
assertion = hyperhiveCfg.swarm.authelia.url != null;
message = ''
services.hyperhive.deploy.swarm-otel.enable is true but
services.hyperhive.swarm.authelia.url is null: every hive
@ -1065,7 +1063,7 @@ in
# A path, never a value — nothing here may read the
# secret, or it lands in the store world-readable.
client_secret_file = collectorSecretPath;
token_url = "${autheliaCfg.url}/api/oidc/token";
token_url = "${hyperhiveCfg.swarm.authelia.url}/api/oidc/token";
# The scope authelia's bearer-authz check looks for.
# The client is REGISTERED for it (the collector's
# entry sets `bearerAuthz`), but prometheus asks for
@ -1287,13 +1285,13 @@ in
lib.mapAttrs' (
h: _:
lib.nameValuePair "oidc/${h}" {
issuer_url = autheliaCfg.url;
issuer_url = hyperhiveCfg.swarm.authelia.url;
# The audience this hive's client is registered to
# request, and the reason one hive's token is refused by
# another hive's receiver. Same expression authelia
# registers it under — a second spelling here would deny
# every hive, as a 401 that blames the token.
audience = "${autheliaCfg.hiveClientPrefix}${h}";
audience = "${hyperhiveCfg.swarm.authelia.hiveClientPrefix}${h}";
# ⛔ DO NOT ADD `issuer_ca_path` HERE. The failure it
# causes is invisible to every check we have.
#
@ -1336,7 +1334,7 @@ in
# a real swarm-controller push gets a healthy-looking 401.
// {
"oidc/${swarmTierName}" = {
issuer_url = autheliaCfg.url;
issuer_url = hyperhiveCfg.swarm.authelia.url;
audience = config.services.hyperhive.swarm.controller.queueClientId;
};
}
@ -1351,7 +1349,7 @@ in
client_id = cfg.clientId;
# A path, never a value. Same file the scrape side reads.
client_secret_file = collectorSecretPath;
token_url = "${autheliaCfg.url}/api/oidc/token";
token_url = "${hyperhiveCfg.swarm.authelia.url}/api/oidc/token";
# Registered is not requested: a client that does not ASK
# for the scope gets a token carrying none, and one that
# does not ask for an audience gets `aud: []`.

View file

@ -37,7 +37,6 @@ let
hyperhiveCfg = config.services.hyperhive;
deployCfg = hyperhiveCfg.deploy;
baoDeploy = deployCfg.bao;
autheliaCfg = hyperhiveCfg.swarm.authelia;
cfg = deployCfg.swarm-secret-publisher;
# A reader is defined by holding a certificate the store accepts, never by
@ -54,7 +53,9 @@ let
# The client id agent containers present, per hive — composed exactly as
# ./swarm-authelia.nix composes it, from the same two read-only options, so a
# rename there cannot leave this spelling behind.
agentClientId = hive: "${autheliaCfg.hiveClientPrefix}${hive}${autheliaCfg.agentClientSuffix}";
agentClientId =
hive:
"${hyperhiveCfg.swarm.authelia.hiveClientPrefix}${hive}${hyperhiveCfg.swarm.authelia.agentClientSuffix}";
# The swarm's own services, as opposed to its hives. One client for the whole
# swarm rather than one per hive, so one value in the store rather than a copy

View file

@ -40,7 +40,6 @@ let
networkCfg = config.services.hyperhive.network;
hyperhiveCfg = config.services.hyperhive;
gatewayCfg = hyperhiveCfg.gateway;
autheliaCfg = hyperhiveCfg.swarm.authelia;
swarmDomain = hyperhiveCfg.swarm.domain;
# Total on a null swarm domain for the same reason every sibling module is:
@ -56,7 +55,7 @@ let
swarmAuthRequest = ''
auth_request /__hive_authelia;
auth_request_set $target_url $scheme://$http_host$request_uri;
error_page 401 =302 https://${autheliaCfg.domain}/?rd=$target_url;
error_page 401 =302 https://${hyperhiveCfg.swarm.authelia.domain}/?rd=$target_url;
'';
in
{
@ -241,14 +240,14 @@ in
# reasoning as `swarm-ui.nix`'s own copy (measured against the
# pinned authelia binary, not copied from an example).
"= /__hive_authelia" = {
proxyPass = "https://${autheliaCfg.domain}/api/authz/auth-request";
proxyPass = "https://${hyperhiveCfg.swarm.authelia.domain}/api/authz/auth-request";
# nixpkgs appends its OWN `Host $host` after extraConfig,
# which would override verifiedProxyTo's — see the comment
# on verifiedProxyTo in hive-gateway/vhost-lib.nix.
recommendedProxySettings = false;
extraConfig = ''
internal;
${gatewayCfg.lib.verifiedProxyTo autheliaCfg.domain}
${gatewayCfg.lib.verifiedProxyTo hyperhiveCfg.swarm.authelia.domain}
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-Method $request_method;

View file

@ -21,7 +21,6 @@ let
networkCfg = config.services.hyperhive.network;
hyperhiveCfg = config.services.hyperhive;
gatewayCfg = hyperhiveCfg.gateway;
autheliaCfg = hyperhiveCfg.swarm.authelia;
swarmDomain = hyperhiveCfg.swarm.domain;
# Total on a null swarm domain for the same reason every sibling module is:
@ -160,14 +159,14 @@ in
# `X-Original-Method` are what authelia's auth-request implementation
# reads, and the address it compares the token's audience against.
"= /__metrics_push_authz" = {
proxyPass = "https://${autheliaCfg.domain}/api/authz/auth-request";
proxyPass = "https://${hyperhiveCfg.swarm.authelia.domain}/api/authz/auth-request";
# nixpkgs appends its OWN `Host $host` after extraConfig, which
# would override verifiedProxyTo's — see the comment on
# verifiedProxyTo in hive-gateway/vhost-lib.nix.
recommendedProxySettings = false;
extraConfig = ''
internal;
${gatewayCfg.lib.verifiedProxyTo autheliaCfg.domain}
${gatewayCfg.lib.verifiedProxyTo hyperhiveCfg.swarm.authelia.domain}
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-Method $request_method;