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
51
lib/images/macos/templates/software/default.nix
Normal file
51
lib/images/macos/templates/software/default.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Software installation templates.
|
||||
# pkg — install a flat/distribution .pkg offline from the PE (`installer -target`)
|
||||
# app — copy an .app bundle (from a directory or zip) into /Applications offline
|
||||
# script — run a shell script as root on the booted image (network available)
|
||||
{ pkgs, lib, ... }:
|
||||
rec {
|
||||
pkg = { name, src, choices ? null }: {
|
||||
name = "pkg-${name}";
|
||||
files = [ { source = src; name = "${name}.pkg"; } ]
|
||||
++ lib.optional (choices != null) { source = choices; name = "${name}.choices.xml"; };
|
||||
script = ''
|
||||
echo "vmix: installing ${name}.pkg into $SYS"
|
||||
installer -verboseR -pkg "$V/${name}.pkg" -target "$SYS" \
|
||||
${lib.optionalString (choices != null) ''-applyChoiceChangesXML "$V/${name}.choices.xml"''} \
|
||||
|| pe_fail "installer ${name}.pkg"
|
||||
'';
|
||||
};
|
||||
|
||||
app = { name, src }: {
|
||||
name = "app-${name}";
|
||||
files = [ { source = src; name = "${name}.app"; } ];
|
||||
script = ''
|
||||
echo "vmix: copying ${name}.app to $DATA/Applications"
|
||||
mkdir -p "$DATA/Applications"
|
||||
rm -rf "$DATA/Applications/${name}.app"
|
||||
ditto "$V/${name}.app" "$DATA/Applications/${name}.app" || pe_fail "ditto ${name}.app"
|
||||
chown -R 0:80 "$DATA/Applications/${name}.app"
|
||||
xattr -dr com.apple.quarantine "$DATA/Applications/${name}.app" 2>/dev/null || true
|
||||
'';
|
||||
};
|
||||
|
||||
script = { name, script, files ? [], network ? true }: {
|
||||
name = "script-${name}";
|
||||
inherit files network;
|
||||
bootScript = script;
|
||||
};
|
||||
|
||||
# Homebrew (needs network; installs for the console user or the given user)
|
||||
homebrew = { user ? null, formulae ? [], casks ? [] }: {
|
||||
name = "homebrew";
|
||||
bootScript = ''
|
||||
U=${if user == null then "$CONSOLE_USER" else user}
|
||||
[ -n "$U" ] || { echo "vmix: no user to install Homebrew for"; exit 1; }
|
||||
launchctl asuser "$(id -u "$U")" sudo -u "$U" env NONINTERACTIVE=1 \
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || exit 1
|
||||
B=/usr/local/bin/brew
|
||||
${lib.optionalString (formulae != []) ''launchctl asuser "$(id -u "$U")" sudo -u "$U" $B install ${lib.escapeShellArgs formulae} || exit 1''}
|
||||
${lib.optionalString (casks != []) ''launchctl asuser "$(id -u "$U")" sudo -u "$U" $B install --cask ${lib.escapeShellArgs casks} || exit 1''}
|
||||
'';
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue