Watch
0
0
Fork
You've already forked hyperhive
0

gateway: reject unmatched Host instead of serving the dashboard

The `_` vhost was serving the hive's own surface, so every dashboard and
agent-UI request matched the default server rather than a named vhost --
and so did a request for any name at all, including a raw IP.

Split it: `_` keeps only `return 444`, and the hive surface moves to a
vhost named for the hive domain. `_` is `mkDefault` so an operator can
claim default_server themselves, plus an assertion for the case where
they add one without turning ours off -- nginx refuses to start on a
duplicate default_server and nixpkgs asserts nothing, so that would
otherwise surface as a gateway outage at rebuild time.
This commit is contained in:
atlas 2026-08-13 19:34:12 +02:00 • committed by mara
commit c32a9367e4
2 changed files with 74 additions and 4 deletions

View file

@ -24,6 +24,13 @@ let
matrixCfg = config.services.hyperhive.swarm.matrix;
networkCfg = config.services.hyperhive.network;
# Every vhost claiming `default_server`, ours and the operator's
# alike. Computed once so the assertion below and the message it
# prints cannot disagree about what they found.
defaultVhosts = lib.filter (n: config.services.nginx.virtualHosts.${n}.default or false) (
lib.attrNames config.services.nginx.virtualHosts
);
# Dashboard SPA dist, static-served by nginx.
dashboardDist = "${config.services.hyperhive.c0re.servedFrontend}/dashboard";
@ -143,6 +150,39 @@ in
rather than letting dnsmasq pick.
'';
}
{
# nginx refuses to start with two `default_server`s on one
# address ("a duplicate default server for 0.0.0.0:<port>",
# exit 1) and nixpkgs asserts nothing — `vhost.default` is a
# plain bool rendered straight into the listen line. So without
# this, an operator adding their own default vhost gets a
# gateway that fails its config test at rebuild time, which
# takes the forge, dashboard, matrix and swarm UI with it, and
# reports a port rather than a cause.
#
# Not covered by our `mkDefault`: an operator's own vhost is a
# different option path, so nothing merges and nothing
# conflicts — priority only helps someone who already knows
# ours exists. Fail at eval and name both, so the fix
# (`services.nginx.virtualHosts.<ours>.default = false`) is
# readable from the error.
assertion = lib.length defaultVhosts <= 1;
message = ''
More than one nginx virtual host is marked `default = true`:
${lib.concatStringsSep ", " defaultVhosts}
nginx allows exactly one default server per listen address
and refuses to start otherwise, so this would fail at
service start rather than here — taking every site behind
the gateway down with it.
The gateway's own catch-all (`_`, which returns 444) is set
with `mkDefault`, so to make yours the default server turn
ours off explicitly:
services.nginx.virtualHosts."_".default = false;
'';
}
];
# Ensure the gateway state dirs exist at host boot, before anything