Network Boot a VM on Your Mac

PXE boot an ARM64 VM in UTM on Apple Silicon. No ISO needed.

Boot Tracking

-
Successful Boots
-
Today

Recent Boots

Loading...

What You Need

An Apple Silicon Mac (M1/M2/M3/M4), UTM installed, and network access.

Setup Steps

1. Install UTM

Download from mac.getutm.app or install via Homebrew:

brew install --cask utm

2. Create a New VM

Open UTM and create a virtual machine configured for network boot:

# In UTM:
# 1. Click "+" → Virtualize → Other
# 2. Skip Boot ISO (leave empty) → Continue
# 3. Set RAM (4GB+) and CPU cores (2+) → Continue
# 4. Set disk size (32GB) → Continue
# 5. Save the VM
#
# Then edit VM settings:
# 6. Network → Change to "Bridged (Advanced)"
# 7. Select your active network interface (e.g., en0)
# 8. UEFI Boot should be enabled by default
Bridged networking is required for PXE boot. The default Shared Network (NAT) blocks PXE broadcasts. Select the interface connected to the same network as the bootstrap container.

3. Start the Bootstrap Container

On any machine on the same network (your Mac works fine), run:

# bootstrap.env (mode 600, outside any repo):
#   BOOTSTRAP_TOKEN=<random, 32+ chars — same value as the Worker secret>
#   BOOTSTRAP_ALLOWED_MACS=<this machine's MAC, comma-separated for more>
#   BOOTSTRAP_CLIENT_CIDR=192.168.1.0/24

# From the repo root (reads the same variables from the environment):
docker compose up

# Or standalone:
docker run --net=host --cap-add=NET_ADMIN \
  --env-file ./bootstrap.env \
  -e IPXE_SERVER_URL=https://ipxe.cloudcompute.com \
  -e DHCP_RANGE=192.168.1.0 \
  ghcr.io/fairchild/ipxe-bootstrap

This runs dnsmasq in proxy DHCP mode — it won't interfere with your existing router/DHCP — but it answers PXE only for allowlisted MACs, serves iPXE over TFTP, and runs a small boot proxy on :8080 that relays each machine's boot request to the Worker with the bootstrap bearer. The container fails closed if BOOTSTRAP_TOKEN or BOOTSTRAP_ALLOWED_MACS is missing.

4. Boot the VM

Press Play in UTM. The VM will PXE boot through this chain:

# Boot chain:
# 1. QEMU UEFI firmware (EDK2) → PXE DHCP request (answered only for an allowlisted MAC)
# 2. dnsmasq detects ARM64 (client-arch=11)
# 3. dnsmasq responds with ipxe-arm64.efi via TFTP
# 4. iPXE does DHCP again, gets the non-secret bootstrap.ipxe via TFTP
# 5. bootstrap.ipxe chains to the local boot proxy on :8080
# 6. Proxy adds the bearer, fetches /boot.ipxe from the Worker over HTTPS
# 7. Boot menu appears — or the role/install script if this MAC is assigned
# 8. Check-in recorded ✓

The VM's MAC is shown in UTM's network settings; put it in BOOTSTRAP_ALLOWED_MACS or the bootstrap ignores the VM entirely. The ephemeral RAM node boots after the countdown; arrow up to pick Debian ARM64.

5. Alternative: UEFI HTTP Boot (no bootstrap container)

UTM uses EDK2 firmware which supports HTTP Boot natively. Skip the bootstrap container entirely:

# In the VM's UEFI setup (press Escape at TianoCore logo):
# 1. Device Manager → Network Device List → select MAC
# 2. HTTP Boot Configuration
# 3. Boot URI: http://ipxe.cloudcompute.com/boot/ipxe-arm64.efi
# 4. Press F10 to save, then Reset

The VM fetches iPXE directly over HTTP — no TFTP, no proxy DHCP, no bootstrap container needed. Works with Shared Network (NAT) since it's a direct HTTP request.

This is the zero-infrastructure option. No Docker, no bootstrap container, no bridged networking. The VM just needs internet access. It reaches the public boot menu only: with no bootstrap proof on the request, an assigned MAC still gets the menu rather than its role or unattended install.

Troubleshooting

VM hangs at "Start PXE over IPv4"

PXE requires bridged networking. Check that the VM's network mode is set to Bridged (Advanced), not Shared Network. Select the correct network interface. Or try the HTTP Boot alternative (Step 5) which works with any network mode.

Menu shows but boot fails or hangs

This usually means architecture mismatch — an x86_64 kernel was loaded on an ARM64 VM. Verify the boot menu shows ARM64-specific entries (e.g., "Debian 12 (Bookworm)" under Operating Systems with no sbnb listed).

No iPXE prompt appears

The bootstrap container may not be running, may not be on the same network, or the VM's MAC may be missing from BOOTSTRAP_ALLOWED_MACS — dnsmasq ignores non-allowlisted clients silently. Check docker compose logs -f for the DHCP request and whether an offer followed it. Alternatively, use UEFI HTTP Boot (Step 5) which doesn't need the bootstrap container.

UEFI HTTP Boot option not available

Older UTM/QEMU versions may not expose HTTP Boot in the UEFI setup. Update UTM to the latest version, or use the bootstrap container method (Steps 3-4).