Quickstart — Apple VZ via vfkit#
The Path C / menu-then-reboot flow on Apple Silicon. We'll use
vfkit — Apple's officially
supported front-end for Virtualization.framework — to boot an
immutable boot.iso against a writable menu-cache.raw cache
disk, then reboot into Debian Trixie.
Why this and not Path A#
VZ traps kexec_file_load(2) → Path A is out
VZ firmware has no HTTP/TCP/DHCP/DNS → Path B can't fetch plans
(the loader's networked phases
D–J were abandoned for VZ)
Path C: networking + FS walks happen in a Linux kernel
target loaded by firmware on next pass via BootOrder → ✓
See Architecture / hypervisors for the protocol matrix and a longer discussion.
1. Install vfkit + dependencies#
(QEMU is used as a build-time helper for the host-side tools; the runtime is vfkit.)
2. Build the immutable boot.iso#
cd cloud-boot/uki
go run . build \
--arch aarch64 \
--iso boot.iso \
--cmdline "cloudboot.exit=reboot cloudboot.plan=oci://ghcr.io/me/cloud-plan:prod"
The output is a hybrid GPT/El-Torito ISO. The El-Torito boot catalogue points at the UKI on the appended GPT FAT partition, so the same file boots equally from CD-ROM emulation, USB, or as a virtio-blk read-only disk.
3. Build the writable cache disk#
This creates a 256 MiB GPT disk with one FAT32 partition labelled
cloud-boot-cache. The label is what cloud-boot-init looks for
when staging targets. The script is idempotent — re-running it
won't clobber existing Boot#### entries.
4. Boot#
cd cloud-boot
vfkit \
--bootloader efi,variable-store=nvram.fd \
--device virtio-blk,path=uki/boot.iso,readonly \
--device virtio-blk,path=uki/menu-cache.raw \
--device virtio-blk,path=trixie.raw \
--device virtio-net,nat,mac=auto \
--device virtio-serial,logFilePath=vm.log
What happens:
- Firmware loads
\EFI\BOOT\BOOTAA64.EFIfromboot.iso(UKI). - UKI runs
cloud-boot-initas PID 1. - virtio-net comes up, init fetches the plan over OCI.
- The plan resolves to a target with
disksource pointing at/dev/vda3(or whichever virtio-blk index Trixie landed at). cloud-boot-initreads/boot/vmlinuz-*and/boot/initrd.img-*via the ext4 userland driver, writes them to\EFI\Linux\<target>-vmlinuz.efi+<target>-initrdon the cache ESP.- Writes
Boot0001(LoadOption pointing at<target>-vmlinuz.efiwithinitrd=<target>-initrd <cmdline>as load options) andBootOrder = [0001, ...existing]viaefivarfs. reboot(LINUX_REBOOT_CMD_RESTART).- vfkit restarts. UEFI Boot Manager honours
BootOrder, runs<target>-vmlinuz.efifrom the cache ESP, distro kernel takes over viaExitBootServices.
You'll see the bootstrap kernel boot once, then the Trixie kernel
boots immediately on the second pass — no second cloud-boot-init
run.
5. --gui framebuffer console#
vfkit can show the guest's framebuffer in a Cocoa window if the
guest kernel ships the right virtio-gpu drivers. The cloud kernel
variant already has them; see
kernel/cloud-arm64.config:
vfkit --gui \
--bootloader efi,variable-store=nvram.fd \
--device virtio-blk,path=uki/boot.iso,readonly \
--device virtio-blk,path=uki/menu-cache.raw \
--device virtio-blk,path=trixie.raw \
--device virtio-net,nat,mac=auto
A vfkit window opens showing the boot console. Useful for
keyboard-driven menus — cloudboot.exit=reboot without an
explicit cloudboot.target= puts the user at an interactive menu.
6. Reset to the menu#
Once a target has been staged, the firmware will keep booting it. To go back to the menu (e.g. to pick a different target), clear the NVRAM:
Troubleshooting#
| Symptom | Likely cause |
|---|---|
vfkit: error: bootloader: file not found: nvram.fd |
First run — vfkit creates nvram.fd automatically; re-run. |
Bootstrap kernel hangs at [init] virtio-net: timeout |
Plan URL unreachable. Confirm --device virtio-net,nat,mac=auto is present, that the host has internet, and that the registry doesn't require auth that you haven't supplied. |
| Second-pass kernel doesn't appear, vfkit keeps re-booting the UKI | The Boot0001 write failed. Check cloud-boot-init logs in vm.log. Common cause: menu-cache.raw doesn't have the cloud-boot-cache partition label. Re-run make-cache-disk.sh. |
findESPDevice: no partition labelled cloud-boot-cache |
Same as above. |
Next#
- OpenStack with Keystone AC for production plans.
- Reference / NVRAM reset for the full ceremony.
- Filesystem drivers / RAID discovery for what happens when the chained distro is on btrfs RAID or ZFS raidz.