Skip to content

Mass Deployment (GPO, Intune, JAMF)

This guide covers rolling the Breeze agent out to hundreds or thousands of endpoints with the deployment tooling you already run: Group Policy, Microsoft Intune, JAMF, or a configuration-management system such as Ansible. It assumes you are migrating a fleet from another RMM or standing up a new one — for single-machine installs see Agent Installation, and for the full flag-by-flag reference see Advanced Install Methods.

Every deployment method below needs an enrollment key. Keys are created per organization (optionally pinned to a site) and carry a usage cap (maxUsage) and a TTL, so plan them around your rollout:

  • Create one key per site so devices land in the right place — there is no SITE_ID install parameter; site assignment is encoded in the key.
  • Set maxUsage to the number of devices you are deploying, and a TTL that covers your rollout window (the default is 60 minutes, which is too short for a phased GPO rollout — set an explicit expiry).
  • If your server enforces AGENT_ENROLLMENT_SECRET, you will also need that shared secret at deploy time.

Windows: the MSI Is the Deployment Vehicle

Section titled “Windows: the MSI Is the Deployment Vehicle”

Deploy Windows agents with the MSI package and its public properties. The canonical silent-install payload and the full property table live in MSI with Properties; the short version:

Terminal window
msiexec /i breeze-agent.msi /qn `
SERVER_URL=https://breeze.yourdomain.com `
ENROLLMENT_KEY=<64-hex-enrollment-key> `
ENROLLMENT_SECRET=<shared-enrollment-secret>

SERVER_URL and ENROLLMENT_KEY must be provided together or not at all (a WiX launch condition enforces this). ENROLLMENT_SECRET is optional, and BOOTSTRAP_TOKEN exists for the dashboard’s pre-signed installer flow — you will not normally set it by hand.

Enrollment happens at install time — network required

Section titled “Enrollment happens at install time — network required”

When ENROLLMENT_KEY is set, the MSI’s deferred EnrollAgent custom action runs breeze-agent.exe enroll during the install. That means the machine must be able to reach your Breeze server at the moment msiexec runs. This is the single most important constraint when choosing a GPO mechanism.

Use a startup script (or an immediate scheduled task pushed via Group Policy Preferences) that runs msiexec, not a GPO software-installation policy. Software-installation assignments execute in the foreground boot phase and, on some network/VPN/802.1X configurations, run before the network is up — the install then fails or rolls back because the enrollment custom action cannot reach the server.

A minimal startup script, with a guard so it only runs once:

Terminal window
@echo off
if exist "C:\ProgramData\Breeze\agent.yaml" goto :eof
msiexec /i "\\fileserver\deploy\breeze-agent.msi" /qn ^
SERVER_URL=https://breeze.yourdomain.com ^
ENROLLMENT_KEY=YOUR_64_HEX_KEY ^
ENROLLMENT_SECRET=YOUR_SECRET ^
/l*v "C:\Windows\Temp\breeze-install.log"

C:\ProgramData\Breeze\agent.yaml is written by successful enrollment, so it doubles as an idempotency marker. If a machine boots off-network, the script simply runs again on the next boot.

Package the MSI as a Win32 app (.intunewin) rather than a line-of-business MSI app, so you control the command line and detection:

  1. Wrap breeze-agent.msi with the Microsoft Win32 Content Prep Tool to produce breeze-agent.intunewin.
  2. Install command — the same silent payload as above: msiexec /i breeze-agent.msi /qn SERVER_URL=https://breeze.yourdomain.com ENROLLMENT_KEY=... ENROLLMENT_SECRET=...
  3. Uninstall command: msiexec /x breeze-agent.msi /qn
  4. Detection rule — either of the enrollment footprints:
    • File exists: C:\ProgramData\Breeze\agent.yaml, or
    • Service exists: BreezeAgent (the watchdog installs as BreezeWatchdog)
  5. Assign to your device groups. Intune Win32 installs run in SYSTEM context after the network is up, so the install-time enrollment constraint is satisfied on ordinary corporate networks.

If you prefer not to embed the enrollment key in the Intune app definition, deploy the MSI with no properties and push a separate script (Intune remediation or platform script) that runs breeze-agent.exe enroll <key> --server <url> afterwards.

macOS agents ship as per-architecture PKGs: breeze-agent-darwin-amd64.pkg (Intel) and breeze-agent-darwin-arm64.pkg (Apple silicon).

A typical JAMF policy:

  1. Upload both PKGs and scope each to the matching architecture (or use a smart group on Architecture Type).

  2. In the same policy (packages install before scripts within a policy), add a script step that enrolls:

    #!/bin/bash
    # Idempotent: enroll exits 0 with a notice if already enrolled.
    /usr/local/bin/breeze-agent enroll "$4" \
    --server "$5" \
    --enrollment-secret "$6" \
    --quiet

    Pass the enrollment key, server URL, and (if required) enrollment secret as JAMF script parameters $4$6 so they are not hard-coded in the script body. Omit --enrollment-secret if your server does not require one.

  3. The running daemon (com.breeze.agent) starts in a waiting-for-enrollment state and picks up the new credentials within a few seconds of the enroll command succeeding — no restart step is needed.

The same two-step shape (install PKG, then run the enroll command as root) applies to any other macOS MDM.

There is no .deb or .rpm package today. Linux deployment is the agent binary plus two commands, which maps cleanly onto Ansible, Puppet, Chef, or Salt:

  1. Copy the breeze-agent binary for the target architecture to /usr/local/bin/breeze-agent (mode 0755).
  2. Install the service: breeze-agent service install (systemd unit + watchdog; see the flag reference).
  3. Enroll: breeze-agent enroll <key> --server https://breeze.yourdomain.com

The agent reads the enrollment secret from the BREEZE_AGENT_ENROLLMENT_SECRET environment variable when the --enrollment-secret flag is not passed — use that to keep the secret out of process listings and shell history. The server URL has no environment variable: pass --server (or rely on an existing agent.yaml from a pre-staged image).

An Ansible sketch:

- name: Install Breeze agent binary
ansible.builtin.copy:
src: "breeze-agent-linux-{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}"
dest: /usr/local/bin/breeze-agent
mode: "0755"
- name: Install the agent service
ansible.builtin.command: /usr/local/bin/breeze-agent service install
args:
creates: /etc/systemd/system/breeze-agent.service
- name: Enroll the agent
ansible.builtin.command: >-
/usr/local/bin/breeze-agent enroll {{ breeze_enrollment_key }}
--server {{ breeze_server_url }} --quiet
environment:
BREEZE_AGENT_ENROLLMENT_SECRET: "{{ breeze_enrollment_secret | default('') }}"
args:
creates: /etc/breeze/agent.yaml

/etc/breeze/agent.yaml only exists after successful enrollment, so both steps are naturally idempotent.

For imaging workflows, install without enrolling (MSI with no ENROLLMENT_KEY, PKG as-is, or binary + service install on Linux), seal the image, and enroll each clone on first boot. The exact pattern — including how the waiting service auto-detects the new credentials — is documented in Pre-Staging Without Enrollment.

  • Watch the device list fill in — new devices appear within seconds of enrollment and report inventory on the first check-in.
  • Track enrollment-key consumption (usageCount vs maxUsage) via GET /enrollment-keys to spot stalled cohorts.
  • On a machine that failed to appear, check the local logs: C:\ProgramData\Breeze\logs\ (Windows), /Library/Logs/Breeze/ (macOS), or run breeze-agent enroll interactively to see the error.