diff --git a/nix/host-modules/hive-gateway/default.nix b/nix/host-modules/hive-gateway/default.nix index 084937a5..92d5f7c9 100644 --- a/nix/host-modules/hive-gateway/default.nix +++ b/nix/host-modules/hive-gateway/default.nix @@ -22,6 +22,7 @@ let # same list rather than each deciding what "a swarm service" means. swarmServiceDomains = config.services.hyperhive.swarm.serviceDomains; matrixCfg = config.services.hyperhive.swarm.matrix; + autheliaCfg = config.services.hyperhive.swarm.authelia; forgeCfg = config.services.hyperhive.swarm.forge; networkCfg = config.services.hyperhive.network; @@ -70,6 +71,7 @@ let cfg forgeCfg matrixCfg + autheliaCfg hyperhiveDomain dashboardDist swaggerUiTheme @@ -309,6 +311,7 @@ in networkCfg forgeCfg matrixCfg + autheliaCfg hyperhiveDomain ; }; @@ -332,6 +335,7 @@ in ++ lib.optional (config.services.hyperhive.swarm.forge.behindGateway or false ) config.services.hyperhive.swarm.forge.domain ++ lib.optional (matrixCfg.enable && matrixCfg.gatewayHost != null) matrixCfg.gatewayHost + ++ lib.optional autheliaCfg.enable autheliaCfg.domain ); }; }; diff --git a/nix/host-modules/hive-gateway/dnsmasq.nix b/nix/host-modules/hive-gateway/dnsmasq.nix index b212309a..52eabb4d 100644 --- a/nix/host-modules/hive-gateway/dnsmasq.nix +++ b/nix/host-modules/hive-gateway/dnsmasq.nix @@ -10,6 +10,7 @@ networkCfg, forgeCfg, matrixCfg, + autheliaCfg, hyperhiveDomain, }: { @@ -58,7 +59,8 @@ ++ lib.optional ((forgeCfg.behindGateway or false)) "/${forgeCfg.domain}/${networkCfg.bridgeIp}" ++ lib.optional ( matrixCfg.enable && matrixCfg.gatewayHost != null - ) "/${matrixCfg.gatewayHost}/${networkCfg.bridgeIp}"; + ) "/${matrixCfg.gatewayHost}/${networkCfg.bridgeIp}" + ++ lib.optional autheliaCfg.enable "/${autheliaCfg.domain}/${networkCfg.bridgeIp}"; # DHCP pool covering all usable host addresses on the bridge # subnet — bounds computed by hive-network.nix from # bridgeIp/bridgePrefixLength. All containers (agents and service diff --git a/nix/host-modules/hive-gateway/vhosts.nix b/nix/host-modules/hive-gateway/vhosts.nix index 91d5f484..20d9c97d 100644 --- a/nix/host-modules/hive-gateway/vhosts.nix +++ b/nix/host-modules/hive-gateway/vhosts.nix @@ -9,6 +9,7 @@ cfg, # services.hyperhive.gateway forgeCfg, matrixCfg, + autheliaCfg, # services.hyperhive.swarm.authelia hyperhiveDomain, dashboardDist, swaggerUiTheme, # nix/packages/swagger-ui-theme.nix: has index.html + hyperhive-theme.css @@ -123,6 +124,42 @@ let }; }; + # Authelia sub-domain vhost. `server_name = authelia.domain`, all of + # `/` → authelia. Empty attrset unless THIS host runs the container: + # every hive knows the swarm's `authelia.url`, but only the one + # serving it may claim the name — a client hive declaring this vhost + # would answer for a service it does not run. + # + # ⚠️ The server name must be exactly `autheliaCfg.domain`, not a + # near-miss: authelia validates `authelia_url ⊂ session cookie domain` + # at STARTUP, so a mismatch is a container that refuses to boot rather + # than a login that misbehaves. + # + # ⚠️ And deliberately NO `dashboardAuth` here. That block is the + # gateway's `auth_basic`; applying it to the SSO provider would put + # the login page behind the login mechanism it exists to replace. + autheliaVhost = lib.optionalAttrs autheliaCfg.enable { + "${autheliaCfg.domain}" = (vhostTlsFor autheliaCfg.domain) // { + listen = vhostListen; + extraConfig = securityHeaders; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString autheliaCfg.port}/"; + proxyWebsockets = true; + extraConfig = '' + proxy_buffering off; + # authelia decides by the ORIGINAL request, not by the hop it + # sees — the login redirect and the session cookie's domain + # both derive from these. Without them every request looks + # like it arrived at 127.0.0.1 over plain http. + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Uri $request_uri; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + ''; + }; + }; + }; + # Matrix sub-domain vhost. `server_name = matrixCfg.gatewayHost`. # `/_matrix/*` → tuwunel (CORS *, 50M body cap, 1h long-poll # timeout). `/` serves fluffychat or 404 if GUI off. nginx @@ -409,5 +446,6 @@ in }; } // forgeVhost + // autheliaVhost // matrixVhost; }