Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

mikronova/draupnir

.nornir/iso-to-fleet.md

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

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.