golang.org/x/build@v0.0.0-20240506185731-218518f32b70/env/darwin/aws/README.md (about) 1 # Darwin builders on AWS 2 3 Darwin builders on AWS run on [EC2 Mac 4 Instances](https://aws.amazon.com/ec2/instance-types/mac/), which are dedicated 5 Mac Mini hosts. These dedicated hosts must be allocated for at least 24 hours at 6 a time. They can be reimaged at any time while allocated, but the reimaging 7 process takes around an hour. Thus, for faster refresh time on hermetic 8 builders, we run buildlets as MacOS guests inside of QEMU on the dedicated 9 hosts. 10 11 ## Creating a dedicated host 12 13 Note that if you simply need more instances, an AMI with the final state is 14 saved on the AWS account. 15 16 To bring up a new host: 17 18 1. In the EC2 console, go to "Dedicated Hosts" -> "Allocate Dedicated Host". 19 2. Configure host type, zone. Instance family `mac1` is amd64; `mac2` is arm64. 20 3. Enable "Instance auto-placement", which allows any instance to run on this 21 host. 22 4. Once the host is allocated and available, go to the "Instances" page and 23 click "Launch an instance". 24 5. Select a macOS AMI. If starting fresh, select the latest macOS version from 25 "Quick Start". If simply adding more instances, a fully set-up AMI is saved 26 in "My AMIs". 27 6. Select a "Key pair" for SSH access. `ec2-go-builders` for official builders, 28 a custom key for testing. You will need the private key to login. 29 7. Configure a 200GB disk. 30 8. If creating from a fully set-up AMI, uncheck "Allow SSH Traffic". 31 9. Under "Advanced", select "Tenancy" -> "Dedicated host". 32 10. Other settings can remain at default. Launch instance. 33 34 If creating from a fully set-up AMI, you are done! 35 36 SSH with the key pair using the "Public IPv4 DNS" address from the "Instances" 37 page. This won't appear until the instance is booted. 38 39 ```sh 40 $ export KEY_PATH=~/.ssh/ec2-go-builders.pem 41 $ ssh -i $KEY_PATH ec2-user@$INSTANCE 42 ``` 43 44 [See the AWS 45 docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-mac-instances.html#mac-instance-vnc) 46 for setting up remote desktop access. Note that not all VNC client work with 47 Apple's server. [Remmina](https://remmina.org/) works. 48 49 The OS will only use 100GB of the disk by default. You must [increase the volume 50 size](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-mac-instances.html#mac-instance-increase-volume) 51 to utilize the full disk. This can be done while the disk is in use. 52 53 Continue below to create a new guest image, or [skip ahead](#guest-creation) to 54 use a pre-created image. 55 56 ## Creating a new guest image 57 58 Steps to create a new QEMU macOS guest image: 59 60 1. Build (`make dist`) or 61 [download](https://github.com/thenickdude/KVM-Opencore/releases) a copy of 62 the OpenCore bootloader from 63 https://github.com/thenickdude/KVM-Opencore. 64 1. Grab the `.iso.gz` file, `gunzip` it, and rename to `opencore.img` (it 65 is a raw disk image, not actually an `iso`). 66 2. Create a macOS recovery disk image: 67 1. Clone https://github.com/kholia/OSX-KVM. 68 2. `cd scripts/monterey && make Monterey-recovery.dmg` 69 3. Download the UTM QEMU fork and extract to `~/sysroot-macos-x86_64`. 70 1. Available as `Sysroot-macos-x86_64` in 71 https://github.com/utmapp/UTM/actions?query=event%3Arelease builds. 72 4. Create a disk image to install macOS to. 73 1. `DYLD_LIBRARY_PATH="$HOME/sysroot-macos-x86_64/lib" 74 "$HOME/sysroot-macos-x86_64/bin/qemu-img" create -f qcow2 75 macos-monterey.qcow2 128G` 76 5. Determine the magic Apple OSK value. 77 1. Either [read it directly from the machine](https://www.nicksherlock.com/2021/10/installing-macos-12-monterey-on-proxmox-7/#:~:text=Fetch%20the%20OSK%20authentication%20key), or [find it in some code](https://github.com/kholia/OSX-KVM/blob/master/OpenCore-Boot-macOS.sh#L45). 78 6. Copy the shell scripts from this directory to `$HOME`. 79 6. Use `$HOME/start-installer.sh macos-monterey.qcow2 opencore.img 80 Monetery-recovery.dmg $OSK_VALUE` to launch the macOS installer in QEMU. 81 82 NOTE: If networking isn't working on older versions of macOS, swap the 83 networking flag in `qemu.sh`. 84 85 This starts QEMU with the display on a VNC server at `localhost:5901`. Use SSH 86 port forwarding to forward this to your local machine: 87 88 ``` 89 $ ssh -i $KEY_PATH -L 5901:localhost:5901 -N ec2-user@$INSTANCE 90 ``` 91 92 Then use a VNC client to connect to `localhost:5901`. 93 94 1. Once connected, select "macOS Base Image" from the bootloader to launch the 95 installer. 96 2. In the installer, open the Disk Utility, find the ~128GB QEMU hard disk, 97 click "Erase", name it "macOS", and leave other options at the default 98 settings. 99 3. When formatting is complete, close Disk Utililty, and select "Reinstall 100 macOs Monterey". 101 4. Click through the installer. The VM will reboot a few times. When it does, 102 select "macOS Installer" from the bootloader to continue installation. 103 Installation is complete when "macOS Installer" is replaced with "MacOS". 104 5. Select "macOS" and go through the macOS setup as described in the [generic 105 setup notes](../setup-notes.md). 106 107 Once macOS is fully installed, we will install OpenCore on the primary disk and 108 configure it to autoboot to macOS. 109 110 1. In the guest, find the OpenCore and primary disks with `diskutil list`. 111 * The OpenCore disk contains only one parition, of type "EFI". e.g., it may 112 be /dev/disk0, EFI partition /dev/disk0s1. 113 * The primary disk contains two paritions, one of type "EFI", one of type 114 "Apple_APFS". e.g., it may be /dev/disk2, EFI partition /dev/disk2s1. 115 2. Copy the OpenCore EFI partition over the primary disk EFI partition. 116 * `sudo dd if=/dev/disk0s1 of=/dev/disk2s1` 117 3. Mount the primary disk EFI partition to edit the configuration. 118 * `sudo mkdir /Volumes/EFI` 119 * `sudo mount -t msdos /dev/disk2s1 /Volumes/EFI` 120 4. Open `/Volumes/EFI/EFI/OC/config.plist`. 121 * Change the Misc -> Boot -> Timeout option from `0` to `1` to set the 122 bootloader to automatically boot macOS with a 1s delay. 123 * In the `7C436110-AB2A-4BBB-A880-FE41995C9F82`, section, add `-v` to the 124 `boot-args` string value. This applies the `nvram` option mentioned in 125 [the setup notes](../setup-notes.md). 126 5. Shutdown the VM and boot it again with `start-mutable.sh`. 127 128 ```sh 129 $ $HOME/start-mutable.sh macos-monterey.qcow2 $OSK_VALUE 130 ``` 131 132 Now complete the remainder of the [machine setup](../setup-notes.md). For SSH 133 access, the guest should be reachable at 192.168.64.2 or 192.168.64.3 from the 134 host machine. 135 136 Copy complete images to `s3://go-builder-data/darwin/` for use on other 137 builders. 138 139 ## Set up automated guest creation {#guest-creation} 140 141 1. Download the latest image from `s3://go-builder-data/darwin/` and save it to 142 `$HOME/macos.qcow2`. 143 2. Download the UTM QEMU fork and extract to `~/sysroot-macos-x86_64`. 144 1. Available as `Sysroot-macos-x86_64` in 145 https://github.com/utmapp/UTM/actions?query=event%3Arelease builds. 146 3. Copy `bootptab` to `/etc/bootptab`. 147 4. 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`. 148 4. Build `golang.org/x/build/cmd/runqemubuildlet` and copy it to `$HOME`. 149 5. Create `$HOME/loop1.sh`: 150 151 ```sh 152 #!/bin/bash 153 154 while true; do 155 echo "Running QEMU..." 156 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" 157 done 158 ``` 159 160 4. Create `$HOME/loop2.sh`: 161 162 ```sh 163 #!/bin/bash 164 165 while true; do 166 echo "Running QEMU..." 167 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" 168 done 169 ``` 170 171 Replace `${OSK_VALUE?} with the OSK value described in the previous section. 172 173 5. Setup Automator: 174 1. Open Automator 175 2. File > New > Application 176 3. Add "Run shell script" 177 4. `open -a Terminal.app $HOME/loop1.sh` 178 5. Save to desktop twice as `run-builder1` 179 2. File > New > Application 180 3. Add "Run shell script" 181 4. `open -a Terminal.app $HOME/loop2.sh` 182 5. Save to desktop twice as `run-builder2` 183 184 Note that loop1.sh and loop2.sh guests will have a display at VNC port 5901 and 185 5902, respectively. 186 187 6. Setup login: 188 1. Users & Groups > ec2-user > Login Items > add run-builder1 189 2. Users & Groups > ec2-user > Login Items > add run-builder2 190 3. Users & Groups > Login Options > auto-login ec2-user 191 4. Desktop & Screensaver > uncheck show screensaver 192 193 Once image is set up and working, stop the instance and create an AMI copy of 194 the instance. On the EC2 "Instances" page, select the instance, and click 195 "Actions" -> "Image and templates" -> "Create Image". 196 197 Either create a new instance from this image with no SSH access, or edit the 198 instance networking inbound rules to remove SSH access. 199 200 201 ## References 202 203 * [EC2 Mac Instances USer 204 Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-mac-instances.html): 205 Contains most of the useful how-tos on working with Mac instances. 206 * [Remmina](https://remmina.org/): VNC client that works with Apple's [VNC 207 server](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-mac-instances.html#mac-instance-vnc) 208 (not all clients work). 209 * [QEMU MacOS install 210 guide](https://www.nicksherlock.com/2021/10/installing-macos-12-monterey-on-proxmox-7/): 211 Guide with similar instructions for MacOS in QEMU.