Skip to content

Manifests

Rod Christiansen edited this page Sep 5, 2026 · 2 revisions

Manifests

A manifest is the document BootstrapMate downloads and executes. It lists the packages and scripts to install and which of the two phases each one belongs to. This page covers the serialisation formats the parser accepts, how the manifest is fetched, what authentication is available, and how to check a manifest before you point a fleet at it.

This is not a Munki or Cimian manifest. See the Glossary for the distinction.

What is in one

The document is an object with up to two keys, setupassistant and userland, each an array of item objects. Everything else at the top level is ignored. Each item names a file to download, where to download it from, and how to install it. Every key the parser actually reads is listed in the Manifest Reference.

{
  "setupassistant": [
    {
      "name": "Management Agent",
      "url": "https://example.com/bootstrap/packages/ManagementAgent.msi",
      "file": "ManagementAgent.msi",
      "type": "msi"
    }
  ],
  "userland": []
}

JSON or YAML

Both work. ManifestParser.Parse decides which it is by two tests, in order:

  1. The URL path, with anything from the first ? or # stripped, ends in .yaml or .yml.
  2. Otherwise, the first non-whitespace character of the content is neither { nor [.

If either test says YAML, the content is deserialised with YamlDotNet, re-serialised to JSON, and parsed from there. The log records Detected YAML manifest format — converting to JSON at Debug level, so you only see it with --verbose. A YAML manifest is the same document shape with the same key spellings; nothing in the schema changes.

Serving a JSON manifest from a URL that ends .yaml will fail to parse. Serving YAML from a URL with no extension works, because of the content sniff.

Hosting and fetching

Host the manifest over HTTPS at a stable URL. The URL reaches the tool one of three ways, in increasing precedence: the value compiled into the binary, the ManifestUrl value under HKLM\SOFTWARE\BootstrapMate\Settings or HKLM\SOFTWARE\Policies\BootstrapMate, or the --url argument, which wins over all of them. See Preferences and the Command Line Reference.

The fetch is a plain HttpClient GET with a User-Agent of BootstrapMate/{version}. That client uses the .NET default 100-second timeout and follows redirects, which is the default HttpClient behaviour rather than a decision the tool makes. The NetworkTimeout and FollowRedirects settings are configurable but are not applied to this request.

Package downloads use a separate request per item, with the same user agent and no hash or size check of any kind. Serve both manifest and packages over HTTPS.

Authentication

There is no CLI flag for headers. Authentication comes only from the AuthorizationHeader setting in the registry or policy, and the whole string is sent verbatim as the Authorization header on the manifest request.

That header is then scoped to the manifest's host. A package download gets the header only when its URL host matches the manifest URL host, case-insensitively; otherwise the header is withheld and the log records Authorization header withheld for cross-host download: {url} at Debug level. This is deliberate — some public object stores return 403 for a request carrying an Authorization header they cannot validate. Host your private manifest and your public packages accordingly, and see Serving Manifests and Packages.

Sanity-checking a manifest

Validate that it parses at all:

Invoke-RestMethod https://example.com/bootstrap/bootstrapmate.json | ConvertTo-Json -Depth 5

Then check by hand that every item in both arrays has all four of name, url, file and type. A missing name on any entry throws before the first install runs, because the progress dialog pre-populates its list from every entry in both phases — one bad entry means nothing installs. A missing url, file or type fails that item only.

Finally, run it once on a test device with logging turned up:

& 'C:\Program Files\BootstrapMate\managedbootstrapinstall.exe' --url https://example.com/bootstrap/bootstrapmate.json --verbose --no-dialog

Then confirm the result from the newest bootstrap.log under C:\ProgramData\ManagedBootstrap\logs\<date>\<time>\ and from HKLM\SOFTWARE\Cimian\BootstrapMate\Status. Do not use the process exit code as a health signal: a run in which every package failed still exits 0, though it does mark its phases Failed and withhold LastRunVersion. An empty C:\ProgramData\ManagedBootstrap\cache directory is the healthy state, because a cached file is only kept when its install failed.

The macOS build parses the same two formats and reads the same top-level keys, plus a preflight stage this build does not implement. See https://github.com/bootstrapmate/bootstrapmate-macintosh/wiki/Manifests.

See also

Clone this wiki locally