docs(gateway): document per-agent static frontend split mode
This commit is contained in:
parent
e162c1a1fa
commit
e99330ef0f
1 changed files with 73 additions and 0 deletions
|
|
@ -234,6 +234,79 @@ State lives at `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/`
|
||||||
and survives container restart / host reboot. To wipe, destroy the
|
and survives container restart / host reboot. To wipe, destroy the
|
||||||
container.
|
container.
|
||||||
|
|
||||||
|
## Per-agent static frontend split
|
||||||
|
|
||||||
|
When `services.hyperhive.frontend` is configured, hive-c0re injects
|
||||||
|
`HIVE_AGENT_FRONTEND_DIR = "${cfg.frontend}/agent"` into its service
|
||||||
|
environment. The nginx include generator (`gateway_nginx::write`) reads
|
||||||
|
this variable and, when set, emits split location blocks per agent
|
||||||
|
instead of the legacy single-proxy block.
|
||||||
|
|
||||||
|
**Location priority for `/agent/<name>/...`:**
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# 1. Compiled assets — content-addressed nix store path, cache forever
|
||||||
|
location ^~ /agent/<name>/static/ {
|
||||||
|
alias <frontend>/static/;
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable, max-age=31536000";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 2. Static dist + proxy fallback for dynamic paths
|
||||||
|
location /agent/<name>/ {
|
||||||
|
alias <frontend>/;
|
||||||
|
try_files $uri $uri.html $uri/index.html @<name>_dynamic;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 3. Proxy catchall — API, events, icon, send, login, …
|
||||||
|
location @<name>_dynamic {
|
||||||
|
proxy_pass <upstream>;
|
||||||
|
proxy_set_header X-Forwarded-Prefix /agent/<name>;
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
error_page 502 503 504 = /__hive_agent_unreachable;
|
||||||
|
# … (full proxy header block)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**`try_files` resolution** (nginx applies the `alias` mapping before
|
||||||
|
checking file existence):
|
||||||
|
|
||||||
|
| request | resolved | outcome |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `/agent/iris/` | `<frontend>/index.html` | main agent page |
|
||||||
|
| `/agent/iris/stats` | `<frontend>/stats.html` | stats page |
|
||||||
|
| `/agent/iris/screen` | `<frontend>/screen.html` | screen page |
|
||||||
|
| `/agent/iris/static/app.js` | caught by `^~` block first | served with immutable cache |
|
||||||
|
| `/agent/iris/api/state` | no file match → `@iris_dynamic` | proxied to agent daemon |
|
||||||
|
| `/agent/iris/events/live` | no file match → `@iris_dynamic` | proxied (SSE) |
|
||||||
|
|
||||||
|
Adding a new HTML page to the frontend dist (`dist/<page>.html`)
|
||||||
|
automatically makes it reachable at `/agent/<name>/<page>` — no
|
||||||
|
generator change needed.
|
||||||
|
|
||||||
|
**Why `^~` for `/static/`**: the `^~` prefix gives this block higher
|
||||||
|
priority than the plain prefix `location /agent/<name>/`, so compiled
|
||||||
|
JS/CSS assets skip `try_files` entirely and get the immutable cache
|
||||||
|
headers. Nix store paths are content-addressed — the hash changes on
|
||||||
|
any content change — so `max-age=31536000` is safe.
|
||||||
|
|
||||||
|
**Why nix store is reachable from the gateway container**: nspawn
|
||||||
|
containers bind-mount `/nix/store` read-only by default. The
|
||||||
|
`HIVE_AGENT_FRONTEND_DIR` path is a nix store path baked in at
|
||||||
|
hive-c0re build time — the same path is visible to both c0re (writing
|
||||||
|
`agents.conf`) and the gateway nginx (serving files from it).
|
||||||
|
|
||||||
|
**Graceful degradation**: if `HIVE_AGENT_FRONTEND_DIR` is empty or
|
||||||
|
unset (e.g. a build that predates `cfg.frontend`), each agent gets the
|
||||||
|
legacy single-proxy block and all traffic is forwarded to the agent
|
||||||
|
daemon as before.
|
||||||
|
|
||||||
|
**`extraFiles`**: per-agent `hyperhive.frontend.extraFiles` are in
|
||||||
|
`mergedDist`, not in the base `cfg.frontend` dist. They are not under
|
||||||
|
the nix-store `alias` path, so requests for them fall through
|
||||||
|
`try_files` to `@<name>_dynamic` and are served by the agent daemon
|
||||||
|
as before.
|
||||||
|
|
||||||
## Per-agent error pages
|
## Per-agent error pages
|
||||||
|
|
||||||
`/agent/<name>/` requests hit two failure modes; both get static
|
`/agent/<name>/` requests hit two failure modes; both get static
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue