docs/gateway.md: extract hive-c0re + hive-forge prose blocks (#718 batch 2)
Continues #718 docs-extraction. Three more blocks moved to `docs/gateway.md` (which already houses the gateway architecture story from #775): 1. **Firewall posture (gateway on vs off)** — was a 22-line block above `networking.firewall = lib.mkIf ...` in hive-c0re.nix. Trimmed to 3-line ref. New `docs/gateway.md::Firewall posture (host-level)` section covers the gateway-on / gateway-off trade-off + why dashboard port stays loopback-only. 2. **`HIVE_FORGE_URL` loopback rationale** — was a 14-line block above the env-var assignment. Trimmed to 5-line ref. New `docs/gateway.md::HIVE_FORGE_URL: loopback for in-cluster, sub-domain for the operator` section covers the in-cluster vs external split + why agent containers can't use the sub-domain. 3. **hive-forge container shape** — was a 15-line top-of-`config` block in hive-forge.nix explaining the nixos-container + host netns choices. Trimmed to 4-line ref. New `docs/gateway.md::hive-forge container shape` section captures the same content with state-dir + wipe-via-destroy notes. Net: hive-c0re.nix -29 lines, hive-forge.nix -11 lines, gateway.md +44 lines. Same pattern as #782 (first pass) per iris's #10114 guidance — substantive WHY moves to docs as named sub-paragraphs, in-code shrinks to `// see docs/<file>::<section>` refs. Verified: `nix eval` on agent-base toplevel still resolves cleanly; firewall posture unchanged (still 0 ports opened in the gateway-on case + the same 8100..8999 range in the gateway-off case). Continues #718. Follow-up batches: remaining harness-base.nix blocks, nix/docs/default.nix, nix/assets.nix, nix/templates/weston-vnc.nix.
This commit is contained in:
parent
df71d8deac
commit
ea90814809
3 changed files with 63 additions and 51 deletions
|
|
@ -76,3 +76,54 @@ SSH for forge stays direct on `cfg.sshPort` — separate listener protocol, not
|
||||||
- #772 / #775 — fluffychat hops from `<hive>/matrix/` to `matrix.<hive>/`.
|
- #772 / #775 — fluffychat hops from `<hive>/matrix/` to `matrix.<hive>/`.
|
||||||
|
|
||||||
Next-up tracked separately: #14 (container netns isolation), TLS (#594).
|
Next-up tracked separately: #14 (container netns isolation), TLS (#594).
|
||||||
|
|
||||||
|
## Firewall posture (host-level)
|
||||||
|
|
||||||
|
`hive-c0re.nix` opens the per-agent web-port range
|
||||||
|
`8100..8999` in the host firewall **only when
|
||||||
|
`services.hyperhive.gateway.enable = false`**. With the gateway on
|
||||||
|
(default), it's the sole external entry point and proxies to
|
||||||
|
`127.0.0.1:<port>` internally — leaving the per-agent ports
|
||||||
|
firewall-open would defeat the single-front-door story (closes
|
||||||
|
#621).
|
||||||
|
|
||||||
|
Manager hashes into the same range since #753 (no more
|
||||||
|
"manager pinned at 8000" special case), so one range opening covers
|
||||||
|
every container.
|
||||||
|
|
||||||
|
The dashboard port (`cfg.dashboardPort`, default 7000) is *not*
|
||||||
|
listed in either case — since #652 it binds `127.0.0.1` only, so a
|
||||||
|
firewall hole would be a no-op. Remote dashboard access flows
|
||||||
|
through the gateway. Operators who opt out of the gateway lose
|
||||||
|
external dashboard reach by design — the surface is privileged
|
||||||
|
(approve / deny / destroy) and must not be exposed without a real
|
||||||
|
reverse proxy in front.
|
||||||
|
|
||||||
|
## `HIVE_FORGE_URL`: loopback for in-cluster, sub-domain for the operator
|
||||||
|
|
||||||
|
Agents poll `HIVE_FORGE_URL` for Forgejo notifications + run all
|
||||||
|
`hive-forge` calls against it. `hive-c0re.nix` pins this to
|
||||||
|
`http://127.0.0.1:<forge.httpPort>` for the in-cluster path: every
|
||||||
|
agent container shares the host's network namespace, so loopback
|
||||||
|
reaches the forge container directly with no DNS lookup needed
|
||||||
|
(closes #761).
|
||||||
|
|
||||||
|
The post-#754 sub-domain default (`forge.<hive-domain>`) is for
|
||||||
|
**operator browsers + cross-host clients**, not in-cluster traffic.
|
||||||
|
Using the sub-domain URL inside agent containers would fail every
|
||||||
|
`hive-forge` invocation with "Name or service not known" — the
|
||||||
|
agent's nspawn doesn't have DNS for the external hostname.
|
||||||
|
|
||||||
|
## hive-forge container shape
|
||||||
|
|
||||||
|
Private Forgejo wrapped in a nixos-container (`hive-forge`, not
|
||||||
|
`h-*` — keeps c0re's lifecycle scanner out of the picture; the
|
||||||
|
operator manages it via the standard `nixos-container` CLI).
|
||||||
|
Container shares the host network namespace
|
||||||
|
(`privateNetwork = false`) so agents reach the forge at
|
||||||
|
`http://localhost:<httpPort>` without extra plumbing — nixos-container
|
||||||
|
is here for state + systemd-unit isolation, not network isolation.
|
||||||
|
|
||||||
|
State lives at `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/`
|
||||||
|
and survives container restart / host reboot. To wipe, destroy the
|
||||||
|
container.
|
||||||
|
|
|
||||||
|
|
@ -238,28 +238,9 @@ in
|
||||||
managerToplevel
|
managerToplevel
|
||||||
];
|
];
|
||||||
|
|
||||||
# Per-container web UIs share the host's network namespace and need
|
# Open the per-agent web-port range when the gateway is *off* —
|
||||||
# their ports reachable when there's no gateway in front. Every
|
# otherwise the gateway nginx is the sole external entry point.
|
||||||
# container — including the manager (#753 dropped the pre-#753
|
# See `docs/gateway.md::Firewall posture (host-level)`.
|
||||||
# "manager pinned at 8000" special case) — hashes into
|
|
||||||
# 8100..8999 via `lifecycle::agent_web_port`'s FNV-1a, so a single
|
|
||||||
# range opening covers all of them.
|
|
||||||
#
|
|
||||||
# The dashboard port (`cfg.dashboardPort`, default 7000) is *not*
|
|
||||||
# listed here — since #652 the dashboard binds `127.0.0.1` only,
|
|
||||||
# so opening the firewall hole would be a no-op. Remote dashboard
|
|
||||||
# access flows through hive-gateway (default-on); operators who
|
|
||||||
# opt out of the gateway lose external dashboard reach by design —
|
|
||||||
# the surface is privileged (approve / deny / destroy) and must
|
|
||||||
# not be exposed without a real reverse proxy in front.
|
|
||||||
#
|
|
||||||
# When `services.hyperhive.gateway.enable = true` (the default), the
|
|
||||||
# gateway nginx is the sole external entry point and proxies to
|
|
||||||
# `127.0.0.1:7000` etc. internally — leaving the per-agent ports
|
|
||||||
# open in the host firewall would defeat the gateway's "single
|
|
||||||
# front door" story (closes #621). Operators who opt out of the
|
|
||||||
# gateway still get those direct ports opened so the legacy
|
|
||||||
# `http://<host>:<port>/` flow works.
|
|
||||||
networking.firewall = lib.mkIf (!config.services.hyperhive.gateway.enable) {
|
networking.firewall = lib.mkIf (!config.services.hyperhive.gateway.enable) {
|
||||||
allowedTCPPortRanges = [
|
allowedTCPPortRanges = [
|
||||||
{
|
{
|
||||||
|
|
@ -307,20 +288,11 @@ in
|
||||||
HYPERHIVE_SWARM_NAME = config.services.hyperhive.swarmName;
|
HYPERHIVE_SWARM_NAME = config.services.hyperhive.swarmName;
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs config.services.hyperhive.forge.enable {
|
// lib.optionalAttrs config.services.hyperhive.forge.enable {
|
||||||
# Agents poll this URL for Forgejo notifications + run all
|
# Loopback for in-cluster calls (agents share host netns;
|
||||||
# `hive-forge` calls against it. Pinned to `127.0.0.1` for
|
# external `forge.<hive>` sub-domain isn't DNS-resolvable
|
||||||
# the in-cluster path: every agent container shares the
|
# from inside nspawn). See
|
||||||
# host's network namespace so loopback reaches the forge
|
# `docs/gateway.md::HIVE_FORGE_URL: loopback for in-cluster,
|
||||||
# container directly, no DNS lookup needed (closes #761).
|
# sub-domain for the operator`.
|
||||||
#
|
|
||||||
# Post-#754 `cfg.domain` defaults to `forge.<hive-domain>`
|
|
||||||
# for the external gateway vhost. Using that value here
|
|
||||||
# would route every in-cluster call through DNS for an
|
|
||||||
# external hostname agents can't resolve from inside their
|
|
||||||
# nspawn — every `hive-forge` invocation would fail with
|
|
||||||
# "Name or service not known". The external gateway URL
|
|
||||||
# is for operator browsers + cross-host clients; internal
|
|
||||||
# callers stay on loopback.
|
|
||||||
HIVE_FORGE_URL = "http://127.0.0.1:${toString config.services.hyperhive.forge.httpPort}";
|
HIVE_FORGE_URL = "http://127.0.0.1:${toString config.services.hyperhive.forge.httpPort}";
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs config.services.hyperhive.matrix.gui.enable {
|
// lib.optionalAttrs config.services.hyperhive.matrix.gui.enable {
|
||||||
|
|
|
||||||
|
|
@ -30,21 +30,10 @@ let
|
||||||
effectiveRootUrl = if cfg.rootUrl != null then cfg.rootUrl else defaultRootUrl;
|
effectiveRootUrl = if cfg.rootUrl != null then cfg.rootUrl else defaultRootUrl;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# Private Forgejo for hyperhive agents, wrapped in a nixos-container
|
# Private Forgejo in a `hive-forge` nixos-container, shared host
|
||||||
# so it doesn't fight any `services.forgejo` the operator already
|
# netns so agents reach it on loopback. State at
|
||||||
# runs on the host. The container shares the host network namespace
|
# `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` survives
|
||||||
# (`privateNetwork = false`) so agents reach the forge at
|
# restart. See `docs/gateway.md::hive-forge container shape`.
|
||||||
# `http://localhost:<httpPort>` without any extra plumbing —
|
|
||||||
# nixos-container is just here for state + systemd-unit isolation,
|
|
||||||
# not network isolation.
|
|
||||||
#
|
|
||||||
# Container name is `hive-forge` (not `h-*`), so hive-c0re's
|
|
||||||
# lifecycle scanner ignores it; the operator manages it via the
|
|
||||||
# standard `nixos-container` CLI.
|
|
||||||
#
|
|
||||||
# State lives at `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/`
|
|
||||||
# and survives container restart / host reboot. To wipe, destroy the
|
|
||||||
# container.
|
|
||||||
|
|
||||||
options.services.hyperhive.forge = {
|
options.services.hyperhive.forge = {
|
||||||
enable = lib.mkOption {
|
enable = lib.mkOption {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue