-
Notifications
You must be signed in to change notification settings - Fork 1
Example Manifests
Three complete manifests you can copy, change the URLs in, and run. Every key used here is one
the parser actually reads; see the Manifest Reference for the full list
and Item Types for what each type does.
The manifest shipped in the repository at examples/bootstrapmate.json is not runnable as
written — its first entry has displayname but no name, and a missing name on any entry
throws before the first install. Start from one of these instead.
One package, one phase. This is the manifest to use for a first run on a test device: it proves the URL is reachable, the file downloads, and the install path works, without anything else in the way.
{
"setupassistant": [
{
"name": "Management Agent",
"url": "https://example.com/bootstrap/packages/ManagementAgent.msi",
"file": "ManagementAgent.msi",
"type": "msi"
}
]
}userland is omitted, which records that phase as Skipped and moves on. Run it with:
& 'C:\Program Files\BootstrapMate\managedbootstrapinstall.exe' --url https://example.com/bootstrap/minimal.json --verbose --no-dialogA realistic first-boot manifest for a device coming through Autopilot and the Enrollment Status Page (ESP). The shape of it is: get the installer helper down first, then the ongoing management agent, then the runtime and the architecture-specific payload, and finish with a script that starts the handoff.
Both phases run back to back in the same process, as SYSTEM, so treat the split as ordering plus separate status reporting rather than as two environments — see Stages.
{
"setupassistant": [
{
"name": "System Binary Installer",
"url": "https://example.com/bootstrap/packages/sbin-installer-1.4.0.msi",
"file": "sbin-installer-1.4.0.msi",
"type": "msi",
"expectedPublisher": "Example Organisation"
},
{
"name": "Cimian",
"url": "https://example.com/bootstrap/packages/Cimian-2026.09.01.msi",
"file": "Cimian-2026.09.01.msi",
"type": "msi",
"expectedPublisher": "Example Organisation"
},
{
"name": "Visual C++ Redistributable (x64)",
"url": "https://example.com/bootstrap/packages/VCRedist-x64.exe",
"file": "VCRedist-x64.exe",
"type": "exe",
"arguments": ["/install", "/quiet", "/norestart"],
"condition": "architecture_x64"
},
{
"name": "Visual C++ Redistributable (arm64)",
"url": "https://example.com/bootstrap/packages/VCRedist-arm64.exe",
"file": "VCRedist-arm64.exe",
"type": "exe",
"arguments": ["/install", "/quiet", "/norestart"],
"condition": "architecture_arm64"
}
],
"userland": [
{
"name": "Corporate Root Certificates",
"url": "https://example.com/bootstrap/packages/RootCerts.msi",
"file": "RootCerts.msi",
"type": "msi",
"expectedPublisher": "Example Organisation"
},
{
"name": "Start Ongoing Management",
"url": "https://example.com/bootstrap/scripts/start-management.ps1",
"file": "start-management.ps1",
"type": "ps1",
"arguments": ["-Environment", "Production"]
}
]
}Four things in that manifest are worth pointing at.
The installer helper is named System Binary Installer, which is one of the names that select
the ten-attempt, retry-on-any-error MSI policy in Retries and Timeouts.
That naming is load-bearing, not decorative.
The two redistributables are the same item twice, gated by condition, because condition
only understands architecture_x64 and architecture_arm64. On an x64 device the arm64 entry
logs a [SKIPPED] line and nothing else happens. See
Conditions and Skipping.
The script is named Start Ongoing Management rather than something like "Clean up and start
management". A ps1 item whose name contains cleanup, clean, wipe, remove, delete,
purge, nuclear or maintenance is moved to the end of its phase automatically, which is
rarely what you meant.
And the script must exit 0 when it has nothing to do. A non-zero exit is the only failure
signal for a ps1 item, so a script that ends on a stray error code reports a failed item even
though provisioning worked.
A reference manifest rather than a deployment one, showing all five types and the optional keys
that apply to each. Note the asymmetry: arguments reaches every type, target only reaches
the sbin-installer paths, and expectedPublisher and allowUnsigned only apply to msi and
exe, because those are the only types Authenticode-verified.
{
"setupassistant": [
{
"name": "Vendor Suite",
"url": "https://example.com/bootstrap/packages/VendorSuite.msi",
"file": "VendorSuite.msi",
"type": "msi",
"arguments": ["ALLUSERS=1", "DESKTOPSHORTCUT=0"],
"expectedPublisher": "Vendor Software Inc"
},
{
"name": "Legacy Driver Package",
"url": "https://example.com/bootstrap/packages/LegacyDriver.exe",
"file": "LegacyDriver.exe",
"type": "exe",
"arguments": ["/S", "/norestart"],
"allowUnsigned": true
},
{
"name": "Internal Tooling",
"url": "https://example.com/bootstrap/packages/InternalTooling-3.2.1.nupkg",
"file": "InternalTooling-3.2.1.nupkg",
"type": "nupkg",
"target": "/"
},
{
"name": "Legacy Payload",
"url": "https://example.com/bootstrap/packages/LegacyPayload-1.0.0.pkg",
"file": "LegacyPayload-1.0.0.pkg",
"type": "pkg",
"target": "/"
}
],
"userland": [
{
"name": "Configure Workstation",
"url": "https://example.com/bootstrap/scripts/configure-workstation.ps1",
"file": "configure-workstation.ps1",
"type": "ps1",
"arguments": ["-Verbose"]
}
]
}allowUnsigned on the driver package permits an installer whose Authenticode signature does
not verify; it does not permit a signature from the wrong publisher, which is refused either
way. The nupkg and pkg entries both need sbin-installer on the device — without it, pkg
fails outright and nupkg falls through to Chocolatey, which will install Chocolatey from the
internet if it is not already present.
The same manifest in YAML, if you would rather maintain it that way, is the same keys and the
same values; serve it from a URL ending .yaml or .yml.