refactor(gateway): extract the _ vhost agent + dashboard location groups
Step 3 of the hive-gateway.nix vhost cleanup. Lift the /agent/ catch-all (+ its two internal error-page targets) and the catch-all dashboard proxy out of the inline //-chain into agentLocations / dashboardProxyLocation bindings. The default _ server's locations now read as a flat composition of named groups — matrixRedirectLocations // wellKnownLocations // agentLocations // dashboardProxyLocation // <auth optionalAttrs> — instead of a deep nested literal. The auth-401 group stays inline (a self-contained lib.optionalAttrs already). Pure readability refactor, eval-identical: generated virtualHosts toJSON is byte-identical before/after (8888 bytes, diff empty).
This commit is contained in:
parent
90b7d61792
commit
36e5e19d8e
1 changed files with 67 additions and 75 deletions
|
|
@ -643,9 +643,9 @@ in
|
|||
};
|
||||
|
||||
# `_` (default) server location groups, lifted out of the inline
|
||||
# `//`-chain so the two matrix groups (each with its own `let`)
|
||||
# read on their own. Composed into the `_` vhost's `locations`
|
||||
# below alongside the still-inline agent/dashboard/auth groups.
|
||||
# `//`-chain so each conditional group reads on its own. Composed
|
||||
# into the `_` vhost's `locations` below alongside the still-inline
|
||||
# auth-401 group (a self-contained `lib.optionalAttrs`).
|
||||
|
||||
# `<hive>/matrix/*` → 301 → `matrix.<hive>/$1` (legacy deep-link
|
||||
# shim during the fluffychat sub-domain move). See `docs/gateway.md`.
|
||||
|
|
@ -707,6 +707,68 @@ in
|
|||
};
|
||||
}
|
||||
);
|
||||
|
||||
# `/agent/` catch-all 404 + the two internal error-page targets it
|
||||
# points at. Per-agent `location /agent/<name>/` blocks live in the
|
||||
# runtime-generated `/run/hive-state/agents.conf` (included via
|
||||
# `extraConfig` on the vhost); nginx longest-prefix-match makes a
|
||||
# real `/agent/<name>/` beat this catch-all. `internal` keeps the
|
||||
# error pages reachable only through nginx's error handling.
|
||||
agentLocations = {
|
||||
"/agent/" = {
|
||||
extraConfig = ''
|
||||
error_page 404 = /__hive_agent_not_found;
|
||||
return 404;
|
||||
'';
|
||||
};
|
||||
"= /__hive_agent_not_found" = {
|
||||
extraConfig = ''
|
||||
internal;
|
||||
alias ${agentErrorPagesDir}/not-found.html;
|
||||
default_type text/html;
|
||||
'';
|
||||
};
|
||||
"= /__hive_agent_unreachable" = {
|
||||
extraConfig = ''
|
||||
internal;
|
||||
alias ${agentErrorPagesDir}/unreachable.html;
|
||||
default_type text/html;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Everything else proxies to hive-c0re. Upgrade headers stay set so
|
||||
# SSE (`/dashboard/stream`, `/events/stream`) + websocket
|
||||
# (`/screen/ws`) endpoints keep working transparently. When auth is
|
||||
# enabled, nginx's built-in `auth_basic` validates against the
|
||||
# bind-mounted htpasswd; the `=401` error_page points at the
|
||||
# internal unauthorized page (the auth-only location below).
|
||||
dashboardProxyLocation = {
|
||||
"/" = {
|
||||
proxyPass = "http://${cfg.upstreamHost}:${toString cfg.upstreamPort}";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 1d;
|
||||
${lib.optionalString cfg.auth.enable ''
|
||||
auth_basic "${cfg.auth.realm}";
|
||||
# htpasswd file lives in the gateway state dir,
|
||||
# already bind-mounted read-only at /run/hive-state/.
|
||||
# Host path: /var/lib/hyperhive/gateway/gateway.htpasswd
|
||||
auth_basic_user_file /run/hive-state/gateway.htpasswd;
|
||||
# Serve a custom page when credentials are missing or wrong.
|
||||
# `=401` forces the final status to remain 401 so browsers
|
||||
# still present the login dialog on first visit; users who
|
||||
# dismiss the dialog see a page explaining how to add users
|
||||
# with `hivectl gateway create-user`.
|
||||
# The exact-match location below beats `location /` in nginx's
|
||||
# prefix ordering, so the internal subrequest does not loop back
|
||||
# through auth_basic.
|
||||
error_page 401 =401 /__hive_auth_unauthorized;
|
||||
''}
|
||||
'';
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
system.stateVersion = "26.05";
|
||||
|
|
@ -830,78 +892,8 @@ in
|
|||
locations =
|
||||
matrixRedirectLocations
|
||||
// wellKnownLocations
|
||||
//
|
||||
# `/agent/` catch-all: hits when an operator
|
||||
# requests `/agent/<unknown>/...`. Without this the
|
||||
# request falls through to `/` (c0re dashboard) and
|
||||
# returns 404 with no useful context. Custom 404
|
||||
# page instead. Per-agent `location /agent/<name>/`
|
||||
# blocks live in `/run/hive-state/agents.conf` —
|
||||
# nginx picks them up via the `include` in
|
||||
# `extraConfig` below; the catch-all only matches
|
||||
# names that aren't in that file (nginx longest-
|
||||
# prefix-match: `/agent/atlas/` beats `/agent/`).
|
||||
{
|
||||
"/agent/" = {
|
||||
extraConfig = ''
|
||||
error_page 404 = /__hive_agent_not_found;
|
||||
return 404;
|
||||
'';
|
||||
};
|
||||
# Internal static-file locations the error_page
|
||||
# directives above point at. `internal` keeps
|
||||
# operators from hitting the file directly (only
|
||||
# nginx's error-handling can reach it); `alias`
|
||||
# serves the exact file regardless of request URI.
|
||||
"= /__hive_agent_not_found" = {
|
||||
extraConfig = ''
|
||||
internal;
|
||||
alias ${agentErrorPagesDir}/not-found.html;
|
||||
default_type text/html;
|
||||
'';
|
||||
};
|
||||
"= /__hive_agent_unreachable" = {
|
||||
extraConfig = ''
|
||||
internal;
|
||||
alias ${agentErrorPagesDir}/unreachable.html;
|
||||
default_type text/html;
|
||||
'';
|
||||
};
|
||||
}
|
||||
// {
|
||||
# Everything else proxies to hive-c0re. Upgrade
|
||||
# headers stay set so SSE (`/dashboard/stream`,
|
||||
# `/events/stream`) + websocket (`/screen/ws`)
|
||||
# endpoints keep working transparently.
|
||||
# When auth is enabled, nginx's built-in `auth_basic`
|
||||
# validates credentials against the htpasswd file
|
||||
# bind-mounted at `/run/gateway-auth/`. No extra
|
||||
# service or host-side daemon required.
|
||||
"/" = {
|
||||
proxyPass = "http://${cfg.upstreamHost}:${toString cfg.upstreamPort}";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 1d;
|
||||
${lib.optionalString cfg.auth.enable ''
|
||||
auth_basic "${cfg.auth.realm}";
|
||||
# htpasswd file lives in the gateway state dir,
|
||||
# already bind-mounted read-only at /run/hive-state/.
|
||||
# Host path: /var/lib/hyperhive/gateway/gateway.htpasswd
|
||||
auth_basic_user_file /run/hive-state/gateway.htpasswd;
|
||||
# Serve a custom page when credentials are missing or wrong.
|
||||
# `=401` forces the final status to remain 401 so browsers
|
||||
# still present the login dialog on first visit; users who
|
||||
# dismiss the dialog see a page explaining how to add users
|
||||
# with `hivectl gateway create-user`.
|
||||
# The exact-match location below beats `location /` in nginx's
|
||||
# prefix ordering, so the internal subrequest does not loop back
|
||||
# through auth_basic.
|
||||
error_page 401 =401 /__hive_auth_unauthorized;
|
||||
''}
|
||||
'';
|
||||
};
|
||||
}
|
||||
// agentLocations
|
||||
// dashboardProxyLocation
|
||||
// lib.optionalAttrs cfg.auth.enable {
|
||||
# Internal-only target for the 401 error_page above.
|
||||
# `internal` prevents direct client access; `alias` serves
|
||||
|
|
|
|||
Loading…
Reference in a new issue