…
|
||
---|---|---|
.. | ||
README.md | ||
bootptab | ||
qemu.sh | ||
start-installer.sh | ||
start-mutable.sh | ||
start-snapshot.sh |
README.md
Darwin builders on AWS
Darwin builders on AWS run on EC2 Mac Instances, which are dedicated Mac Mini hosts. These dedicated hosts must be allocated for at least 24 hours at a time. They can be reimaged at any time while allocated, but the reimaging process takes around an hour. Thus, for faster refresh time on hermetic builders, we run buildlets as MacOS guests inside of QEMU on the dedicated hosts.
Creating a dedicated host
Note that if you simply need more instances, an AMI with the final state is saved on the AWS account.
To bring up a new host:
- In the EC2 console, go to "Dedicated Hosts" -> "Allocate Dedicated Host".
- Configure host type, zone. Instance family
mac1
is amd64;mac2
is arm64. - Enable "Instance auto-placement", which allows any instance to run on this host.
- Once the host is allocated and available, go to the "Instances" page and click "Launch an instance".
- Select a macOS AMI. If starting fresh, select the latest macOS version from "Quick Start". If simply adding more instances, a fully set-up AMI is saved in "My AMIs".
- Select a "Key pair" for SSH access.
ec2-go-builders
for official builders, a custom key for testing. You will need the private key to login. - Configure a 200GB disk.
- If creating from a fully set-up AMI, uncheck "Allow SSH Traffic".
- Under "Advanced", select "Tenancy" -> "Dedicated host".
- Other settings can remain at default. Launch instance.
If creating from a fully set-up AMI, you are done!
SSH with the key pair using the "Public IPv4 DNS" address from the "Instances" page. This won't appear until the instance is booted.
$ export KEY_PATH=~/.ssh/ec2-go-builders.pem
$ ssh -i $KEY_PATH ec2-user@$INSTANCE
See the AWS docs for setting up remote desktop access. Note that not all VNC client work with Apple's server. Remmina works.
The OS will only use 100GB of the disk by default. You must increase the volume size to utilize the full disk. This can be done while the disk is in use.
Continue below to create a new guest image, or skip ahead to use a pre-created image.
Creating a new guest image
Steps to create a new QEMU macOS guest image:
- Build (
make dist
) or download a copy of the OpenCore bootloader from https://github.com/thenickdude/KVM-Opencore.- Grab the
.iso.gz
file,gunzip
it, and rename toopencore.img
(it is a raw disk image, not actually aniso
).
- Grab the
- Create a macOS recovery disk image:
- Clone https://github.com/kholia/OSX-KVM.
cd scripts/monterey && make Monterey-recovery.dmg
- Download the UTM QEMU fork and extract to
~/sysroot-macos-x86_64
.- Available as
Sysroot-macos-x86_64
in https://github.com/utmapp/UTM/actions?query=event%3Arelease builds.
- Available as
- Create a disk image to install macOS to.
DYLD_LIBRARY_PATH="$HOME/sysroot-macos-x86_64/lib" "$HOME/sysroot-macos-x86_64/bin/qemu-img" create -f qcow2 macos-monterey.qcow2 128G
- Determine the magic Apple OSK value.
- Copy the shell scripts from this directory to
$HOME
. - Use
$HOME/start-installer.sh macos-monterey.qcow2 opencore.img Monetery-recovery.dmg $OSK_VALUE
to launch the macOS installer in QEMU.
NOTE: If networking isn't working on older versions of macOS, swap the
networking flag in qemu.sh
.
This starts QEMU with the display on a VNC server at localhost:5901
. Use SSH
port forwarding to forward this to your local machine:
$ ssh -i $KEY_PATH -L 5901:localhost:5901 -N ec2-user@$INSTANCE
Then use a VNC client to connect to localhost:5901
.
- Once connected, select "macOS Base Image" from the bootloader to launch the installer.
- In the installer, open the Disk Utility, find the ~128GB QEMU hard disk, click "Erase", name it "macOS", and leave other options at the default settings.
- When formatting is complete, close Disk Utililty, and select "Reinstall macOs Monterey".
- Click through the installer. The VM will reboot a few times. When it does, select "macOS Installer" from the bootloader to continue installation. Installation is complete when "macOS Installer" is replaced with "MacOS".
- Select "macOS" and go through the macOS setup as described in the generic setup notes.
Once macOS is fully installed, we will install OpenCore on the primary disk and configure it to autoboot to macOS.
- In the guest, find the OpenCore and primary disks with
diskutil list
.- The OpenCore disk contains only one parition, of type "EFI". e.g., it may be /dev/disk0, EFI partition /dev/disk0s1.
- The primary disk contains two paritions, one of type "EFI", one of type "Apple_APFS". e.g., it may be /dev/disk2, EFI partition /dev/disk2s1.
- Copy the OpenCore EFI partition over the primary disk EFI partition.
sudo dd if=/dev/disk0s1 of=/dev/disk2s1
- Mount the primary disk EFI partition to edit the configuration.
sudo mkdir /Volumes/EFI
sudo mount -t msdos /dev/disk2s1 /Volumes/EFI
- Open
/Volumes/EFI/EFI/OC/config.plist
.- Change the Misc -> Boot -> Timeout option from
0
to1
to set the bootloader to automatically boot macOS with a 1s delay. - In the
7C436110-AB2A-4BBB-A880-FE41995C9F82
, section, add-v
to theboot-args
string value. This applies thenvram
option mentioned in the setup notes.
- Change the Misc -> Boot -> Timeout option from
- Shutdown the VM and boot it again with
start-mutable.sh
.
$ $HOME/start-mutable.sh macos-monterey.qcow2 $OSK_VALUE
Now complete the remainder of the machine setup. For SSH access, the guest should be reachable at 192.168.64.2 or 192.168.64.3 from the host machine.
Copy complete images to s3://go-builder-data/darwin/
for use on other
builders.
Set up automated guest creation
- Download the latest image from
s3://go-builder-data/darwin/
and save it to$HOME/macos.qcow2
. - Download the UTM QEMU fork and extract to
~/sysroot-macos-x86_64
.- Available as
Sysroot-macos-x86_64
in https://github.com/utmapp/UTM/actions?query=event%3Arelease builds.
- Available as
- Copy
bootptab
to/etc/bootptab
. - Restart the system DHCP server to pick up the new
bootptab
:sudo /bin/launchctl unload -w /System/Library/LaunchDaemons/bootps.plist; sudo /bin/launchctl load -w /System/Library/LaunchDaemons/bootps.plist
. - Build
golang.org/x/build/cmd/runqemubuildlet
and copy it to$HOME
. - Create
$HOME/loop1.sh
:
#!/bin/bash
while true; do
echo "Running QEMU..."
sudo $HOME/runqemubuildlet -guest-os=darwin -macos-version=${MACOS_VERSION?} -osk=${OSK_VALUE?} -guest-index=1 -buildlet-healthz-url="http://192.168.64.101:8080/healthz"
done
- Create
$HOME/loop2.sh
:
#!/bin/bash
while true; do
echo "Running QEMU..."
sudo $HOME/runqemubuildlet -guest-os=darwin -macos-version=${MACOS_VERSION?} -osk=${OSK_VALUE?} -guest-index=2 -buildlet-healthz-url="http://192.168.64.102:8080/healthz"
done
Replace `${OSK_VALUE?} with the OSK value described in the previous section.
- Setup Automator:
- Open Automator
- File > New > Application
- Add "Run shell script"
open -a Terminal.app $HOME/loop1.sh
- Save to desktop twice as
run-builder1
- File > New > Application
- Add "Run shell script"
open -a Terminal.app $HOME/loop2.sh
- Save to desktop twice as
run-builder2
Note that loop1.sh and loop2.sh guests will have a display at VNC port 5901 and 5902, respectively.
- Setup login:
- Users & Groups > ec2-user > Login Items > add run-builder1
- Users & Groups > ec2-user > Login Items > add run-builder2
- Users & Groups > Login Options > auto-login ec2-user
- Desktop & Screensaver > uncheck show screensaver
Once image is set up and working, stop the instance and create an AMI copy of the instance. On the EC2 "Instances" page, select the instance, and click "Actions" -> "Image and templates" -> "Create Image".
Either create a new instance from this image with no SSH access, or edit the instance networking inbound rules to remove SSH access.
References
- EC2 Mac Instances USer Guide: Contains most of the useful how-tos on working with Mac instances.
- Remmina: VNC client that works with Apple's VNC server (not all clients work).
- QEMU MacOS install guide: Guide with similar instructions for MacOS in QEMU.