-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ
The questions administrators ask in the first week, answered from the shipping behaviour. Where an answer turns on something surprising, it links to the page that covers it in full.
BootstrapMate is a Swift tool descended from an InstallApplications migration, and it
keeps the vocabulary: the same three stages (preflight, setupassistant, userland),
the same item types, and the same key names for hash, packageid, version, retries,
retrywait and donotwait. What it adds is package signature verification with
expectedTeamID and allowUnsigned, YAML manifests alongside JSON, a SwiftDialog
progress window, per-phase status files and an optional run-summary POST. The most
important difference in practice is spelling: manifest keys decode against Swift property
names, so it is skipIf and followRedirects in camelCase, not skip_if.
No. BootstrapMate runs once, installs what the manifest lists, and deletes its own LaunchDaemon. It has no schedule, no check-in, no concept of uninstalling software and no awareness of what should be on the Mac tomorrow. The intended shape is that its manifest installs and configures Munki, and Munki manages the machine from then on. See Handoff to Munki.
It does not — there is no Munki-specific code anywhere in it. Installing munkitools,
writing Munki's preferences and putting Munki into bootstrap mode are all things you
author as ordinary manifest items, typically a package followed by a rootscript in the
setupassistant stage. That is deliberate; it is also why nothing in the tool will warn
you if you forget.
The run waits for a usable network path for up to --network-timeout seconds (default
120), then does one DNS check as a last resort, then continues regardless. A network
timeout is never fatal on its own — you get
Network check timed out - proceeding anyway in the log, and the failure surfaces later as
download failures. Note that setting networkTimeout in a configuration profile has no
effect; only the CLI option is honoured.
It depends on the stage. A failure in setupassistant or userland is recorded against
that item, the remaining items still run, and the run as a whole exits 1 — a single bad
package must not strand provisioning. A preflight script that cannot be downloaded or
launched is different: it fails the phase and skips both remaining stages. There is no
retry on an install failure; retries and retrywait govern downloads only.
Not today. userland items wait for a real console user to appear before running, but
userscript items are executed as root in the daemon process just like rootscript items.
The routine that would run a script as the console user exists in the source and is never
called. If an item needs to act on the current user, it has to determine and switch to that
user itself. This one catches people out; it is also listed on
Troubleshooting and Gotchas.
The CLI can be run by hand as often as you like. The unattended daemon cannot: cleanup at
the end of every run — including a run that preflight skipped — deletes
/Library/LaunchDaemons/com.github.bootstrapmate.plist and boots the job out. To get
another unattended run, reinstall the package or lay the plist back down and
launchctl load -w it. A missing plist is the normal state of a Mac that has already
provisioned, not a fault.
Broadly yes, but by re-doing work rather than by resuming it. There is no state machine:
every run starts from scratch with a new run id. Files whose SHA-256 already matches are
not re-downloaded, and a package with both packageid and version set is skipped when
pkgutil already reports that receipt at that version or newer. Anything without those
two keys will be installed again.
Not from --version. The version string the CLI prints — and the one in the log header,
the reporting payload and the User-Agent — is generated from the clock when it is first
read at runtime, so it reports the current time rather than the build. Ask the installed
bundle instead:
defaults read /Applications/Utilities/BootstrapMate.app/Contents/Info CFBundleShortVersionString
pkgutil --pkg-info com.github.bootstrapmate gives the version of the package receipt.
Only if you say so. Every package item is checked with pkgutil --check-signature before
installer runs, and an untrusted or unsigned package is refused with
Refusing to install <pkg>: untrusted or missing signature. Setting allowUnsigned — as a
preference, as a per-item key, or with --allow-unsigned — permits it with a warning in
the log. A Team ID mismatch against expectedTeamID is refused in every case;
allowUnsigned does not override it. Scripts are never signature-checked at all — their
only protection is the SHA-256 hash, which is a good reason to host them somewhere you
control. See Security and Package Verification.
The run stops in the userland stage and stays there. The wait for a console user is a
poll loop with no timeout, so a Mac left at the login window will sit with the dialog
reading "Waiting for user to log in..." indefinitely, and the run will never reach its
reporting or cleanup steps. If your Macs may never see an interactive login, put the work
in setupassistant instead.
No. BootstrapMate checks for /usr/local/bin/dialog at startup; if it is not there it logs
that it is running in headless mode and every dialog call becomes a no-op. The run proceeds
identically either way. You can also suppress the window explicitly with --no-dialog or
--silent. Note that the dialog-related preferences — enableDialog, dialogIcon,
blurScreen, and the title and message keys — are read from the profile but never reach
the dialog; only the corresponding CLI flags do anything.
Yes. A complete header value passed as --headers (or set as authorizationHeader in the
profile) is sent on the manifest fetch and on every item download. Bear in mind that HTTP
status codes are not inspected on downloads, so an authentication failure returns a body
that gets written to the destination path and then fails the hash check — a hash mismatch
is frequently an auth or URL problem. See
Serving Manifests and Packages.
No. Every item is written to the absolute path in its file key and left there; the
cache-cleaning routine in the source is never called. Choose file paths you are content
to leave on the disk, or remove them yourself from a late manifest item.
The shipping bundle declares a deployment target of macOS 13.0, and the README says macOS 13.0 or later, but the Swift package manifest requires macOS 15 to build. Treat 13.0 as the floor for running an already-built package and 15 as the floor for building from source, and test on the oldest OS you actually deploy.