refactor(gateway): make the gateway unconditional — remove gateway.enable
The gateway container starts alongside every hyperhive deployment, so gating it behind a separate enable flag was a footgun: an operator who set it false lost the only thing exposed to the outside while the agent containers kept running. Re-gate the gateway config on the top-level services.hyperhive.enable instead. - hive-gateway.nix: drop the gateway.enable mkOption; gate the config block on config.services.hyperhive.enable. - hive-forge.nix: behindGateway now defaults to services.hyperhive.enable; remove the behindGateway-requires-gateway assertion (now vacuous). - hive-network.nix: remove both gateway.enable assertions (vacuous). - hive-c0re.nix: drop the firewall.allowedTCPPortRanges 8100-8999 fallback that opened agent ports when the gateway was off (the gateway is now the sole entry point); HIVE_GATEWAY_ENABLED is always set since the gateway always runs. - nix/docs/default.nix: remove the gateway.enable = mkForce false stub (would be an eval error against the removed option; the gateway is already re-gated on hyperhive.enable, which docs force false). - hive-matrix.nix, dashboard.rs: comment/prose updates only. BREAKING: operators relying on services.hyperhive.gateway.enable = false to suppress the gateway must instead point their own reverse proxy at the gateway's port. NixOS errors clearly on the now-unknown option.
This commit is contained in:
parent
d9c66de069
commit
fdf05c1673
7 changed files with 34 additions and 86 deletions
|
|
@ -229,15 +229,15 @@ struct StateSnapshot {
|
|||
/// chrome so the `M4TR1X →` tab doesn't flash when the GUI is off.
|
||||
matrix_gui_enabled: bool,
|
||||
/// Whether `hive-gateway` is in front of this dashboard. Sourced
|
||||
/// from `HIVE_GATEWAY_ENABLED` env var (set by the c0re NixOS
|
||||
/// module when `services.hyperhive.gateway.enable` is on). When
|
||||
/// true the dashboard frontend builds same-origin
|
||||
/// `/agent/<name>/` links to the per-agent web UI (the gateway
|
||||
/// routes them via the runtime-generated `agents.conf` include
|
||||
/// file — see `gateway_nginx.rs`); when false it falls back to
|
||||
/// direct `http://<hostname>:<port>/` TCP links so gateway-off /
|
||||
/// local-dev deploys keep working. See `docs/gateway.md::Vhost
|
||||
/// map`.
|
||||
/// from the `HIVE_GATEWAY_ENABLED` env var, which the c0re NixOS
|
||||
/// module now always sets (the gateway runs unconditionally
|
||||
/// alongside hyperhive), so this is effectively always true: the
|
||||
/// dashboard frontend builds same-origin `/agent/<name>/` links to
|
||||
/// the per-agent web UI (the gateway routes them via the
|
||||
/// runtime-generated `agents.conf` include file — see
|
||||
/// `gateway_nginx.rs`). The `false` branch (direct
|
||||
/// `http://<hostname>:<port>/` TCP links) is retained as a defensive
|
||||
/// fallback for the env being unset. See `docs/gateway.md::Vhost map`.
|
||||
gateway_enabled: bool,
|
||||
/// Public URL of the forge vhost served by hive-gateway (e.g.
|
||||
/// `"https://forge.pr1ma.darkest.space"`). Sourced from the
|
||||
|
|
@ -480,7 +480,7 @@ async fn api_state(headers: HeaderMap, State(state): State<AppState>) -> axum::J
|
|||
gateway_enabled: std::env::var_os("HIVE_GATEWAY_ENABLED").is_some_and(|v| {
|
||||
// Same truthy-string parse as `matrix_gui_enabled`; the
|
||||
// env var is set by the c0re NixOS module to the literal
|
||||
// "1" when `services.hyperhive.gateway.enable` is on.
|
||||
// "1" — the gateway always runs alongside hyperhive.
|
||||
let s = v.to_string_lossy().to_ascii_lowercase();
|
||||
matches!(s.as_str(), "1" | "true" | "yes")
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ let
|
|||
services.hyperhive.enable = lib.mkForce false;
|
||||
services.hyperhive.forge.enable = lib.mkForce false;
|
||||
services.hyperhive.matrix.enable = lib.mkForce false;
|
||||
services.hyperhive.gateway.enable = lib.mkForce false;
|
||||
}
|
||||
)
|
||||
];
|
||||
|
|
|
|||
|
|
@ -634,15 +634,9 @@ in
|
|||
};
|
||||
users.groups.hive-core = { };
|
||||
|
||||
# Open the per-agent web-port range when the gateway is *off* —
|
||||
# otherwise the gateway nginx is the sole external entry point.
|
||||
# See `docs/gateway.md::Firewall posture (host-level)`.
|
||||
networking.firewall.allowedTCPPortRanges = lib.mkIf (!config.services.hyperhive.gateway.enable) [
|
||||
{
|
||||
from = 8100;
|
||||
to = 8999;
|
||||
}
|
||||
];
|
||||
# The gateway nginx is always the sole external entry point (it runs
|
||||
# alongside hyperhive), so the per-agent web-port range stays closed on
|
||||
# the host firewall. See `docs/gateway.md::Firewall posture (host-level)`.
|
||||
|
||||
# WireGuard inter-hive mesh. Enabled when
|
||||
# `services.hyperhive.swarm.wireguard.enable = true`. Brings up a
|
||||
|
|
@ -777,9 +771,11 @@ in
|
|||
# docs/gateway.md::Vhost map.
|
||||
HIVE_MATRIX_GUI_ENABLED = "1";
|
||||
}
|
||||
// lib.optionalAttrs config.services.hyperhive.gateway.enable {
|
||||
# When true the dashboard builds same-origin `/agent/<name>/`
|
||||
# links; when false it falls back to direct `<host>:<port>` TCP.
|
||||
// {
|
||||
# The gateway always runs, so the dashboard always builds
|
||||
# same-origin `/agent/<name>/` links (never the direct
|
||||
# `<host>:<port>` TCP fallback). Kept as an env flag so the
|
||||
# dashboard doesn't need to learn the gateway is unconditional.
|
||||
HIVE_GATEWAY_ENABLED = "1";
|
||||
}
|
||||
//
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ in
|
|||
|
||||
behindGateway = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = gatewayCfg.enable or false;
|
||||
defaultText = lib.literalExpression "config.services.hyperhive.gateway.enable";
|
||||
default = config.services.hyperhive.enable;
|
||||
defaultText = lib.literalExpression "config.services.hyperhive.enable";
|
||||
description = ''
|
||||
Serve forgejo through the hive-gateway nginx as a sub-domain
|
||||
vhost (`server_name = cfg.domain`) instead of directly on
|
||||
|
|
@ -127,9 +127,9 @@ in
|
|||
- `gateway.localHostsEntry = true` extends `/etc/hosts` to
|
||||
include `cfg.domain → 127.0.0.1` for local dev.
|
||||
|
||||
Defaults to `services.hyperhive.gateway.enable` — flipping
|
||||
the gateway on/off auto-routes forge through it. Set `false`
|
||||
explicitly to keep forge on the direct port even when the
|
||||
Defaults to `services.hyperhive.enable` (the gateway always runs
|
||||
alongside hyperhive, so forge auto-routes through it). Set `false`
|
||||
explicitly to keep forge on the direct port even though the
|
||||
gateway is running (e.g. an external git client that doesn't
|
||||
traverse the gateway).
|
||||
|
||||
|
|
@ -211,21 +211,6 @@ in
|
|||
or "git.internal".
|
||||
'';
|
||||
}
|
||||
{
|
||||
# behindGateway requires the gateway module to actually be on.
|
||||
# Otherwise the configured `ROOT_URL` flips to a sub-domain
|
||||
# shape that has no nginx vhost backing it → broken on the
|
||||
# rebuild.
|
||||
assertion = !cfg.behindGateway || (gatewayCfg.enable or false);
|
||||
message = ''
|
||||
services.hyperhive.forge.behindGateway = true requires
|
||||
services.hyperhive.gateway.enable = true (the gateway vhost
|
||||
serving forge needs the gateway container to actually be
|
||||
running). Either turn the gateway on, or set
|
||||
services.hyperhive.forge.behindGateway = false to keep forge
|
||||
on its direct port.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
containers.hive-forge = {
|
||||
|
|
|
|||
|
|
@ -69,22 +69,11 @@ in
|
|||
# `docs/gateway.md`.
|
||||
|
||||
options.services.hyperhive.gateway = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Run hive-gateway — a single nginx in front of every hyperhive
|
||||
surface. On by default: the gateway hosts the matrix GUI static
|
||||
dist (when `services.hyperhive.matrix.gui.enable` is true) and
|
||||
proxies everything else to hive-c0re's dashboard upstream. Set
|
||||
`services.hyperhive.gateway.enable = false` to bypass nginx
|
||||
entirely and reach hive-c0re directly on its dashboard port
|
||||
(7000 by default).
|
||||
|
||||
v0 is HTTP-only; TLS / public-domain shape is tracked
|
||||
separately.
|
||||
'';
|
||||
};
|
||||
# The gateway is always run alongside hyperhive (it's the single nginx
|
||||
# in front of every surface and the only thing exposed to the outside);
|
||||
# there is no enable flag. An operator who wants their own reverse proxy
|
||||
# in front points it at the gateway's `port`. The gateway config below
|
||||
# is gated on the top-level `services.hyperhive.enable`.
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
|
|
@ -375,7 +364,7 @@ in
|
|||
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
config = lib.mkIf config.services.hyperhive.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !cfg.localHostsEntry || hyperhiveDomain != null;
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ in
|
|||
defaultText = lib.literalExpression "config.services.hyperhive.matrix.enable";
|
||||
description = ''
|
||||
Serve a matrix web client at `matrix.''${services.hyperhive.domain}/`.
|
||||
Requires `gateway.enable` + `matrix.gatewayHost != null`
|
||||
(default true / `matrix.<hive>` when hive-domain set). When
|
||||
Requires `matrix.gatewayHost != null` (default `matrix.<hive>`
|
||||
when hive-domain set); the gateway itself always runs. When
|
||||
off, the dashboard's `M4TR1X →` tab is hidden. See
|
||||
`docs/gateway.md` for the discovery flow that lets clients
|
||||
auto-find the sub-domain.
|
||||
|
|
@ -435,9 +435,9 @@ in
|
|||
# boot failure this module fixes was an *empty* resolv.conf, a parse
|
||||
# error, not a connectivity one) — so this is robustness, not a boot
|
||||
# requirement. Soft `after` ordering (not `requires`) keeps the matrix
|
||||
# container's lifecycle decoupled from the gateway's. `network.enable`
|
||||
# asserts `gateway.enable`, so the gateway container unit always exists
|
||||
# here. (Declarative `containers.<n>` → `container@<n>.service` — the
|
||||
# container's lifecycle decoupled from the gateway's. The gateway
|
||||
# always runs alongside hyperhive, so the gateway container unit always
|
||||
# exists here. (Declarative `containers.<n>` → `container@<n>.service` — the
|
||||
# nspawn template NixOS generates, confirmed from the live
|
||||
# `container@hive-matrix.service` host unit.)
|
||||
systemd.services."container@hive-matrix".after = lib.mkIf networkCfg.enable [
|
||||
|
|
|
|||
|
|
@ -154,16 +154,6 @@ in
|
|||
`services.hyperhive.network.enable = false` explicitly.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = config.services.hyperhive.gateway.enable;
|
||||
message = ''
|
||||
services.hyperhive.network.enable = true requires
|
||||
services.hyperhive.gateway.enable = true — the dnsmasq
|
||||
resolver runs inside the hive-gateway container (single
|
||||
front-door for both DNS and HTTP). Enable the gateway or
|
||||
set `services.hyperhive.network.enable = false` explicitly.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
# Virtual bridge — veth pairs attach when isolateContainers flips on.
|
||||
|
|
@ -196,17 +186,6 @@ in
|
|||
resolver must be running before isolation is flipped on).
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = !config.services.hyperhive.forge.enable || config.services.hyperhive.gateway.enable;
|
||||
message = ''
|
||||
services.hyperhive.network.isolateContainers = true with
|
||||
services.hyperhive.forge.enable = true requires
|
||||
services.hyperhive.gateway.enable = true — isolated agents
|
||||
reach the forge via `http://forge.<domain>` which nginx (in
|
||||
the gateway container) proxies to forgejo. Without the gateway
|
||||
there is nothing listening on port 80 to serve that hostname.
|
||||
'';
|
||||
}
|
||||
];
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue