-
Notifications
You must be signed in to change notification settings - Fork 0
Setup Assistant and MDM Bootstrap
BootstrapMate's first phase runs inside a window most provisioning tools never see: after Remote Management enrollment, while Setup Assistant is still on screen and before anybody has logged in. This page describes what that environment actually offers and what falls out of it.
Setup Assistant is the first-boot experience a Mac shows after macOS installs or after an erase: language, region, network, then — on a Mac enrolled in Automated Device Enrollment (ADE) — the Remote Management screen, where the device contacts your MDM, receives its enrollment profile, and installs whatever the MDM has staged for enrollment. Only after that does Setup Assistant continue to account creation and the first user login.
Automated Device Enrollment means the device is claimed by your organisation in Apple's provisioning records, so the Remote Management screen appears automatically and the enrollment profile is applied without anybody typing an enrollment URL. Practically, it means your bootstrap package and your configuration profile are installed at a known point, early, unattended, and before a user exists.
That is where BootstrapMate's LaunchDaemon fires. RunAtLoad starts the CLI as root the
moment the postinstall loads the daemon.
- Root. The daemon runs as root. Anything that needs elevation works.
-
The system volume, and usually the data volume.
/Librarymay not be writable yet immediately after enrollment. -
A configuration profile — eventually. Profile delivery and package delivery are not
synchronised. The package can be running before the profile carrying
com.github.bootstrapmatehas landed. - Networking — eventually. The Mac had network in Setup Assistant to reach the MDM, but the interface state at daemon start is not guaranteed.
What does not exist:
-
No user. No console user, no login session, no home directory, no user defaults domain,
no Dock, no Finder.
SCDynamicStoreCopyConsoleUserreturns either nothing or one of the system placeholders (loginwindow,_mbsetupuser,root). -
No user-context anything. There is no
launchctl asusertarget, so nothing can be run as "the user" because there is no user. -
A read-only system temp directory. BootstrapMate downloads into memory and writes
payloads directly to each item's
filepath for exactly this reason.
Three waits at the top of every run absorb this timing, and none of them is fatal. Each logs and continues:
-
Network. A path monitor waits up to
--network-timeoutseconds (default 120) for a satisfied path. On timeout it does one synchronous DNS resolution as a last check, then logs eitherNetwork is availableorNetwork check timed out - proceeding anyway. -
Data volume. If
/Library/Managed Bootstrapis not writable, it polls/Libraryonce a second for up to 30 seconds, loggingData volume is now writable after NsorData volume still not writable after 30s - proceeding anyway. -
Management profile. Only when no
--jsonurlwas supplied and the configuration is not yet usable, it re-reads managed preferences once a second for up to 300 seconds, loggingStill waiting for management config... (Ns elapsed)every 30 seconds. On expiry it logsManagement configuration not received within 300sand continues — and then, with no manifest URL, exits 1.
-
Nothing in
preflightorsetupassistantmay assume a user. No~, no user defaults, no GUI, no Dock manipulation. Work that needs a user belongs inuserland. -
The
userlandstage blocks until somebody logs in. BootstrapMate polls every two seconds for a console user that is notloginwindow,_mbsetupuser,root, and does not begin with an underscore. There is no timeout on this wait — on a Mac that is never logged into, the run sits there. See Troubleshooting and Gotchas. -
userscriptitems run as root in the daemon context, not as the console user. Do not write a userland script that expects to be the user; derive the console user inside the script instead. This is covered in Troubleshooting and Gotchas. -
A failed
setupassistantitem does not abort the run. Failures are recorded, and the remaining items still run, because a single bad package must not strand provisioning. -
preflightis the escape hatch. Exactly onerootscriptis honoured there. Exit 0 and the entire bootstrap is skipped and the daemon torn down; exit greater than zero and the run continues. - The device may reboot out from under you. There is no resume state. See Stages for what each phase is for and what re-running costs.
On Windows the analogous window is the Out-of-Box Experience (OOBE) with the Autopilot Enrollment Status Page (ESP) on screen: same shape — device-context work, no user, MDM delivering payloads before anyone signs in — with different mechanics and, importantly, an ESP that will time out and show the user a failure, where Setup Assistant will not.
The sibling tool's page covers it: https://github.com/bootstrapmate/bootstrapmate-windows/wiki/Autopilot-and-the-ESP