diff --git a/nix/host-modules/swarm-ui.nix b/nix/host-modules/swarm-ui.nix index 62096f90..9f1b08f5 100644 --- a/nix/host-modules/swarm-ui.nix +++ b/nix/host-modules/swarm-ui.nix @@ -188,6 +188,27 @@ in proxyPass = "http://unix:${controllerCfg.socketPath}:"; extraConfig = swarmAuthRequest; }; + # ⚠️ THE ONE LOCATION ON THIS VHOST WITH NO `swarmAuthRequest`, + # and that is deliberate rather than an omission. + # + # A forge webhook is a machine POST carrying an HMAC signature + # and no session cookie. An authelia auth-request subrequest + # authenticates a *browser session*; there is nothing here for it + # to check, so guarding this location would not make it safer, it + # would make it permanently unreachable. + # + # What replaces it: swarm-controller verifies the + # `X-Hub-Signature-256` HMAC over the raw body before looking at + # anything else, and answers 401 on any mismatch. That check is + # the access control for this path — see the `webhook` module. + # + # Scoped to `/webhook/forge/` rather than `/webhook/` so the + # carve-out is exactly as wide as the endpoint that justifies it: + # a future `/webhook/` does not inherit the + # bypass by living under a shared prefix. + "/webhook/forge/" = { + proxyPass = "http://unix:${controllerCfg.socketPath}:"; + }; # Swagger UI: same "nginx hosts the themed dist straight from # the store, only /api/openapi.json is dynamic" shape as the # per-hive gateway's `swaggerUiLocations`.