diff --git a/.ci/cirrus.vanilla.yml b/.ci/cirrus.vanilla.yml index ef510ec..95156c0 100644 --- a/.ci/cirrus.vanilla.yml +++ b/.ci/cirrus.vanilla.yml @@ -7,6 +7,8 @@ task: name: "Update Vanilla Image ($MACOS_VERSION)" env: matrix: + - MACOS_VERSION: tahoe + DISABLE_SIP_TEMPLATE: disable-sip-with-username.pkr.hcl - MACOS_VERSION: sequoia DISABLE_SIP_TEMPLATE: disable-sip-with-username.pkr.hcl - MACOS_VERSION: sonoma diff --git a/templates/vanilla-tahoe.pkr.hcl b/templates/vanilla-tahoe.pkr.hcl new file mode 100644 index 0000000..6a46036 --- /dev/null +++ b/templates/vanilla-tahoe.pkr.hcl @@ -0,0 +1,176 @@ +packer { + required_plugins { + tart = { + version = ">= 1.12.0" + source = "github.com/cirruslabs/tart" + } + ansible = { + version = "~> 1" + source = "github.com/hashicorp/ansible" + } + } +} + +source "tart-cli" "tart" { + from_ipsw = "https://updates.cdn-apple.com/2025SummerSeed/fullrestores/082-55592/95F6DA16-4116-491E-B332-7165C051E1C5/UniversalMac_26.0_25A5279m_Restore.ipsw" + vm_name = "tahoe-vanilla" + cpu_count = 4 + memory_gb = 8 + disk_size_gb = 50 + ssh_password = "admin" + ssh_username = "admin" + ssh_timeout = "300s" + boot_command = [ + # hello, hola, bonjour, etc. + "", + # Language: most of the times we have a list of "English"[1], "English (UK)", etc. with + # "English" language already selected. If we type "english", it'll cause us to switch + # to the "English (UK)", which is not what we want. To solve this, we switch to some other + # language first, e.g. "Italiano" and then switch back to "English". We'll then jump to the + # first entry in a list of "english"-prefixed items, which will be "English". + # + # [1]: should be named "English (US)", but oh well 🤷 + "italianoenglish", + # Select Your Country or Region + "united states", + # Transfer Your Data to This Mac + "", + # Written and Spoken Languages + "", + # Accessibility + "", + # Data & Privacy + "", + # Create a Mac Account + "Managed via Tartadminadminadmin", + # Enable Voice Over + "", + # Sign In with Your Apple ID + "", + # Are you sure you want to skip signing in with an Apple ID? + "", + # Terms and Conditions + "", + # I have read and agree to the macOS Software License Agreement + "", + # Enable Location Services + "", + # Are you sure you don't want to use Location Services? + "", + # Select Your Time Zone + "UTC", + # Analytics + "", + # Screen Time + "", + # Siri + "", + # Choose Your Look + "", + # Update Mac Automatically + "", + # Welcome to Mac + "", + # Disable Voice Over + "", + # Enable Keyboard navigation + # This is so that we can navigate the System Settings app using the keyboard + "Terminal", + "defaults write NSGlobalDomain AppleKeyboardUIMode -int 3", + "q", + # Now that the installation is done, open "System Settings" + "System Settings", + # Navigate to "Sharing" + "Sharing", + # Navigate to "Screen Sharing" and enable it + "", + # Navigate to "Remote Login" and enable it + "", + # Quit System Settings + "q", + # Disable Gatekeeper (1/2) + "Terminal", + "sudo spctl --global-disable", + "admin", + "q", + # Disable Gatekeeper (2/2) + "System Settings", + "Privacy & Security", + "", + "", + "admin", + "", + # Quit System Settings + "q", + ] + + // A (hopefully) temporary workaround for Virtualization.Framework's + // installation process not fully finishing in a timely manner + create_grace_time = "30s" + + // Keep the recovery partition, otherwise it's not possible to "softwareupdate" + recovery_partition = "keep" +} + +build { + sources = ["source.tart-cli.tart"] + + provisioner "shell" { + inline = [ + // Enable passwordless sudo + "echo admin | sudo -S sh -c \"mkdir -p /etc/sudoers.d/; echo 'admin ALL=(ALL) NOPASSWD: ALL' | EDITOR=tee visudo /etc/sudoers.d/admin-nopasswd\"", + // Enable auto-login + // + // See https://github.com/xfreebird/kcpassword for details. + "echo '00000000: 1ced 3f4a bcbc ba2c caca 4e82' | sudo xxd -r - /etc/kcpassword", + "sudo defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser admin", + // Disable screensaver at login screen + "sudo defaults write /Library/Preferences/com.apple.screensaver loginWindowIdleTime 0", + // Disable screensaver for admin user + "defaults -currentHost write com.apple.screensaver idleTime 0", + // Prevent the VM from sleeping + "sudo systemsetup -setsleep Off 2>/dev/null", + // Launch Safari to populate the defaults + "/Applications/Safari.app/Contents/MacOS/Safari &", + "SAFARI_PID=$!", + "disown", + "sleep 30", + "kill -9 $SAFARI_PID", + // Enable Safari's remote automation + "sudo safaridriver --enable", + // Disable screen lock + // + // Note that this only works if the user is logged-in, + // i.e. not on login screen. + "sysadminctl -screenLock off -password admin", + ] + } + + provisioner "shell" { + inline = [ + # Ensure that Gatekeeper is disabled + "spctl --status | grep -q 'assessments disabled'" + ] + } + + provisioner "shell" { + inline = [ + # Install command-line tools + "touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress", + "softwareupdate --list | sed -n 's/.*Label: \\(Command Line Tools .*\\)/\\1/p' | tr '\\n' '\\0' | xargs -0 -I {} softwareupdate --install '{}'", + "rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress", + ] + } + + provisioner "ansible" { + playbook_file = "ansible/playbook-system-updater.yml" + extra_arguments = [ + "-vvv", + ] + ansible_env_vars = [ + "ANSIBLE_TRANSPORT=paramiko", + "ANSIBLE_HOST_KEY_CHECKING=False", + ] + use_proxy = false + } +}