Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09c1abe5b4 | ||
|
|
cb1a5cdbb8 |
1 changed files with 101 additions and 0 deletions
|
|
@ -8,6 +8,31 @@ let
|
|||
cfg = config.services.hyperhive.gateway;
|
||||
hyperhiveDomain = config.services.hyperhive.domain;
|
||||
matrixCfg = config.services.hyperhive.matrix;
|
||||
|
||||
# Per-agent port table for `/agent/<name>/` routing (#15 v0). Single-
|
||||
# sourced from `cfg.agentPortsFile` (default
|
||||
# `/var/lib/hyperhive/agent-ports.json`), written by hive-c0re on every
|
||||
# topology change in shape `{ "<name>": <port>, ... }`.
|
||||
#
|
||||
# Read at deploy time via `builtins.fromJSON (builtins.readFile ...)`
|
||||
# — pure eval (the file lives outside the nix store; nix copies the
|
||||
# content into the store as a fixed-output dep). When the file is
|
||||
# missing (fresh install before c0re has had a chance to write it),
|
||||
# default to an empty map → no per-agent routes generated → gateway
|
||||
# falls back to its pre-#15 shape. The container rebuilds on every
|
||||
# `hivectl gateway-sync` (operator-initiated) or on the next
|
||||
# `nixos-rebuild switch`, picking up whatever c0re has written
|
||||
# since the last build.
|
||||
#
|
||||
# mara on #740 (comment 9295) + #15 (comment 9270): the gateway
|
||||
# nginx container lives in system config (not meta), so it can't
|
||||
# auto-rebuild from meta-flake events — the JSON file is what
|
||||
# bridges the host's nix eval to the agent-lifecycle data c0re owns.
|
||||
agentPortsTable =
|
||||
if cfg.agentPortsFile == null || !builtins.pathExists cfg.agentPortsFile then
|
||||
{ }
|
||||
else
|
||||
builtins.fromJSON (builtins.readFile cfg.agentPortsFile);
|
||||
in
|
||||
{
|
||||
# Single nginx in front of every hyperhive surface (#609 / #15 v0).
|
||||
|
|
@ -117,6 +142,42 @@ in
|
|||
around. Requires `services.hyperhive.domain` to be set.
|
||||
'';
|
||||
};
|
||||
|
||||
agentPortsFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = "/var/lib/hyperhive/agent-ports.json";
|
||||
example = "/var/lib/hyperhive/agent-ports.json";
|
||||
description = ''
|
||||
Path to a JSON file mapping sub-agent names to their web ports
|
||||
for `/agent/<name>/` routing through the gateway (#15 v0).
|
||||
Shape: `{ "<name>": <port>, ... }`. Written by hive-c0re on
|
||||
every topology change (the rust side knows the canonical port
|
||||
allocation via `lifecycle::agent_web_port`; the gateway just
|
||||
reads what it's told).
|
||||
|
||||
For each `<name>: <port>` entry, the gateway adds a
|
||||
`location /agent/<name>/` block that `proxy_pass`es to
|
||||
`http://127.0.0.1:<port>/`. Empty / missing file → no
|
||||
per-agent routes generated → gateway falls back to its pre-#15
|
||||
shape (just `/` + matrix surfaces).
|
||||
|
||||
**Purely additive**: the old `http://<host>:<port>/` direct
|
||||
reach keeps working in parallel; this just gives the operator
|
||||
a single-origin route. Manager isn't included in the map (no
|
||||
per-agent prefix needed; manager already gets the `/` route
|
||||
via the c0re upstream block).
|
||||
|
||||
Set to `null` to disable per-agent routing entirely without
|
||||
creating the file. Set to a custom path if the operator's c0re
|
||||
writes the table elsewhere.
|
||||
|
||||
**Rebuild trigger**: the gateway container picks up new entries
|
||||
on the next `nixos-rebuild switch` (or `hivectl gateway-sync`
|
||||
if that helper lands). c0re writes are not auto-applied to a
|
||||
running gateway — see the follow-up in #15 for runtime nginx
|
||||
include + reload + eventual per-agent unix sockets.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
|
@ -248,6 +309,46 @@ in
|
|||
'';
|
||||
};
|
||||
}
|
||||
//
|
||||
# Per-agent UIs (#15 v0). One `/agent/<name>/`
|
||||
# block per `<name>: <port>` entry in
|
||||
# `agentPortsTable` (loaded from `cfg.agentPortsFile`
|
||||
# — `/var/lib/hyperhive/agent-ports.json` by default,
|
||||
# written by hive-c0re on every topology change).
|
||||
#
|
||||
# Trailing-slash pair (`/agent/<name>/` + `proxy_pass
|
||||
# http://...:<port>/`) strips the `/agent/<name>`
|
||||
# prefix on the upstream side, so the agent server
|
||||
# receives `GET /` for the SPA root, `GET /api/state`
|
||||
# for the API, `GET /screen/ws` for the websocket, etc.
|
||||
# The agent's emitted asset URLs are document-relative
|
||||
# (iris's #731) so they round-trip back through the
|
||||
# gateway under the same prefix without the harness
|
||||
# needing prefix-awareness.
|
||||
#
|
||||
# `X-Forwarded-Prefix` set so the harness can build
|
||||
# correct absolute URLs for any case where relative
|
||||
# isn't enough (server-emitted redirects, OG meta
|
||||
# tags, etc.).
|
||||
#
|
||||
# SSE / websocket support via `proxyWebsockets = true`
|
||||
# (same as the c0re `/` block below).
|
||||
#
|
||||
# Empty / missing `cfg.agentPortsFile` → empty table
|
||||
# → no per-agent blocks; old `<host>:<port>/` direct
|
||||
# reach still works.
|
||||
lib.mapAttrs' (name: port: {
|
||||
name = "/agent/${name}/";
|
||||
value = {
|
||||
proxyPass = "http://127.0.0.1:${toString port}/";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Prefix /agent/${name};
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 1d;
|
||||
'';
|
||||
};
|
||||
}) agentPortsTable
|
||||
// {
|
||||
# Everything else proxies to hive-c0re. Upgrade
|
||||
# headers stay set so SSE (`/dashboard/stream`,
|
||||
|
|
|
|||
Loading…
Reference in a new issue