Skip to content

Managed Bootstrap Install App

Rod Christiansen edited this page Oct 8, 2026 · 2 revisions

Managed Bootstrap Install App

The package installs a settings app, Managed Bootstrap Install, at /Applications/Utilities/Managed Bootstrap Install.app. It edits BootstrapMate's machine-level preferences, starts a run and streams its output, and shows past runs. This page covers what each tab does, how it gets root without running as root, and why it may report the helper as unavailable. The app is optional: enrollment runs come from the LaunchDaemon and never touch it.

How it is put together

The app runs as the logged-in user. Everything that needs root goes through the privileged helper, BootstrapMateHelper, a LaunchDaemon (com.github.bootstrapmate.helper) that the package postinstall loads and that exposes the Mach service com.github.bootstrapmate.helper. The app asks the helper to do exactly two kinds of thing:

  • Run or stop the CLI. The helper launches managedbootstrapinstall from the same bundle with the arguments the app sends, streams each output line back, and reports the exit code. Stop sends the CLI SIGTERM, which closes SwiftDialog and records the run as interrupted.
  • Write or remove a preference in the com.github.bootstrapmate domain, at machine level (/Library/Preferences), which is where the CLI reads it.

The helper accepts a connection only from a client signed by its own Apple Team ID, and the system rechecks that on every message. An unsigned or ad-hoc signed bundle has no Team ID, so its helper refuses every connection. Because of that, standard users can use the app's Run tab on a signed build without being administrators, and nothing else on the Mac can drive the helper.

The window opens at 850 × 748 and has three tabs.

Prefs

The Prefs tab shows the app's name, description and links to this wiki and the issue tracker, then four groups of settings:

Group Settings Preference key
Connection Manifest URL, Authorization header, Follow HTTP redirects url, headers, followRedirects
Behavior Reboot after completion, Suppress console output, Enable verbose logging, Download and verify only, Only run userland scripts reboot, silentMode, verboseMode, dryRun, userscriptOnly
Dialog Show SwiftDialog UI during run, title, message, icon, Blur screen behind dialog enableDialog, dialogTitle, dialogMessage, dialogIcon, blurScreen
Advanced Keep downloaded payloads after a successful run, network timeout in seconds retainCache, networkTimeout

Changes save automatically about three quarters of a second after you stop typing, and a Saved label confirms the write. Saving is paused while a run is going. The Authorization header is saved only when a new value is entered, so an existing header is never shown or cleared by accident.

An eye button beside the Manifest URL field (Preview manifest content) fetches the URL, with the header, and shows the document in a popover.

A field whose key a configuration profile forces — under any of the key's accepted spellings — is disabled and shows a Managed label with a lock. The app does not try to save it, and the helper refuses the write if asked. Keys set locally, for example by an earlier save from this app, stay editable.

The file these values are written to, /Library/Preferences/com.github.bootstrapmate.plist, is also the file each run rewrites with its status, so a locally saved setting does not survive the next run. Deliver settings a run depends on by configuration profile; see Troubleshooting and Gotchas.

The helper writes only these fifteen keys, each only with its expected type. Any other key, a wrong type, another domain or a profile-forced key is refused, and the helper logs the refusal with NSLog.

The five Behavior toggles are overridden by the CLI on daemon-driven runs. A run started from this app passes --reboot, --silent and --dry-run when those toggles are on, and always passes --verbose; it never passes --userscript, so Only run userland scripts has no effect on any run. See Preferences.

Run

The Run tab has a Run Managed Bootstrap Install button, Stop, Clear, and a Debug toggle that shows or hides debug lines in the console view. A run started here always carries --verbose, plus flags built from the current Prefs: --jsonurl, --headers, --no-follow-redirects, --dry-run, --reboot, --silent, --no-dialog, and --dialog-title, --dialog-message or --network-timeout when those differ from their defaults. The output streams into the console view as it happens, and the tab ends on Completed or Failed (exit <code>).

The Run button is disabled, and the tab shows Helper not available, while the helper is not reachable. A run started here obeys the same single-run lock as any other: if a run is already going, the CLI exits at once.

Logs

The Logs tab lists runs from /Library/Managed Bootstrap/logs, newest first: one entry per session directory, showing that run's bootstrap.log, plus any flat per-run .log file at the logs root. A filter box narrows the lines shown, and sidebar buttons open the selected log in the default editor, open the logs folder in Finder, and reread the directory. With no runs yet, both panes fill the window: the sidebar names the logs directory and the detail pane says there are no logs yet. See Logging and Reporting.

Helper not available

When the app cannot reach the helper, check these in order:

  1. The bundle is signed with a Developer ID. The package from this repository's releases is unsigned, and its helper refuses every connection until the bundle is signed — see Building and Signing.
  2. The helper is loaded:
launchctl print system/com.github.bootstrapmate.helper
  1. The helper logs each connection it accepts or rejects, with the reason, to the unified log:
log show --predicate 'subsystem == "com.github.bootstrapmate.helper"' --last 1h

See also

Clone this wiki locally