# Smoke VM on Proxmox Test Host Every push to `main` builds a fresh ISO (`build-iso.yml`) and then boots it in a throwaway VM on the Proxmox test host — currently `192.168.178.165` — to confirm the live ISO boots and the webinstaller responds on `:5000`. If the smoke step fails, the ISO artifact is still uploaded and the VM is left running for post-mortem. The heavy lifting lives in [`scripts/smoke-vm.sh`](../scripts/smoke-vm.sh); the workflow just downloads the artifact and shells out. ## Where smoke VMs live - Node: whatever the test host reports as its node name (auto-detected) - VMID range: `9000–9099` (`PVE_TEST_VMID_MIN` / `PVE_TEST_VMID_MAX`) - Name: `furtka-smoke-<12-char-sha>` - Tags: `furtka`, `smoke`, `sha-<12-char-sha>` - MAC: `BC:24:11:` (Proxmox's OUI; lets the runner find the VM by scanning the LAN — the live ISO has no guest agent) - ISO on test host: `local:iso/furtka-.iso` Five most recent VMs (and their ISOs) are kept; anything older is stopped and purged (`destroy-unreferenced-disks=1`) on the next run. Tune via `PVE_TEST_KEEP`. ## Poking a failed smoke VM 1. Find it in the Proxmox WebUI — look for `furtka-smoke-` in the 9000-range. The VM is still running. 2. Console: **Console** tab in the WebUI (SPICE or noVNC). The webinstaller logs to `journalctl -u furtka-webinstaller.service` on the live ISO. 3. SSH: the live Arch ISO ships `sshd` enabled with no root password. Normally SSH as a LAN-reachable user is not possible without creds — use the WebUI console instead. (The **installed** system, post-wizard, has the `server` user with the password the wizard set.) 4. Fetch the short-sha from the VM name → cross-reference against `git log` to see exactly which commit built the failing ISO. ## Running a smoke test locally Needs LAN access to the test Proxmox and an API token with VM perms. ```bash PVE_TEST_HOST=192.168.178.165 \ PVE_TEST_TOKEN='user@pve!smoke=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \ ./scripts/smoke-vm.sh iso/out/furtka-*.iso ``` The script exits 0 on success, non-zero if the VM never served `http://:5000`. Pruning runs either way. ## Clearing the 9000-range by hand If smoke tests wedge or you want a clean slate: ```bash # List smoke VMs curl -sSk -H "Authorization: PVEAPIToken=${PVE_TEST_TOKEN}" \ https://192.168.178.165:8006/api2/json/nodes//qemu \ | python3 -c 'import json,sys; [print(v["vmid"],v["name"]) for v in json.load(sys.stdin)["data"] if 9000<=int(v["vmid"])<=9099]' # Destroy one curl -sSk -X POST -H "Authorization: PVEAPIToken=${PVE_TEST_TOKEN}" \ https://192.168.178.165:8006/api2/json/nodes//qemu//status/stop curl -sSk -X DELETE -H "Authorization: PVEAPIToken=${PVE_TEST_TOKEN}" \ "https://192.168.178.165:8006/api2/json/nodes//qemu/?purge=1&destroy-unreferenced-disks=1" ``` Or just run `scripts/smoke-vm.sh` with `PVE_TEST_KEEP=0` and any ISO — the prune step will sweep everything in the range except the one it just created. ## Proxmox API token setup (one-time) 1. WebUI → **Datacenter → Permissions → API Tokens → Add** 2. User: `root@pam` (or a dedicated `smoke@pve` user — see below) 3. Token ID: `smoke` 4. Uncheck **Privilege Separation** for the quick path, or keep it separated and grant explicit perms below 5. Save the displayed secret once — it's shown only here Minimum perms on `/` (if privilege-separated): `VM.Allocate`, `VM.Config.Disk`, `VM.Config.CPU`, `VM.Config.Memory`, `VM.Config.Network`, `VM.Config.Options`, `VM.Config.HWType`, `VM.Config.CDROM`, `VM.PowerMgmt`, `VM.Audit`, `Datastore.AllocateTemplate` (for ISO upload/delete on the `local` content store). Set the result as Forgejo secret `PVE_TEST_TOKEN` in the format: ``` user@realm!tokenid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ``` …and `PVE_TEST_HOST` as `192.168.178.165`. That's all the workflow needs. ## Assumptions - Runner has L2 reachability to `192.168.178.0/24` (MAC→IP discovery uses `arp-scan` from the runner). - Test host uses default storage names: `local` for ISOs, `local-lvm` for disks. Override via `PVE_TEST_ISO_STORAGE` / `PVE_TEST_DISK_STORAGE`. - Bridge `vmbr0` carries LAN DHCP. Override via `PVE_TEST_BRIDGE`. If any of those don't match, set the corresponding env var in `build-iso.yml` (via `env:` on the smoke step) or override on the CLI when running locally.