diff --git a/docs/process/gotchas.md b/docs/process/gotchas.md index 55a1c546..1e5bf753 100644 --- a/docs/process/gotchas.md +++ b/docs/process/gotchas.md @@ -75,17 +75,6 @@ the path entry resolves to `/run/wrappers/bin/bin` instead. hive-c0re restarts. Without it, every restart wipes bind sources and existing containers fail to start. -### `DynamicUser` + `RuntimeDirectoryPreserve` hides the socket from nginx - -With both set, systemd creates the runtime directory under `/run/private/` -(`0700 root:root`) and symlinks `/run/` to it (`systemd.exec(5)`, -`RuntimeDirectoryPreserve=`). No unprivileged user can traverse that, so -nginx's `connect()` to a socket in it fails with `EACCES` whatever the -directory and socket modes are. A unit serving a socket to another user -runs as a static user instead (`swarm-controller`, `swarm-logs-auth`). -`module-eval-core-toggle` fails on any `unix:` upstream of nginx owned by -such a unit. - ### `RestrictAddressFamilies` fails as "Address family not supported by protocol" A unit whose `RestrictAddressFamilies` omits a family gets `EAFNOSUPPORT` diff --git a/nix/host-modules/swarm-victorialogs.nix b/nix/host-modules/swarm-victorialogs.nix index 15ecac06..b1b946b4 100644 --- a/nix/host-modules/swarm-victorialogs.nix +++ b/nix/host-modules/swarm-victorialogs.nix @@ -372,13 +372,6 @@ in # The agents' check on `/select/logsql/`. On the host rather than in the # store's container: it needs nothing of the store, only nginx's reach to # its socket and its own store identity. - users.users.${logsAuthUnit} = { - isSystemUser = true; - group = logsAuthUnit; - description = "swarm log store auth_request responder"; - }; - users.groups.${logsAuthUnit} = { }; - systemd.services.${logsAuthUnit} = { description = "swarm log store auth_request responder for agent credentials"; wantedBy = [ "multi-user.target" ]; @@ -398,11 +391,7 @@ in ]; # Paths only: `argv` is world-readable via /proc//cmdline. LoadCredential = lib.mapAttrsToList (id: path: "${id}:${path}") logsAuthStoreFiles; - # ⚠️ A static user, never `DynamicUser`: with `RuntimeDirectoryPreserve` - # systemd puts a dynamic user's runtime directory under - # `/run/private/` (0700 root:root), which nginx cannot traverse. - User = logsAuthUnit; - Group = logsAuthUnit; + DynamicUser = true; RuntimeDirectory = logsAuthUnit; # Traverse-only for others, so nginx reaches the socket path. RuntimeDirectoryMode = "0751"; @@ -414,11 +403,9 @@ in SyslogIdentifier = logsAuthUnit; ProtectSystem = "strict"; ProtectHome = true; - PrivateTmp = "disconnected"; + PrivateTmp = true; PrivateDevices = true; NoNewPrivileges = true; - RestrictSUIDSGID = true; - RemoveIPC = true; }; environment = { BAO_ADDR = "https://${baoCfg.domain}:${toString baoCfg.port}"; diff --git a/nix/module-eval/core-toggle.nix b/nix/module-eval/core-toggle.nix index 9b470792..1e123772 100644 --- a/nix/module-eval/core-toggle.nix +++ b/nix/module-eval/core-toggle.nix @@ -578,47 +578,6 @@ let && lib.hasInfix "--socket /run/swarm-logs-auth/auth.sock" unit.serviceConfig.ExecStart && l ? "= /__hive_authelia"; } - { - # A `DynamicUser` unit's preserved runtime directory lives under - # `/run/private/` (0700 root:root), which nginx cannot traverse, so a - # socket there answers every proxied request with a 502. Each `unix:` - # upstream under `/run//` is matched to the units creating ``. - # The first clause is the control: the match finds swarm-logs-auth's. - name = "no unix socket nginx proxies to sits in a DynamicUser's preserved runtime directory"; - ok = - let - prefix = "http://unix:/run/"; - upstreamDirs = lib.unique ( - map (p: lib.head (lib.splitString "/" (lib.removePrefix prefix p))) ( - lib.filter (p: p != null && lib.hasPrefix prefix p) ( - lib.concatMap (vh: lib.mapAttrsToList (_: loc: loc.proxyPass) vh.locations) ( - lib.attrValues allLocal.services.nginx.virtualHosts - ) - ) - ) - ); - runtimeDirs = - sc: - let - r = sc.RuntimeDirectory or [ ]; - in - if lib.isList r then r else lib.splitString " " r; - owners = lib.filterAttrs ( - _: u: lib.any (d: lib.elem d upstreamDirs) (runtimeDirs u.serviceConfig) - ) allLocal.systemd.services; - hidden = - sc: - lib.elem (sc.DynamicUser or false) [ - true - "yes" - ] - && !(lib.elem (sc.RuntimeDirectoryPreserve or "no") [ - false - "no" - ]); - in - owners ? swarm-logs-auth && !(lib.any (u: hidden u.serviceConfig) (lib.attrValues owners)); - } { # Every agent bearer the responder has not recently granted costs a # store login and read, so its location carries the per-address limit.