Watch
0
0
Fork
You've already forked hyperhive
0

swarm-authelia: run in its own network namespace

Refs #4815
This commit is contained in:
atlas 2026-10-21 21:26:13 +02:00 • committed by mara
commit 220b51d0a3
12 changed files with 204 additions and 105 deletions

View file

@ -692,7 +692,7 @@ let
in
url autheliaNotColocated == "${autheliaNotColocated.services.hyperhive.swarm.authelia.url}/bridge"
&& url autheliaColocated == url autheliaNotColocated
&& location.proxyPass == "http://127.0.0.1:${toString authelia.bridgePort}/";
&& location.proxyPass == "http://unix:/run/swarm-authelia/bridge.sock:/";
}
{
# Config NAMES the IdP; it never computes where the IdP is. Both arms

View file

@ -236,7 +236,7 @@ let
}
{
# The location the collector's job requests: gated, and proxying to the
# loopback listener that has no authentication of its own.
# socket listener that has no authentication of its own.
name = "authelia's vhost serves /metrics only behind the collector's auth subrequest";
ok =
let
@ -244,7 +244,7 @@ let
locs = autheliaOnly.services.nginx.virtualHosts.${h.swarm.authelia.domain}.locations;
authz = locs."= /__authelia_metrics_authz";
in
locs."= /metrics".proxyPass == "http://127.0.0.1:${toString h.swarm.authelia.metricsPort}/metrics"
locs."= /metrics".proxyPass == "http://unix:/run/swarm-authelia/metrics.sock:/"
&& lib.hasInfix "auth_request /__authelia_metrics_authz;" locs."= /metrics".extraConfig
&& authz.proxyPass == "https://${h.swarm.authelia.domain}/api/authz/auth-request"
&& lib.hasInfix "internal;" authz.extraConfig;

View file

@ -171,7 +171,7 @@ let
# Every service container at once: the services-only host plus the CI
# runner. The CI runner, the review classifier, the builder, the claude login
# minter, the metrics store and the homeserver are the six containers on a
# minter, the metrics store, the homeserver and authelia are the seven containers on a
# netns of their own.
serviceContainersWithCi = hive {
deploy.hive-controller.enable = false;
@ -599,7 +599,7 @@ let
let
shared = lib.filter (c: !c.privateNetwork) (lib.attrValues serviceContainers);
in
lib.length shared == 7
lib.length shared == 6
&& lib.all (
c: !c.config.networking.firewall.enable && !c.config.networking.resolvconf.enable
) shared;
@ -694,6 +694,51 @@ let
&& unit.serviceConfig.Group == "gateway-nginx"
&& lib.elem dir unit.serviceConfig.ReadWritePaths;
}
{
# On the bridge by DHCP, with all three listeners on sockets: nothing
# the bridge can dial. Every vhost location that forwards goes through
# one of the sockets, except the internal authz subrequest, which is
# `https://`. The main, bridge and metrics locations are named so an
# empty filter can't pass.
name = "authelia runs on a netns of its own and the gateway reaches all three listeners over sockets";
ok =
let
host = serviceContainersWithCi;
net = host.services.hyperhive.network;
c = host.containers.swarm-authelia;
dir = "/run/swarm-authelia";
sock = n: "${dir}/${n}.sock";
locs = host.services.nginx.virtualHosts.${host.services.hyperhive.swarm.authelia.domain}.locations;
forwarded = lib.filter (p: p != null && !(lib.hasPrefix "https://" p)) (
map (l: l.proxyPass) (lib.attrValues locs)
);
inner = c.config;
settings = inner.services.authelia.instances.swarm.settings;
unit = inner.systemd.services.authelia-swarm;
bridge = inner.systemd.services.swarm-authelia-bridge;
nginxGid = host.ids.gids.nginx;
in
c.privateNetwork
&& c.hostBridge == net.bridgeName
&& c.hostAddress == null
&& c.localAddress == null
&& inner.networking.interfaces.eth0.useDHCP
&& inner.networking.firewall.enable
&& settings.server.address == "unix://${sock "authelia"}?umask=0007"
&& settings.telemetry.metrics.address == "unix://${sock "metrics"}?umask=0007"
&& bridge.environment.SWARM_AUTHELIA_BRIDGE_SOCKET == sock "bridge"
&& !(bridge.environment ? SWARM_AUTHELIA_BRIDGE_BIND)
&& locs."/".proxyPass == "http://unix:${sock "authelia"}:/"
&& locs."/bridge/".proxyPass == "http://unix:${sock "bridge"}:/"
&& locs."= /metrics".proxyPass == "http://unix:${sock "metrics"}:/"
&& lib.all (lib.hasPrefix "http://unix:${dir}/") forwarded
&& c.bindMounts.${dir}.hostPath == dir
&& builtins.elem "d ${dir} 0770 root ${toString nginxGid} - -" host.systemd.tmpfiles.rules
&& inner.users.groups.gateway-nginx.gid == nginxGid
&& unit.serviceConfig.Group == "gateway-nginx"
&& bridge.serviceConfig.Group == "gateway-nginx"
&& lib.elem dir unit.serviceConfig.ReadWritePaths;
}
{
# The DynamicUser layout keeps the history under /var/lib/private; the
# static user's StateDirectory is the plain path. The move runs as its