Cut virtualization from the app: out of scope
Ham Lab is meant to be lightweight; VMs, passthrough and their consoles are too much. Removes the Virtualization tab, the incus package, the /api/virt routes, the instance.* sensors and their alert default, the virt-export command, the VGA console and the vendored spice-html5, and VIRTUALIZATION.md. A saved instance-down rule is dropped on load. Everything removed is kept, as it was, on the virtualization branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a2674bea6a
commit
d70ddb6d67
+10
-13
@@ -5,6 +5,9 @@ every place the code, defaults, docs or UI assume Mitchell's hosts, network, har
|
||||
distro, init system, orchestrator history or posture. **Nothing here is fixed yet** — this
|
||||
is the list to work from. Each item: where, what it assumes, what the general form is.
|
||||
|
||||
Virtualization was cut from the app 2026-10-15 (kept on the `virtualization` branch); its
|
||||
items — 1.8, 4.2, 5.1, 5.2, 6.14 and the Incus halves of 5.3, 5.7, 6.15, 10.3 — went with it.
|
||||
|
||||
Severity key: **A** breaks or misbehaves on an ordinary host · **B** works but is wrong by
|
||||
default or phones home to this lab · **C** cosmetic (placeholder text, comments, docs).
|
||||
|
||||
@@ -21,7 +24,6 @@ default or phones home to this lab · **C** cosmetic (placeholder text, comments
|
||||
| 1.5 | **C** | `examples/external-demo/index.html:8` `base: 'http://10.0.0.234:8100'` | Demo config names the hub's LAN IP. | `http://<hamlab-host>:8100`. |
|
||||
| 1.6 | **C** | `SENSORS.md:149` Prometheus target `10.0.0.234:8100`; `:187` `&machine=grid`; `:196-208` Glance examples at `hamlab.bigham.dev`, `zfs.tank.used_pct`, `/api/nodes/grid/...`; `:218-220` `grid,wyse`, `{"core":…,"grid":…,"mac":…}` | Docs use real host names, pool and domain. | Generic placeholders (`<host>`, `<machine>`, `<pool>`). |
|
||||
| 1.7 | **C** | `PLAN.md:3-4` "bare-metal Debian 13 host. First target: `core` (10.0.0.234)"; decisions table rows (Listen `10.0.0.234:8100`, Data `/home/core/apps/hamlab/`, Ingress NPM/`hamlab.bigham.dev`, Repo) | Product plan is written as this lab's plan. | Keep as history, or split lab facts out to `hamlet`. The repo is public. |
|
||||
| 1.8 | **C** | `VIRTUALIZATION.md:339-353` per-machine probe table; `:412, 425-436` `~/apps/hamlab`, `/tank/...`, boot NVMe free space | Plan is written against the five lab hosts. | Same as 1.7. |
|
||||
| 1.9 | **C** | `BUGS.md` throughout | Bug bashes narrate `core`, `grid`, `wyse`, `hamtv`, `gate`, the Mac. | History; fine to leave, but it is public. |
|
||||
| 1.10 | **C** | `cmd/hamlab/main.go:1` "Proxmox-style web console for a bare-metal Debian host"; `internal/hardware/hardware.go:5` "what Debian and its kin already have"; `internal/hardware/hardware.go:29` `// "GMKtec NucBox G3"`; `internal/metrics/metrics.go:1358` "did, on grid, 2026-10-02"; `internal/api/server.go:1382-1383` `["grid", …]`, `?machines=grid,wyse`; `internal/api/stacks.go:10` `/home/core/apps/dockhand/stacks/…`; `internal/api/dockersched.go:5` "unbound, nginx and pihole"; `internal/api/zfs.go:5` "grid already runs zfSnap"; `internal/storage/snapshots.go:6` "grid has run zfSnap v1.11.1"; `internal/api/guests.go:8` "Mitchell, 2026-09-27"; `internal/network/network.go:306` "the public address here is a DHCP lease"; `internal/metrics/gpu.go:17` "Asahi, today"; `internal/metrics/pciids.go:4-6` "the router's GPU"; `web/src/Top.tsx:522, 576`; `web/src/hashsel.ts:1-9`; `web/src/Embed.tsx:3` `&machine=grid` | Comments explain decisions by naming lab hosts. | Harmless, but rewrite the ones in package doc comments so a reader of the source doesn't need the lab to understand the code. |
|
||||
|
||||
@@ -60,7 +62,6 @@ The installer supports systemd, procd and OpenRC (`internal/setup/setup.go:217-2
|
||||
| # | Sev | Where | Assumes | General form |
|
||||
|---|---|---|---|---|
|
||||
| 4.1 | **A** | `internal/updates/updates.go:537-543` `Power()` | `systemctl reboot` / `systemctl poweroff`. On OpenWrt (`gate`) and OpenRC the Power dialog fails. | Try `systemctl`, else `reboot` / `poweroff` (busybox, OpenRC, sysvinit all have them). |
|
||||
| 4.2 | **A** | `internal/incus/incus.go:1017, 1044-1058, 1069, 1075` | The Incus install script writes `/etc/systemd/system/*` drop-ins and units, adds `SupplementaryGroups` to `hamlab.service`, restarts with `systemd-run`. On OpenRC/procd the daemon never joins `incus-admin` → the tab stays in "repair" forever; the Docker FORWARD fix is never persisted. `HamlabUnit = "hamlab.service"` (`:35`) is surfaced in the API (`:280`). | Branch on the detected init: OpenRC `rc-update`/`conf.d`, procd init script edits, or fall back to `usermod` + a daemon restart via the installer's own supervisor knowledge. Docker rules via a boot hook that is not a unit. |
|
||||
| 4.3 | **A** | `internal/services/services.go:163-170` | Services tab is systemd-only ("says so cleanly"). `gate` (procd) and any OpenRC/runit/s6 box have no Services tab. | `rc-service`/`rc-status` (OpenRC), `/etc/init.d/<x> status` + `ubus call service list` (procd), `sv` (runit) backends. Noted as "not done" in `PLAN.md:487-489`. |
|
||||
| 4.4 | **A** | `internal/cron/cron.go:353-373, 401, 442, 532-534, 669-670` | Jobs tab reads `/etc/crontab`, `/etc/cron.d`, `/var/spool/cron{,/crontabs}` (Debian/cronie), `/usr/sbin/anacron`, last-runs from **journald**, timers via `systemctl`; writes only `/etc/crontab` and `/etc/cron.d`. Busybox crond (OpenWrt, Alpine) keeps crontabs in `/etc/crontabs/<user>` and has no `cron.d` → the Jobs tab is empty on `gate` and schedules written by 4.5 never run. | Add `/etc/crontabs/*` as a source; last-runs from syslog/logread when there is no journal. |
|
||||
| 4.5 | **A** | `internal/storage/snapshots.go:402` `/etc/cron.d/hamlab-zfs`; `internal/api/dockersched.go:65` `/etc/cron.d/hamlab-docker` | ZFS snapshot and image-update schedules are cron.d files. No cron.d on busybox crond; no cron at all on a systemd-timer-only host (Fedora Server, CoreOS). | Detect: cron.d → cron.d; busybox → a line in `/etc/crontabs/<user>`; none but systemd → a timer unit. The daemon-side runner already exists (`hamlab zfs-snapshot`, `docker-update`). |
|
||||
@@ -74,13 +75,11 @@ The installer supports systemd, procd and OpenRC (`internal/setup/setup.go:217-2
|
||||
|
||||
| # | Sev | Where | Assumes | General form |
|
||||
|---|---|---|---|---|
|
||||
| 5.1 | **B** | `internal/incus/incus.go:213-250, 351-352` | Incus can be installed with apt, dnf, pacman, apk. **zypper is missing** (the Updates tab supports it), so an openSUSE host reads "No package manager Ham Lab knows how to drive". `opkg` is known only to say "not packaged for OpenWrt". | Add zypper; phrase the opkg case as "not packaged for this distribution". |
|
||||
| 5.2 | **B** | `internal/incus/incus.go:973-978` | dnf branch adds `qemu-system-x86-core`/`edk2-ovmf` or `qemu-system-aarch64-core`/`edk2-aarch64`; other arches (riscv64, ppc64le, which `IncusArch()` maps) get no QEMU. pacman and apk branches assume their package names never change. | Table per PM × arch, or let `incus` pull its own deps where the distro does that (Debian does). |
|
||||
| 5.3 | **B** | `internal/incus/incus.go:958, 970` `DEBIAN_FRONTEND`, `apt-get … -o Dpkg::Options::=--force-confold`; `internal/updates/updates.go:78, 432` | Debian-isms exported unconditionally. Harmless elsewhere. | Fine; note only. |
|
||||
| 5.3 | **B** | `DEBIAN_FRONTEND`, `apt-get … -o Dpkg::Options::=--force-confold` in `internal/updates/updates.go:78, 432` | Debian-isms exported unconditionally. Harmless elsewhere. | Fine; note only. |
|
||||
| 5.4 | **B** | `scripts/pci-ids-gpu.sh:7, 41` default `/usr/share/misc/pci.ids` | Debian's path for `pci.ids`; Fedora/Arch keep it in `/usr/share/hwdata/`. Build-time only. | Try both. |
|
||||
| 5.5 | **B** | `internal/api/status_sensors.go:283`, `internal/api/docker.go:133` | Container memory/CPU read from three cgroup paths: cgroup v2 + systemd driver, cgroupfs, libpod. cgroup v1 hosts (older Debian/Ubuntu, some Alpine, OpenWrt) get no `container.*.mem/cpu`. | Add the v1 `memory/docker/<id>` and `cpu,cpuacct` paths, or fall back to `docker stats --no-stream` once in a while. |
|
||||
| 5.6 | **B** | `internal/metrics/metrics.go:1064` `clkTck = 100` | USER_HZ assumed 100. True on every mainstream build; wrong on a kernel built otherwise. | `sysconf` via `getconf CLK_TCK` once at start. |
|
||||
| 5.7 | **B** | `internal/incus/subnet.go:150-179` `ip -j`; `internal/space/manager.go:578-585` `timeout -s KILL` | iproute2 JSON output (busybox `ip` has no `-j`); GNU `timeout`. | Parse plain `ip route`/`ip addr`; busybox has `timeout` too but flag spelling differs — use the context deadline. |
|
||||
| 5.7 | **B** | `internal/space/manager.go:578-585` `timeout -s KILL` | GNU `timeout`. | Busybox has `timeout` too but flag spelling differs — use the context deadline. |
|
||||
|
||||
## 6. Hardware and vendor assumptions
|
||||
|
||||
@@ -99,8 +98,7 @@ The installer supports systemd, procd and OpenRC (`internal/setup/setup.go:217-2
|
||||
| 6.11 | **B** | `internal/vpn/edit.go:5-7, 419-421` | Peers can be **created/edited only through OpenWrt UCI** "because that is where the server here is configured". A wg-quick server (the common case everywhere else) is read-only. | Write wg-quick `.conf` too (append a `[Peer]` block + `wg set`), guarded the same way. |
|
||||
| 6.12 | **B** | `internal/vpn/vpn.go:251-253` | Peer names come from wg-quick comments or UCI descriptions — "which between them cover every machine here". NetworkManager and systemd-networkd WireGuard configs are not read. | Add `.nmconnection` and `.netdev` readers. |
|
||||
| 6.13 | **B** | `internal/vpn/edit.go:515` `profile()` | Split-tunnel routes hard-code `10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12` on top of the tunnel's own prefix. | Offer the host's actual LAN prefixes (from `TakenPrefixes`-style route reading), with RFC 1918 as the fallback. |
|
||||
| 6.14 | **B** | `internal/incus/subnet.go:1-9, 23-34, 55`; `web/src/Virtualization.tsx:133` | Bridge subnet candidates skip **all of 10/8** because "this LAN is 10.0.0.0/8"; order is 172.16.100–254, then 192.168.254–200, then 172.16.1–99; last-resort `172.16.100.0/24`. Works anywhere, but a lab on 172.16/12 gets 192.168.x first and a lab on 192.168/16 never gets its own range. | Read the host's routes (already done) and pick from all three RFC 1918 blocks in a neutral order. |
|
||||
| 6.15 | **B** | `internal/network/network.go:170-199, 303-314`; `internal/incus/subnet.go`; `internal/vpn/edit.go:558-595`; `internal/tlsauto/tlsauto.go:533-537`; `install.sh:114-120`; `internal/setup/setup.go:648-666` | **IPv4 everywhere**: default route from `/proc/net/route` only, outside view v4 only, bridge/peer allocation v4 only, cert SANs v4 only, installer lists v4 addresses only. | `/proc/net/ipv6_route`, v6 SANs, v6 peer addresses. An IPv6-only host today has no gateway, no cert SAN and no bridge. |
|
||||
| 6.15 | **B** | `internal/network/network.go:170-199, 303-314`; `internal/vpn/edit.go:558-595`; `internal/tlsauto/tlsauto.go:533-537`; `install.sh:114-120`; `internal/setup/setup.go:648-666` | **IPv4 everywhere**: default route from `/proc/net/route` only, outside view v4 only, peer allocation v4 only, cert SANs v4 only, installer lists v4 addresses only. | `/proc/net/ipv6_route`, v6 SANs, v6 peer addresses. An IPv6-only host today has no gateway, and no cert SAN. |
|
||||
|
||||
## 7. Privilege and deployment posture (the lab's NOPASSWD-everywhere model)
|
||||
|
||||
@@ -134,7 +132,7 @@ The installer supports systemd, procd and OpenRC (`internal/setup/setup.go:217-2
|
||||
|---|---|---|---|---|
|
||||
| 10.1 | **B** | `Makefile:60-61, 442-443`; `scripts/gitea-release.sh` | Publishing is Gitea/Forgejo-only (release API shape). `selfupdate` also understands a static directory, so publishing could too. | `make release` + any static host is already enough; add a GitHub/Forgejo-agnostic `release-dir` note. |
|
||||
| 10.2 | **C** | `scripts/gitea-release.sh:500-515` | Needs `python3` on the publishing host. | `jq`, or do it in Go (`hamlab publish`). |
|
||||
| 10.3 | **C** | `Makefile:392` `ARCHES ?= amd64 arm64 arm 386 riscv64` | Fine. `ppc64le`/`s390x` are mapped by `IncusArch()` but never built. | Add or drop them from `IncusArch`. |
|
||||
| 10.3 | **C** | `Makefile:392` `ARCHES ?= amd64 arm64 arm 386 riscv64` | Fine. | — |
|
||||
|
||||
## 11. Things that are already general (checked, no change needed)
|
||||
|
||||
@@ -145,7 +143,6 @@ Listed so the sweep is known to be complete, not because they need work.
|
||||
- `internal/storage` block devices: `lsblk -J` with a `/sys/block` fallback, eMMC health, NVMe namespace folding, SMART only when `smartctl` exists.
|
||||
- `internal/metrics` CPU/mem/hwmon/thermal/net/disk/fs from `/proc` and `/sys`; remote-FS and pseudo-FS lists; filesystem statfs with a timeout.
|
||||
- `internal/hardware`: every reader may come back empty with a note; device-tree fallbacks for non-SMBIOS boards.
|
||||
- `internal/incus` detection and the per-machine "ready / repair / installable / unavailable" model (modulo 4.2, 5.1, 5.2).
|
||||
- `internal/nodes`, `internal/tlsauto`: hub ↔ node pairing, pinned certs, proxy, push.
|
||||
- `internal/sensors`, alerts, widgets, embeds, Prometheus: machine-agnostic by design.
|
||||
- `internal/files`, `internal/term`, `internal/tasks`, `internal/auth`, `internal/store`.
|
||||
@@ -158,7 +155,7 @@ Listed so the sweep is known to be complete, not because they need work.
|
||||
## Suggested order of work
|
||||
|
||||
1. **Posture and safety first (A):** 7.2 trusted proxies; 7.1 installer-written scoped sudoers; ~~3.1 drop the `:2375` probe (with 3.2 as its consequence)~~ done 2026-10-10.
|
||||
2. **"Any Linux" promises the README already makes (A):** 4.1 power, 4.4/4.5 cron on busybox and timer-only hosts, 4.2 Incus install on non-systemd, 4.3 a Services backend for OpenRC/procd, 2.10 the `tank` regex.
|
||||
2. **"Any Linux" promises the README already makes (A):** 4.1 power, 4.4/4.5 cron on busybox and timer-only hosts, 4.3 a Services backend for OpenRC/procd, 2.10 the `tank` regex.
|
||||
3. **Lab defaults that phone home or mislead (B):** 1.1–1.3 update/install URLs, 2.9 schedule defaults, 6.9/6.10 speed-test sources and an off switch, 8.1 memory limit, ~~3.3/9.2 stack home = DataDir~~ done 2026-10-10.
|
||||
4. **Breadth (B):** 5.1 zypper for Incus, 5.5 cgroup v1, 6.1/6.2 GPUs beyond Intel/AMD, 6.4 UPS order, 6.11/6.12 wg-quick/NetworkManager, 6.15 IPv6.
|
||||
5. **Cosmetics (C):** every placeholder and comment in §1.10 and §2, then split lab facts out of `PLAN.md`, `VIRTUALIZATION.md`, `SENSORS.md`, `README.md`.
|
||||
4. **Breadth (B):** 5.5 cgroup v1, 6.1/6.2 GPUs beyond Intel/AMD, 6.4 UPS order, 6.11/6.12 wg-quick/NetworkManager, 6.15 IPv6.
|
||||
5. **Cosmetics (C):** every placeholder and comment in §1.10 and §2, then split lab facts out of `PLAN.md`, `SENSORS.md`, `README.md`.
|
||||
|
||||
Reference in New Issue
Block a user