Skip to content

Manifests

Rod Christiansen edited this page Sep 3, 2026 · 1 revision

Manifests

A manifest is the document BootstrapMate downloads and executes. It lists every package and script a freshly enrolled Mac should receive, grouped into three stages. This page covers what a manifest is, the two file formats, how BootstrapMate fetches one, and how to check a manifest before you point a fleet at it.

Note the vocabulary collision: this is not a Munki manifest. BootstrapMate's manifest is the bootstrap document in the InstallApplications sense — see Glossary.

Structure

A manifest is a single document with three optional top-level arrays: preflight, setupassistant and userland. Each array holds items, and each item is one package or one script. The stages always run in that order. Every field is documented in Manifest Reference; the stages themselves in Stages.

There is no include, import or nesting mechanism. One URL yields one document, and that document is the whole run.

JSON and YAML

BootstrapMate accepts both, and picks the parser from the path extension of the manifest URL, not from the content:

  • .yaml or .yml — parsed as YAML.
  • .json — parsed as JSON.
  • Any other extension, or none — parsed as JSON first, then retried as YAML if that fails.

Query parameters after the path do not affect detection. The two formats express exactly the same schema, so bootstrap.json and bootstrap.yaml are interchangeable as long as the key names match. Serving YAML from a URL that ends in .json still works, because the JSON attempt fails and the YAML fallback succeeds — but naming the file for its format is less surprising.

Key names are the Swift property names verbatim, so they are camelCase: skipIf, followRedirects, expectedTeamID, allowUnsigned. Snake-case spellings such as skip_if are not recognised and are silently ignored by both decoders.

Hosting and fetching

Point BootstrapMate at the manifest with --jsonurl, or set jsonUrl (aliases url, jsonurl, JsonUrl, ConfigURL, ManifestURL) in the com.github.bootstrapmate managed-preference domain. The LaunchDaemon installed by the package passes no arguments, so on an MDM-driven run the URL must come from the profile. See Preferences and Deployment.

The fetch has a 60-second ceiling. If it fails — HTTP error, timeout, or a document that will not decode — the run logs Failed to decode BootstrapManifest: … and exits 1. Nothing is retried at this level; manifest retry settings apply to item payloads, not to the manifest itself.

Serve manifests over HTTPS. If the origin needs authentication, supply a complete header value with --headers or the authorizationHeader preference (aliases headers, Headers, AuthorizationHeader); it is sent as the Authorization header on the manifest fetch and on every item download. There is no separate username/password option and no per-item header. Details in Serving Manifests and Packages.

HTTP status codes are not inspected on item downloads. A 404 error page is written to the item's file path and then fails the SHA-256 check, so a broken URL surfaces as a hash mismatch rather than as a 404.

Checking a manifest before you deploy it

Confirm the document parses and the hashes are right before an enrolled Mac depends on it. Parse it locally first:

python3 -c 'import json,sys; json.load(open("bootstrap.json"))'

Compute each item's hash from the exact bytes you are serving:

shasum -a 256 munkitools.pkg

Then run the CLI against the URL on a test Mac with output on the console:

/usr/local/bootstrapmate/managedbootstrapinstall --jsonurl https://example.com/bootstrap.json --verbose --no-dialog --dry-run

--dry-run suppresses downloads only — each item logs [Dry Run] Would download <name>. The install and script steps are still attempted, so a dry run against a real manifest will report failures for payloads it never fetched. It is a way to confirm the document decodes and the stages and item list are what you expect, not a full no-op rehearsal.

A real end-to-end test needs a machine you can re-run: the bootstrap LaunchDaemon removes itself after any completed run, so re-testing means re-installing the package or invoking the CLI by hand.

See also

Clone this wiki locally