feat(nh3-svos): SVOS a737a06 refresh — app-terminal on its own mesh origin (svos-terminal.phasefinal.com), app-knowledge, app-postoffice units; quiesce hook covers the new units
This commit is contained in:
@@ -23,6 +23,37 @@ configuration, enrollment and acceptance.
|
||||
| App-consistent hook | svos-dev's `/etc/qemu/fsfreeze-hook.d/50-svos` stops the SVOS services on freeze and restarts the ones that were running on thaw. ⚠ **Debian's qemu-ga does NOT run fsfreeze hooks unless configured** (no `-F` in the unit, no `qemu-ga.conf` by default). Here `/etc/qemu/qemu-ga.conf` points it at **`/usr/local/sbin/fsfreeze-dispatch`** (`configs/qemu-ga/fsfreeze-dispatch`), which unlike the stock `/etc/qemu/fsfreeze-hook` propagates failure: if a freeze hook fails, it thaws that hook and the completed ones and exits 1, so qemu-ga refuses the freeze. **Live drill 2026-10-05 1952–1953 (services running):** quiesced backup `vm/111/2026-10-06T02:52:11Z` → kernel+interface down ~1–2 s, back by themselves, health ok. Refused freeze (temporary `60-drill-refuse` after 50-svos, since removed) `vm/111/2026-10-06T02:53:03Z` → the dispatcher unwound and restarted the services, and then **⚠ vzdump did NOT abort: it logged `ERROR: unable to freeze guest fs`, backed up UNFROZEN (crash-consistent, app live), and reported `Backup job finished successfully`, rc 0.** Both images mapped from PBS and mounted read-only (`ro,noload`) on nh3-pve-2, never booted: `svos.db` integrity ok (each image still carries its ~0.9 MB WAL: keep `-wal` with the db when restoring), interface `pins.sqlite3` integrity ok, config/key/config-generation hashes equal live, table counts equal live except `events`. **Monitoring:** `scripts/check-backup-freshness.sh` now reads the LOG of every OK vzdump task and reports ERROR lines; a freeze/thaw error is an APPLICATION-CONSISTENCY FAILURE, verdict **DEGRADED, exit 4** (alerted by the daily wrapper to infra-hermes). nh3-pve-2 was not in the check's node lists at all before 2026-10-05; it is now. Drill B is acknowledged by UPID in the script |
|
||||
| Monitoring | Beszel native agent 0.18.7 (`playbooks/beszel-native.yaml`, `configs/beszel-agent/hosts/nh3-svos.env`), hub system `t6y646ifa3x7xxv`, alerts CPU>95%/15m, Disk>85%/5m, Memory>90%/10m, offline/2m. Up 2026-10-05 |
|
||||
|
||||
## Release a737a06 + apps (2026-10-07, svos-dev thread `01M4D1GNYBW7QVY7RF05R412V2`, Prime's 2240 decision)
|
||||
|
||||
- **Release:** `/opt/svos/current` → `releases/a737a06` (previous `6c6abbe` kept: it cannot read schema 11, and the
|
||||
front door's previous-asset handle still points at it). Built by infra-ops from a clean `git archive`: 9 wheels,
|
||||
the `web/` 0.0.6 static build, `kernel-requirements.txt` (uv export) and `apps-requirements.txt` (uv pip compile
|
||||
against the kernel pins, hashed), `vendor/bifrost-1.2.1` (gitea vh index, sha256-verified, because PyPI has an
|
||||
unrelated `bifrost`), and `hermes-plugin/svos` (staged for U13). Kernel 0.0.5 migrated schema 9 → 11 on first start.
|
||||
- **Pre-change backups:** vzdump `vm/111/2026-10-08T06:02:14Z` (freeze/thaw clean) and an online sqlite `.backup`
|
||||
plus config, keys and app state at `/var/lib/svos/backup/pre-a737a06/` (integrity ok, user_version 9).
|
||||
- **Apps:**
|
||||
| slug | listener | unit | state |
|
||||
|---|---|---|---|
|
||||
| app-interface | 127.0.0.1:8403 | svos-interface | up |
|
||||
| app-knowledge | 127.0.0.1:8405 | svos-knowledge | up; Albok token `01M4D22HHJ7AJHX30WPDE02DFC`, vault `nh3-svos/albok-token-knowledge`, grants per A111 `read:fleet/memory`, `read:fleet/stash`, `read:personal/notes` (no wildcard, no restricted wing, no class grant) |
|
||||
| app-terminal | 127.0.0.1:8404, base_url **https://svos-terminal.phasefinal.com** | svos-terminal | **degraded by design**: no zellij and no fleet session on this box |
|
||||
| app-postoffice | 127.0.0.1:8406 | svos-postoffice (installed, NOT enabled) | declared + enrolled, stopped until Prime declares the bridge handle; `handle = "svos"` in its config is the example's placeholder |
|
||||
| app-miranda, svos-agent | — | — | packages in apps-env only (U13) |
|
||||
Credentials `/etc/svos/<app>.env` (root 0600); units in `configs/svos-apps/`; the quiesce hook lists all three new units.
|
||||
- **Terminal origin:** `svos-terminal.phasefinal.com` = headscale MagicDNS extra record → 100.64.0.9, its own Caddy
|
||||
site (LE via DNS-01). **No Basic auth** (Chromium cancels Basic prompts in cross-origin frames; the lease is the
|
||||
page's auth). `/verbs/*` and `/health` are refused unless they come from the box itself. The kernel's signed calls
|
||||
reach the app through Caddy, so nh3-svos resolves the name via `/etc/hosts` (`100.64.0.9 svos-terminal.phasefinal.com
|
||||
svos.phasefinal.com`): it has no MagicDNS (`accept-dns=false`). The terminal is `up` only while Caddy is.
|
||||
- **Acceptance 2026-10-07 ~2315:** 17/17 HTTPS controls through an SSH forward to the real listener (the 12 from 10-05,
|
||||
plus: health schema 11 with 2 up and 1 degraded; the terminal registered on its own origin; knowledge `wings`
|
||||
= exactly the 3 token wings; knowledge `search` hits; terminal `attach` refused `404 unknown seat`). Chromium
|
||||
phone + desk: shell, inbox, stream, reload, `/status`, `/graph`, `/feed`, no overflow, no page errors; desk
|
||||
"Open Terminal here" → pane open, framed from `https://svos-terminal.phasefinal.com/`, body `waiting` (no lease).
|
||||
From mesh peer fv-ml1, the terminal origin returns: `/` 200 with `frame-ancestors https://svos.phasefinal.com`;
|
||||
lease routes 401; `/verbs/*` and `/health` 403; anything else 404.
|
||||
|
||||
## Build (reproducible)
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user