Configuring a bootstrap package in Fleet GitOps

3 min read

Bootstrap packages provide a common way to deliver an initial payload of software, such as a management agent, to a macOS device during the Automated Device Enrollment process. The package is installed using Apple’s InstallEnterpriseApplication command during device enrollment.

If you use Fleet Device Management for Mobile Device Management (MDM), you have the option to manage your configuration for the server including the software, profiles, and scripts using a workflow called GitOps. There are advantages to doing this, namely being able to utilize version control and peer review for any changes made to these systems. Changes that can potentially affect thousands of endpoints.

Using the bootstrap_package key in GitOps

Managing the bootstrap package using GitOps is indeed possible, using a key called bootstrap_package, under the macos_setup section. The key accepts a URL as a value, that must be accessible by your runner for GitHub, or GitLab etc.

How do you secure it?

This presents a bit of a problem, as you don’t want a package like this available from a publicly accessible URL. Often a package like this can contain secrets used during the initial setup of a device. So what options do you have?

Maybe you have Git LFS, and are able to produce a URL that works this way. Or maybe you can secure it in your own cloud storage solution of choice. I was really hoping to make use of Fleet’s new hash_sha256 key, that is used for their software package definitions. This key allows you to use the Fleet server itself as the source of the package defined in GitOps, rather than source it from another URL. But that isn’t possible just yet for the bootstrap_package key.

A solution

Recently, Steven Palmesano from Fleet shared a way to work around this by pulling the metadata for the uploaded package via the API and constructing a URL for use in GitOps.

Start by pulling the team_id for the team you uploaded a bootstrap package to. This is shown as the team_id parameter at the end of the URL when viewing the team in the browser, ie: https:​//acme.cloud.fleetdm.com/dashboard?team_id=1

Next do a GET request from the api/v1/fleet/bootstrap/1/metadata endpoint for our server. Note that 1 here is our team id. The response you get back contains a token we will use to construct our URL.

{
  "name": "signed_bootstrap.pkg",
  "team_id": 1,
  "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "token": "73c58b3b-d779-4f33-b9f8-12c402cba2fb",
  "created_at": "2025-11-08T18:17:20Z"
}

The URL starts with our server URL, https:​//acme.cloud.fleetdm.com, followed by /api/v1/fleet/bootstrap?token=, and finally our token. We end up with the following, which we can then use inside our GitOps workflow.

macos_setup:
  bootstrap_package: 'https://acme.cloud.fleetdm.com/api/v1/fleet/bootstrap?token=73c58b3b-d779-4f33-b9f8-12c402cba2fb'

The feature to add hash_sha256 support for this is still open, and may yet become the preferred path in the future, but for now this is something you can use today.