macOS: guest agent, online templates, virtio-fs shares, persistent home volume
Apple's built-in QEMU guest agent (AppleQEMUGuestAgent, launched by launchd when a virtio console port org.qemu.guest_agent.0 appears; guest-exec as root) is attached by vmix run --macos and the NixOS module. AppleVirtIO.kext on x86 Tahoe drives virtio-fs, block, console, input, net — verified in QEMU. - customizeImage: `bootScript` — online step through the guest agent (driver mode qga): boot the image, run the script as root with the VMIX volume, shut down through the agent. `as_user` runs commands in the logged-in session. - templates.software: pkg/app (offline in the PE), script/homebrew (online). - templates.profile.settings: widgets, wallpaper (pinned desktoppr — Apple Events need TCC consent that a headless session cannot give), dock apps, autohide, dark mode, hidden files. - generalize: persistHome (fstab LABEL=vmix-home /Users), hideWidgets offline. - formatVolume: formats a blank disk image as APFS by booting the PE (~35 s); idempotent. - NixOS module: macos.guestAgent (/run/vmix/qga-<name>.sock), shares via virtiofsd + vhost-user-fs (Apple automount tag for the first share, others mounted through the agent), macos.homeDisk (created + formatted on first start, virtio-blk), SPICE keeps -vga vmware for macOS. - CLI: vmix run --macos --share DIR --home FILE --qga PATH. - qemu.nix helpers; README section. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XsESshRCoBoUVWV9qKURUF
This commit is contained in:
parent
50ad8d521c
commit
0f9373263d
13 changed files with 600 additions and 19 deletions
44
cli.nix
44
cli.nix
|
|
@ -35,6 +35,9 @@ pkgs.writeShellScriptBin "vmix" ''
|
|||
echo " --ahci Use AHCI storage for vmix run (for laptop images)"
|
||||
echo " --macos macOS image for vmix run (OpenCore/VirtualSMC flags, AHCI)"
|
||||
echo " --applesmc with --macos: add QEMU's isa-applesmc (images built before 2026-09-09)"
|
||||
echo " --share DIR with --macos: virtio-fs share (first: /Volumes/My Shared Files); repeatable"
|
||||
echo " --home FILE with --macos: persistent home volume (qcow2, created+formatted if missing)"
|
||||
echo " --qga PATH with --macos: guest agent socket path (default /tmp/vmix-qga-<pid>.sock)"
|
||||
echo " --vnc DISPLAY VNC instead of SDL for vmix run, e.g. :10 (port 5910) or 0.0.0.0:10"
|
||||
echo " --mac ADDR NIC MAC for vmix run (macOS: read from the image's ESP by default)"
|
||||
echo " -y, --yes Skip disk write confirmation"
|
||||
|
|
@ -95,6 +98,10 @@ pkgs.writeShellScriptBin "vmix" ''
|
|||
RUN_MACOS=false
|
||||
RUN_VNC=""
|
||||
RUN_MAC=""
|
||||
RUN_SHARES=()
|
||||
RUN_HOME=""
|
||||
RUN_HOME_IMAGE="macos.images.tahoe.upstream"
|
||||
RUN_QGA=""
|
||||
while [[ ''${#} -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--mem) RUN_MEM="$2"; shift 2 ;;
|
||||
|
|
@ -102,6 +109,10 @@ pkgs.writeShellScriptBin "vmix" ''
|
|||
--ahci) RUN_AHCI=true; shift ;;
|
||||
--macos) RUN_MACOS=true; shift ;;
|
||||
--applesmc) RUN_APPLESMC=true; shift ;;
|
||||
--share) RUN_SHARES+=("$2"); shift 2 ;;
|
||||
--home) RUN_HOME="$2"; shift 2 ;;
|
||||
--home-image) RUN_HOME_IMAGE="$2"; shift 2 ;;
|
||||
--qga) RUN_QGA="$2"; shift 2 ;;
|
||||
--vnc) RUN_VNC="$2"; shift 2 ;;
|
||||
--mac) RUN_MAC="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
|
|
@ -136,8 +147,41 @@ pkgs.writeShellScriptBin "vmix" ''
|
|||
[[ -z "$RUN_MAC" || "$RUN_MAC" == "null" ]] && { RUN_MAC="52:54:00:c9:18:27"; echo "Warning: could not read MAC from image ESP, using $RUN_MAC"; }
|
||||
fi
|
||||
echo "macOS: yes (MAC $RUN_MAC)"
|
||||
# Apple's built-in QEMU guest agent: guest-exec as root over this socket
|
||||
[[ -z "$RUN_QGA" ]] && RUN_QGA="/tmp/vmix-qga-$$.sock"
|
||||
rm -f "$RUN_QGA"
|
||||
echo "Agent: $RUN_QGA (guest-exec as root)"
|
||||
# virtio-fs shares: the first one auto-mounts at /Volumes/My Shared Files, the
|
||||
# others are mounted with: mount -t virtiofs <tag> /Volumes/<tag>
|
||||
MACOS_SHARE_ARGS=""
|
||||
MACOS_MEM_ARGS=""
|
||||
i=0
|
||||
for SHARE in "''${RUN_SHARES[@]}"; do
|
||||
i=$((i + 1)); SOCK="/tmp/vmix-vfs-$$-$i.sock"; rm -f "$SOCK"
|
||||
TAG=$([[ $i -eq 1 ]] && echo "${macosQemu.automountTag}" || echo "share$i")
|
||||
${pkgs.virtiofsd}/bin/virtiofsd --socket-path="$SOCK" --shared-dir "$SHARE" --cache auto --sandbox none >/dev/null 2>&1 &
|
||||
for t in $(seq 1 50); do [[ -S "$SOCK" ]] && break; sleep 0.2; done
|
||||
MACOS_SHARE_ARGS="$MACOS_SHARE_ARGS -chardev socket,id=vfs$i,path=$SOCK -device vhost-user-fs-pci,chardev=vfs$i,tag=$TAG"
|
||||
MACOS_MEM_ARGS="-object memory-backend-memfd,id=vmix-mem,size=''${RUN_MEM}M,share=on -numa node,memdev=vmix-mem"
|
||||
echo "Share: $SHARE -> $([[ $i -eq 1 ]] && echo '/Volumes/My Shared Files' || echo "mount -t virtiofs $TAG ...")"
|
||||
done
|
||||
# persistent home volume (virtio-blk); created + formatted APFS by the PE if missing
|
||||
MACOS_HOME_ARGS=""
|
||||
if [[ -n "$RUN_HOME" ]]; then
|
||||
if [[ ! -e "$RUN_HOME" ]]; then
|
||||
echo "Home: creating $RUN_HOME (64G qcow2) and formatting it as APFS 'vmix-home' via the PE of $RUN_HOME_IMAGE ..."
|
||||
${pkgs.qemu}/bin/qemu-img create -q -f qcow2 "$RUN_HOME" 64G
|
||||
FMT=$(${pkgs.nix}/bin/nix build --no-link --print-out-paths --impure --expr "let l = (builtins.getFlake \"${self}\").lib.${system}; in l.macos.formatVolume { image = l.$RUN_HOME_IMAGE; }") || { echo "Error: could not build the formatter"; exit 1; }
|
||||
"$FMT" "$RUN_HOME" qcow2 || exit 1
|
||||
fi
|
||||
HOME_FMT=$(${pkgs.qemu}/bin/qemu-img info --output=json "$RUN_HOME" | ${pkgs.jq}/bin/jq -r .format)
|
||||
MACOS_HOME_ARGS="-drive id=home,if=none,format=$HOME_FMT,file=$RUN_HOME -device virtio-blk-pci,drive=home"
|
||||
echo "Home: $RUN_HOME (mounted at /Users by images generalized with persistHome)"
|
||||
fi
|
||||
echo ""
|
||||
exec ${pkgs.qemu}/bin/qemu-system-x86_64 \
|
||||
$MACOS_MEM_ARGS $MACOS_SHARE_ARGS $MACOS_HOME_ARGS \
|
||||
-device virtio-serial-pci,id=vmix-vser -chardev socket,path="$RUN_QGA",server=on,wait=off,id=vmix-qga -device virtserialport,chardev=vmix-qga,name=org.qemu.guest_agent.0 \
|
||||
$VMIX_DISPLAY \
|
||||
${macosQemu.deviceArgs} ${macosQemu.vgaArgs} \
|
||||
$([[ "$RUN_APPLESMC" == true ]] && echo '-device isa-applesmc,osk="${macosQemu.osk}"') \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue