Skip to content

Example Manifests

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

Example Manifests

Three complete manifests to copy and adapt: the smallest thing that works, a realistic provisioning run using all three stages, and that same run written in YAML.

Every hash below is a placeholder — the SHA-256 of an empty file, repeated. Replace each one with the real digest of the payload you are serving, from shasum -a 256 <file>, or the item will fail every download attempt. Replace example.com with your own host.

Every key used here exists in the schema; see Manifest Reference.

Minimum viable manifest

One stage, one item. file, hash, url and type are the only required keys — name is added here because without it the logs and the progress window show the full path instead. This installs one package as root during Setup Assistant and does nothing else.

{
  "setupassistant": [
    {
      "file": "/Library/Application Support/BootstrapMate/munkitools.pkg",
      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://example.com/bootstrap/packages/munkitools-6.6.0.pkg",
      "name": "Munki Tools",
      "type": "package"
    }
  ]
}

preflight and userland are absent, which is legal: the preflight stage records itself as skipped, and the run never waits for a user to log in.

A realistic provisioning manifest

This one uses all three stages. preflight asks whether the machine already has management installed and exits 0 if so, cancelling the whole run. setupassistant installs the management agent as root and configures it before anyone logs in, using packageid and version so a machine that already has a new-enough Munki does not reinstall it, and expectedTeamID so an in-house package must be signed by the expected team. userland waits for a user session and then fires the first management run with donotwait, so the child process outlives BootstrapMate's own teardown.

{
  "preflight": [
    {
      "file": "/Library/Application Support/BootstrapMate/preflight.sh",
      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://example.com/bootstrap/scripts/preflight.sh",
      "name": "Preflight Check",
      "type": "rootscript",
      "retries": 3,
      "retrywait": 5
    }
  ],
  "setupassistant": [
    {
      "file": "/Library/Application Support/BootstrapMate/munkitools.pkg",
      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://example.com/bootstrap/packages/munkitools-6.6.0.pkg",
      "name": "Munki Tools",
      "type": "package",
      "packageid": "com.googlecode.munki.core",
      "version": "6.6.0",
      "retries": 5,
      "retrywait": 10
    },
    {
      "file": "/Library/Application Support/BootstrapMate/site-config.pkg",
      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://example.com/bootstrap/packages/site-config-1.4.0.pkg",
      "name": "Site Configuration",
      "type": "package",
      "packageid": "com.example.siteconfig",
      "version": "1.4.0",
      "expectedTeamID": "AB12CD34EF"
    },
    {
      "file": "/Library/Application Support/BootstrapMate/configure-munki.sh",
      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://example.com/bootstrap/scripts/configure-munki.sh",
      "name": "Configure Munki",
      "type": "rootscript",
      "retries": 2,
      "retrywait": 5
    }
  ],
  "userland": [
    {
      "file": "/Library/Application Support/BootstrapMate/start-munki-run.sh",
      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://example.com/bootstrap/scripts/start-munki-run.sh",
      "name": "Start Managed Software Update",
      "type": "rootscript",
      "donotwait": true
    }
  ]
}

Two things about the last item are worth stating plainly. It is a rootscript, not a userscript, because both types run as root anyway and the name should say so — see Item Types. And because donotwait is set, its exit code is never read and its output is never logged, so it reports success the moment it launches.

The same manifest in YAML

Identical content and identical key names. BootstrapMate chooses the parser from the manifest URL's path extension, so serve this as bootstrap.yaml or bootstrap.yml. Quote version numbers so YAML does not read 6.6.0 as something other than a string.

preflight:
  - file: /Library/Application Support/BootstrapMate/preflight.sh
    hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    url: https://example.com/bootstrap/scripts/preflight.sh
    name: Preflight Check
    type: rootscript
    retries: 3
    retrywait: 5

setupassistant:
  - file: /Library/Application Support/BootstrapMate/munkitools.pkg
    hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    url: https://example.com/bootstrap/packages/munkitools-6.6.0.pkg
    name: Munki Tools
    type: package
    packageid: com.googlecode.munki.core
    version: "6.6.0"
    retries: 5
    retrywait: 10

  - file: /Library/Application Support/BootstrapMate/site-config.pkg
    hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    url: https://example.com/bootstrap/packages/site-config-1.4.0.pkg
    name: Site Configuration
    type: package
    packageid: com.example.siteconfig
    version: "1.4.0"
    expectedTeamID: AB12CD34EF

  - file: /Library/Application Support/BootstrapMate/configure-munki.sh
    hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    url: https://example.com/bootstrap/scripts/configure-munki.sh
    name: Configure Munki
    type: rootscript
    retries: 2
    retrywait: 5

userland:
  - file: /Library/Application Support/BootstrapMate/start-munki-run.sh
    hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    url: https://example.com/bootstrap/scripts/start-munki-run.sh
    name: Start Managed Software Update
    type: rootscript
    donotwait: true

Before you deploy one

Check the document against a test Mac with the console output on:

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

That confirms the manifest decodes and the stages and items are the ones you meant. It does not rehearse the installs — see Manifests for what --dry-run actually suppresses.

See also

Clone this wiki locally