# The ISO → N machines path (appliance brief §4)
Status 2026-08-13, measured on henrik's T14s. The brief's ask: a documented,
tested path from "a per-site installer ISO built by the Build Thing" to
"N machines booted from it", and an honest answer on how it is proven without
real hardware. This is that document. Nothing here rebuilds the backend —
`backend-redfish` already does the three actions that matter, and
`plan_fleet()` already fans one spec into N.
## The path, end to end
```
1. BUILD (product repo, e.g. holger)
cargo xtask appliance-pack # the static app payload
cargo xtask installer-iso \
--param site=stockholm-7 \
--param hub_conf=@site7-hub.conf \
--sign dev # Secure Boot arming (see below)
→ .iso-out/holger-installer.iso # the declared [[build.installer]] cell,
# applied params ride the attested descriptor
2. HOST (operator step — draupnir does NOT serve files)
Redfish VirtualMedia.InsertMedia takes an "Image" the BMC PULLS over the
network (http/https/nfs URL) — never a local path. Serve .iso-out/ from a
depot the BMCs can reach; the URL is what goes in the spec:
https://depot.site7.example/holger-installer.iso
3. PLAN (draupnir, pure)
let spec = BootSpec::redfish_iso("site7-holger", iso_url, template_bmc);
let mut fleet = plan_fleet(&spec, N); # N members, names -1..-N
for (i, m) in fleet.iter_mut().enumerate() { # plan_fleet CLONES the
m.bmc = Some(BmcEndpoint { .. }); # template BMC — binding
} # each member to ITS OWN
# BMC is the CALLER's move
4. BURN (draupnir, backend-redfish)
let rf = RedfishBoot::new().with_password(secret) # secret at drive time,
.pin_cert_pem(bmc_cert); # never in a BootSpec
boot_fleet(&rf, &fleet) # per member:
# InsertMedia {"Image": iso_url, "Inserted": true, "WriteProtected": true}
# PATCH Boot {"BootSourceOverrideEnabled": "Once", "BootSourceOverrideTarget": "Cd"}
# ComputerSystem.Reset {"ResetType": "On"}
5. INSTALL (each machine, unattended)
korp-boot → pinned kernel → installer PID-1 → INSTALL-OK → reboot
→ first boot: korp-start mounts P3, load-or-MINTS the wg identity, prints
"wg-appliance identity: product=<p> pubkey=<44-char-b64>"
→ each machine registers its OWN public key with the hub.
```
## What is proven, and where
* **Fleet request shapes** — `redfish.rs` test
`a_fleet_of_three_shapes_the_same_burn_against_three_distinct_bmcs`:
`plan_fleet` × per-member BMC × the three request bodies/URLs, byte-shaped
against the same fixtures the per-request seam has always proven. RED arm:
`a_member_without_its_own_bmc_refuses_instead_of_borrowing_one`.
* **The install + first-boot mint, per machine, no hardware** — holger's
fleet KVM proof (`xtask/tests/installer_iso_fleet_kvm.rs`): ONE verb-built
ISO fanned via `plan_fleet`, each member installed under QEMU/OVMF and then
FIRST-BOOTED from its own disk; asserts N DISTINCT minted public keys. That
test rides korp-installer's `kvmproof` harness, NOT draupnir's KVM backend —
see the wall below.
* **Single-machine legs** (already green elsewhere): install to blank disk,
real-chain boot, RAID mirror, Secure-Boot signed-boots/unsigned-refused,
per-site params on the installed ESP, hub.conf byte-for-byte on P3.
## The walls, verbatim and dated (2026-08-13)
1. **No BMC and no Redfish HTTP mock is reachable on this box.** The live
HTTP exchange (send, status handling, response parsing) is UNMEASURED —
the wire-shape tests pin exactly the requests that would be sent, nothing
more. We do not fake a green: a mock BMC server is new capability §4
explicitly does not ask for. Open question for Rickard/Henrik: mannequin
(holger's mock-world: PKI+OIDC+Nexus) is the natural home for a minimal
Redfish mock if one is ever ruled in.
2. **Per-member credentials.** `Boot::boot` reads `spec.bmc` PER MEMBER
(proven), but the BMC password lives on the `RedfishBoot` instance — one
password per backend value. A fleet whose BMCs have DISTINCT passwords
needs one `RedfishBoot` per member (cheap, clonable) — or a shared
fleet-provisioning account. Deliberately not abstracted away: a credential
never rides a `BootSpec`.
3. **draupnir's KVM backend cannot boot an ISO** (`ImageSource::suits`: Iso →
Redfish only; the KVM arm boots kernel+rootfs or kernel+disk). The
no-hardware install proof therefore stays on korp-installer's `kvmproof`
harness — per §4's own clause ("where an existing harness already
hand-rolls qemu … do not break a working proof"; the move is bigger than
the task). NOTE: origin/main (this checkout is behind it) already carries
`BootSpec::kvm_bootloader_disk` — a firmware/bootloader disk boot with no
`-kernel` — which is the exact shape the INSTALLED-disk first-boot leg
needs; adopting it here awaits the main sync, and would move the first-boot
leg (not the ISO leg) onto draupnir's seam.
4. **SecureBoot/ResetKeys over Redfish: not driven, assessed SMALL.** Redfish
standardises a `SecureBoot` resource (PK/KEK/db) and a `ResetKeys` action;
draupnir's module is virtual media + power only. The request-shaping
pattern extends directly (one PATCH + one POST action URL, same
`post`/`patch` plumbing and fixtures) — deliberately not implemented per
the brief's own instruction ("report whether adding that to draupnir is
small; do not implement it unless the rest is done").
## Secure Boot on the burned ISO
The brief requires the shipped ISO SIGNED. The verb arms it: `--sign dev`
(throwaway dev identity) or `--sign <pkcs8-key>` beside
`$KORP_SECURE_BOOT_CERT` (production). The enforcing proof
(`installer_iso_secure_boot.rs`, green 2026-08-13): signed boots, unsigned
refused, foreign key refused. An unsigned ISO remains buildable for labs —
the per-site cell decides, and the build record carries the answer.