From cb650f2dbb8b6c3c6c86065ba1b454d23a21db08 Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 17 Aug 2026 19:43:23 +0200 Subject: [PATCH] fix(#3363): give swarm-authelia the hive CA too Same class-B defect as the queue responder: swarm-authelia-bridge introspects authelia by name over https and the container trusted no swarm CA, so the call could only ever fail UnknownIssuer. This is also the prerequisite for the by-domain introspection change on #3391 -- flipping that URL without the trust half would swap one failure for another. --- nix/host-modules/swarm-authelia.nix | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/nix/host-modules/swarm-authelia.nix b/nix/host-modules/swarm-authelia.nix index cd63c2a6..753b067f 100644 --- a/nix/host-modules/swarm-authelia.nix +++ b/nix/host-modules/swarm-authelia.nix @@ -64,6 +64,18 @@ let unitName = "authelia-${instance}"; stateDir = "/var/lib/${unitName}"; + tlsCfg = hyperhiveCfg.tls; + caTrust = import ./lib/hive-ca-trust.nix { inherit lib tlsCfg gatewayCfg; }; + # `swarm-authelia-bridge` verifies the gateway when it introspects by name. + # Nothing in this container trusted the swarm CA, which is a runtime file no + # build-time option can name — so an https call out of here could only ever + # fail `UnknownIssuer`. Same defect the queue's responder hit. + caBundleModule = caTrust.trustBundle { + inherit pkgs; + name = cfg.machine; + consumers = [ "swarm-authelia-bridge" ]; + }; + # The SWARM's domain, because that is where the protected apps now live # (`forge.`, `chat.`, `auth.`). It moves in the # same commit as `domain` below and cannot lag it: authelia validates @@ -751,12 +763,19 @@ in }; }; + # Order the container after the host CA generator, so the bind source + # exists before nspawn sets the mount up. + systemd.services."container@${cfg.machine}" = caTrust.containerOrdering; + containers.${cfg.machine} = { autoStart = true; ephemeral = false; # Shared host netns, like the forge and matrix containers: the # gateway reaches authelia at 127.0.0.1:. privateNetwork = false; + # Public trust bundle only, read-only. Empty when the gateway is not + # self-signed, so the whole trust path drops out cleanly. + bindMounts = caTrust.bindMount; config = { ... }: @@ -766,6 +785,7 @@ in inherit (networkCfg) bridgeIp; dnsConsumers = [ "authelia-${instance}.service" ]; }) + caBundleModule ]; system.stateVersion = "26.05";