Skip to content

scripting: provision macOS guests on first boot - #7881

Merged
osy merged 1 commit into
mainfrom
feature/apple-guest-provisioning
Sep 20, 2026
Merged

osy merged 1 commit into
mainfrom
feature/apple-guest-provisioning

Conversation

@osy

@osy osy commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Summary

macOS 27 can set up a macOS guest without Setup Assistant: VZMacGuestProvisioningOptions creates the user account and can turn on automatic login and Remote Login. This makes "create a ready-to-use macOS VM" possible for CI and other automation. The guest only reads these options on the first boot after macOS is installed.

  • AppleScript: start vm provisioning {full name:"CI", username:"ci", password:"…", automatic login:true, remote login:true}
  • utmctl start vm --provision-username ci --provision-password-stdin --provision-auto-login --provision-ssh (also --provision-password and --provision-full-name). Reading the password from standard input keeps it out of the process list, and it is not echoed when typed at a terminal.
  • The options include a password, so they are a parameter to a single start and are never written to config.plist or the registry.
  • A request that cannot be honoured fails before the VM starts, so the first boot is not used up: not a macOS guest, not the Apple backend, a host older than macOS 27, an install that has not run yet, a saved state, recovery mode, or an account the framework rejects (the new 40001–40003 errors have their own messages).

This is only exposed to scripting because most users will never need it. There is no wizard or settings UI.

Notes for review:

  • On main the window controller restarts the guest automatically after an install, which is the first boot. A fully unattended flow therefore needs a scripted install such as scripting: add an install command for macOS guests #7863 (with scripting: allow creating macOS VMs with the Apple backend #7862 to create the VM): create → install → start with provisioning.
  • UTMScripting.swift contains only the regenerated start declaration, identical to the bridge-gen.sh output. The rest of the generator's current output is unrelated to this change (lower-cased class names, b'…' four-char-code comments, and members that were never regenerated on main), so it is left for a separate catch-up.
  • An older UTM ignores the unknown provisioning parameter and performs a normal start. utmctl ships inside the app bundle so the two stay in step.

Resolves #7757

Testing

Testing: Tested by a human on macOS 27.0 (26A428), Apple Silicon Mac. The author acknowledges that this change has been tested and/or reviewed by a human in accordance with UTM's AI contribution guidelines.

Verified on a fresh macOS 27.0 guest through both AppleScript and utmctl with the password on standard input: the guest boots to the desktop without Setup Assistant, and over SSH the account, full name, administrator rights and automatic login are as requested. Each rejected case fails before the VM starts and leaves it stopped, a saved state survives a rejected request, and the password does not appear in config.plist, the registry, preferences or logs. Starting without provisioning is unchanged for Apple and QEMU VMs.

@osy
osy force-pushed the feature/apple-guest-provisioning branch from bfe966c to 77aa6bc Compare September 19, 2026 15:46
@osy osy added this to the v5.0 milestone Sep 20, 2026
macOS 27 can create the guest's user account, turn on automatic login and
Remote Login without going through Setup Assistant, which lets CI and other
automation get a ready-to-use macOS VM. The guest only reads these options
on the first boot after macOS is installed and they include a password, so
they are passed as a parameter to a single start and are never saved to the
configuration or the registry.

This is only exposed to AppleScript (`start ... provisioning {...}`) and
utmctl (`start --provision-*`) because most users will never need it. utmctl
can read the password from standard input to keep it out of the process
list. Requests that cannot be honoured (not a macOS guest, host older than
macOS 27, install still pending, saved state, recovery mode, invalid account)
fail before the VM starts so the first boot is not used up.

UTMScripting.swift has only the regenerated `start` declaration. The rest of
the current bridge-gen.sh output is unrelated to this change.

Assisted-by: Claude:claude-fable-5-1
@osy
osy force-pushed the feature/apple-guest-provisioning branch from 77aa6bc to 602d8fc Compare September 20, 2026 03:26
@osy
osy merged commit 3af22be into main Sep 20, 2026
54 checks passed
@osy
osy deleted the feature/apple-guest-provisioning branch September 20, 2026 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support the new macOS VM provisioning API

1 participant