macOS: drive the install and all customization from a Recovery "PE", no GUI
Replace the screenshot/OCR/keystroke driving of Apple's Recovery with a "PE": BaseSystem.dmg (a journaled HFS+ volume, writable from Linux) with one LaunchDaemon added (makeRecoveryPE) that runs /Volumes/VMIX/run.sh as root at boot, records the status and powers off. launchd loads it alongside its signed cache (verified on Tahoe 26.6.2); same idea as AutoNBI/Imagr NetBoot images. - makeImage: the PE runs vmix-install.sh (erase, installer app, SharedSupport pkgdmg, startosinstall). Progress is read from the serial console (boot-args serial=3 -v, VMIX-* markers) and screenshots (brightness only). Fully offline; prepare now takes ~5 min instead of ~10. - customizeImage: boots the PE with the image attached and runs the template offline against the mounted System/Data volumes; OpenCore ScanPolicy restricted to HFS+/SATA so only the PE can boot. One PE boot ~30 s. The installed macOS is never booted for customization, so nothing depends on launchd/BTM approval or a first-boot agent (removed). - templates rewritten for offline use: generalize creates the user with dscl -f (admin, home, auto-login kcpassword, Setup Assistant suppression, hostname, locale, timezone, keyboard type, container resize); remote-access, no-updates, performance edit the target's plists. - makeBootDisk: build-time OpenCore variant (serial console, ScanPolicy). - vm-driver.py rewritten: passive observation only (serial markers, kernel boots, panics, brightness), disk+serial-aware hang watchdog, reboot-death reset, halt/loginwindow detection. No OCR/tesseract. - OpenCore: four SMBIOS DIMMs for MacPro7,1 (no "Memory Modules Misconfigured" warning). - tools/soak.sh: repeatability harness. Verified on daku: base install 23 min end to end; basic + generalize in three ~30 s PE boots; the result auto-logs into the desktop with the created user. Root cause of the "first-boot hang" (from the serial log): the guest's restart path panics (IOPlatformHaltRestartAction -> AppleSMC, SMCWDT smcWriteKey kSMCBadCommand, nested panic) because the pinned OSX-KVM Lilu disables itself on macOS 26, so VirtualSMC never loads. Handled by the driver (reset within 60 s); kext update to follow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XsESshRCoBoUVWV9qKURUF
This commit is contained in:
parent
58a317f5d2
commit
8dc8f4265d
24 changed files with 802 additions and 977 deletions
30
lib/images/macos/helpers/makeRecoveryPE.nix
Normal file
30
lib/images/macos/helpers/makeRecoveryPE.nix
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# The vmix "PE": Apple's Recovery (BaseSystem.dmg) with one LaunchDaemon added
|
||||
# that runs /Volumes/VMIX/run.sh as root at boot and powers off afterwards.
|
||||
# BaseSystem is a plain (journaled) HFS+ volume that Linux can write with the
|
||||
# hfsplus driver's force option — the pristine image's journal is empty, so this
|
||||
# is safe. The kernel and boot.efi are untouched; launchd loads the extra plist
|
||||
# from /System/Library/LaunchDaemons alongside its signed cache (verified on
|
||||
# Tahoe 26.6.2). Same idea as AutoNBI/Imagr NetBoot images.
|
||||
# Output: raw disk image (HFS+ volume with a partition table) that OpenCore boots.
|
||||
{ pkgs, lib, ... }:
|
||||
{ name ? "macos", recovery }:
|
||||
pkgs.runCommand "${name}-pe.img" {
|
||||
nativeBuildInputs = with pkgs; [ dmg2img libguestfs-with-appliance ];
|
||||
} ''
|
||||
echo "=== vmix: building the recovery PE from BaseSystem.dmg ==="
|
||||
dmg2img -s ${recovery} $out
|
||||
chmod +w $out
|
||||
guestfish -a $out <<GFS
|
||||
run
|
||||
mount-options force /dev/sda1 /
|
||||
mkdir-p /usr/libexec/vmix
|
||||
upload ${../guest/pe.sh} /usr/libexec/vmix/pe.sh
|
||||
chmod 0755 /usr/libexec/vmix/pe.sh
|
||||
upload ${../guest/ch.vmix.pe.plist} /System/Library/LaunchDaemons/ch.vmix.pe.plist
|
||||
chmod 0644 /System/Library/LaunchDaemons/ch.vmix.pe.plist
|
||||
ls /usr/libexec/vmix
|
||||
umount /
|
||||
GFS
|
||||
guestfish --ro -a $out -m /dev/sda1 ls /System/Library/LaunchDaemons | grep -q '^ch.vmix.pe.plist$' \
|
||||
|| { echo "vmix: PE hook not installed"; exit 1; }
|
||||
''
|
||||
Loading…
Add table
Add a link
Reference in a new issue