/dev/kvm present and accessible). Both Intel and AMD hosts work —
the same boot recipe applies to both; you never choose “OpenCore vs LongQT”.qemu-system-x86_64, qemu-nbd (from qemu-utils), and NBD kernel module support.go build -o cocoon-macos .
sudo install -m 755 cocoon-macos /usr/local/bin/cocoon-macos
scripts/doctor.sh)Run once per host. doctor.sh:
/dev/kvm and installs any missing dependencies (qemu, OVMF, gdisk, dosfstools, curl),nbd kernel module,<state-dir>/firmware — it downloads the LongQT OpenCore
release and bakes a GPT/ESP OpenCore.qcow2 plus the 4 MB OVMF CODE/VARS. Every VM reuses this
one firmware install. Firmware is built in a staging directory and only completed files are
published, so a failed provisioning attempt can be retried.sudo scripts/doctor.sh
vm run fails with a “run scripts/doctor.sh” message when the firmware is absent. You can override
any piece with --opencore / --ovmf-code / --ovmf-vars on the VM commands.
doctor.sh is a bash script, not the Go CLI: it reads $COCOON_MACOS_HOME only (there is no
--state-dir flag), and the LongQT OpenCore release it fetches is pinned by $LONGQT_VER (default
v0.7).
Use sudo cocoon-macos ... with the default root-owned state directory or host networking.
All persistent state lives under --state-dir / $COCOON_MACOS_HOME, default
/var/lib/cocoon-macos (mirroring cocoon’s /var/lib/cocoon):
/var/lib/cocoon-macos/
├── firmware/ # shared OpenCore.qcow2 + OVMF_CODE/VARS (from doctor.sh)
├── cloudimg/ # content-addressed golden-image store (image pull)
└── vms/
├── .locks/<name>.lock # per-VM lock, held across create/start/stop/rm
└── <name>/ # disk.qcow2 overlay, OVMF_VARS, OpenCore overlay, vm.json, sockets,
# data-<name>.qcow2 per --data-disk