JAMF deployment
A complete JAMF rollout requires:
- An enrollment Configuration Profile (preference domain
ai.preamp) carrying anenrollmentTokenkey. The managed.pkg’s preinstall script aborts the install if this profile is not present, so it must land on the device before the deployment policy runs. - An identity Configuration Profile (preference domain
ai.preamp.identity) carryingemailandfullname, populated via JAMF’s$EMAIL/$REALNAMEsubstitution. The bootstrap script reads these so each device attributes to a real person on the Workforce tab. - A bootstrap script that writes
/etc/preamp/bootstrap.envbefore the.pkginstalls, carrying the org enrollment token plus the identity values it reads from the profile above. - The managed
.pkg, deployed via a JAMF policy.
A PPPC profile granting Full Disk Access is optional for current deployments. The default Claude backup path is user-owned and does not require Full Disk Access. See Do you need the PPPC profile? below.
Why identity goes in a Configuration Profile, not a script parameter. JAMF substitutes inventory variables like
$REALNAMEonly inside Configuration Profile payloads. It does not substitute them inside Policy script parameter fields. If you typePREAMP_USER_EMAIL=$EMAILverbatim intobootstrap.env. Enrollment silently lands the device in the unattributed bucket (or fails outright) with no useful error in the policy log. Carry identity in theai.preamp.identityConfiguration Profile and have the bootstrap script read it viadefaults read.
Prerequisites
- Preamp admin console access (to generate an enrollment token).
- JAMF Pro tenant with permission to upload scripts, configuration profiles, and packages.
- The signed
preamp-managed-<version>.pkg. See Package downloads for the URL and SHA-256 verification steps. - At least one verified domain for your org under
app.preamp.ai → Settings → Domains. Without it, devices still back up but land in the per-org unattributed bucket on the Workforce tab instead of attributing to a real person.
Steps
-
Generate an enrollment token in the Preamp admin console (https://app.preamp.ai/org/fleet/devices?tab=enrollment). Copy it immediately, the plaintext is shown only once.
-
Create the enrollment Configuration Profile. Computers → Configuration Profiles → New, add an Application & Custom Settings → External Applications payload with preference domain
ai.preamp. Add these keys:Key Type Value enrollmentTokenstring The token from step 1. managedboolean true(disables the agent’s self-update so upgrades flow through JAMF).The
.pkgpreinstall requires theenrollmentTokenkey to be present at/Library/Managed Preferences/ai.preamp.plist. Without this profile installed first, the install aborts with a generic “contact the software manufacturer” error and no useful diagnostic in the policy log. See the managed preferences reference for other keys you can add to this profile. -
Create the identity Configuration Profile. Add a second Configuration Profile with an Application & Custom Settings → External Applications payload, preference domain
ai.preamp.identity. Add these keys, using JAMF variable substitution for the values:Key Type Value emailstring $EMAIL(JAMF substitutes the assigned user’s email from User and Location). Must be a verified-domain address for per-person attribution.fullnamestring $REALNAME(optional; the assigned user’s display name).These substitute correctly because they live in a Configuration Profile payload, not a script parameter.
-
Add the bootstrap script to JAMF. In Settings → Computer Management → Scripts create a new script named
Preamp bootstrapwith this parameter label:Parameter Label Value at policy time Parameter 4 Org token The token from step 1. Paste this body:
#!/bin/bash set -euo pipefail IDENTITY_PLIST="/Library/Managed Preferences/ai.preamp.identity" TOK="${4:-}" # JAMF does NOT substitute $EMAIL / $REALNAME in script parameters, so read # the assigned user's identity from the ai.preamp.identity Configuration # Profile, where JAMF's substitution DOES apply. Missing keys resolve to an # empty string, which lands the device in the unattributed bucket rather # than failing the install. EM="$(/usr/bin/defaults read "$IDENTITY_PLIST" email 2>/dev/null || true)" NM="$(/usr/bin/defaults read "$IDENTITY_PLIST" fullname 2>/dev/null || true)" if [[ -z "$TOK" ]]; then echo "preamp bootstrap: parameter 4 (org token) is required" >&2 exit 1 fi mkdir -p /etc/preamp chmod 0700 /etc/preamp umask 077 { printf 'PREAMP_ORG_TOKEN=%s\n' "$TOK" printf 'PREAMP_USER_EMAIL=%s\n' "$EM" printf 'PREAMP_USER_NAME=%s\n' "$NM" } > /etc/preamp/bootstrap.env chmod 0600 /etc/preamp/bootstrap.envTo keep the token out of the policy run log entirely, read the token from the enrollment profile instead of Parameter 4. This is two edits that must be made together: replace the
TOK="${4:-}"line withTOK="$(/usr/bin/defaults read /Library/Managed\ Preferences/ai.preamp enrollmentToken 2>/dev/null || true)", and then you can leave Parameter 4 empty. Omitting Parameter 4 without also swapping theTOK=line leavesTOKempty and theif [[ -z "$TOK" ]]guard aborts the script. Done correctly, the token lives only in theai.preampConfiguration Profile. -
Upload the managed
.pkg(preamp-managed-<version>.pkg) to JAMF’s package repository. -
Scope both Configuration Profiles (
ai.preampandai.preamp.identity) to the target Macs and confirm they have installed before proceeding. Configuration Profiles apply at MDM check-in; on a test Mac verify withprofiles showor System Settings → Device Management thatai.preamp.plistexists under/Library/Managed Preferences/before running the deployment policy. If the policy runs before the enrollment profile lands, the preinstall gate aborts the install. -
Create the deployment policy. Computers → Policies → New:
- Scripts payload: add the
Preamp bootstrapscript. Set Priority to Before. Fill in Parameter 4 (or omit it if reading the token from the profile per step 4). - Packages payload: add
preamp-managed-<version>.pkg. - General → Trigger: Check-in.
- General → Frequency: Once per computer.
- Scope: the target Macs (the same set the Configuration Profiles are scoped to).
The script writes the bootstrap file, then the .pkg installs, then the postinstall reads the file, runs
preamp enrollas the console user, and deletes the bootstrap file on success. - Scripts payload: add the
-
(Optional) Deploy the PPPC profile. Only needed if you want to pre-grant Full Disk Access defensively. See Do you need the PPPC profile?.
Do you need the PPPC profile?
Probably not for current deployments. The Preamp agent runs as the logged-in console user and reads user-owned paths (~/.claude, ~/Library/Application Support/Claude). These do not require Full Disk Access, so under normal operation the agent never appears in System Settings → Privacy & Security → Full Disk Access, and a full backup completes without it.
Deploy the PPPC profile only if you want to pre-grant FDA defensively (for example, ahead of a future provider whose paths are TCC-protected). If you do, follow the PPPC profile guide and scope it to the same target set as the deployment policy.
Verification
On a target Mac after the policy runs:
- The
ai.preampandai.preamp.identitymanaged preferences exist under/Library/Managed Preferences/(confirm withprofiles showordefaults read "/Library/Managed Preferences/ai.preamp.identity" email). /etc/preamp/bootstrap.envis absent (the postinstall deletes it on successful enroll; presence means enroll failed, check the policy run log). If it is present, inspect it: a literal$EMAILvalue means identity is being pulled from a script parameter instead of the Configuration Profile.- The device shows up under the assigned user on
app.preamp.ai/org/inventory/workforce. If it lands under Unattributed devices, either the assigned user’s email domain isn’t in the org’s verified-domains list (add it underapp.preamp.ai → Settings → Domainsand retry) or the identity profile didn’t resolve$EMAIL(check theemailkey on the device). - The agent does not appear in System Settings → Privacy & Security → Full Disk Access unless you deployed the optional PPPC profile. Its absence is expected and is not a failure.
Failure modes
- Install aborts with a generic “contact the software manufacturer” error and no useful policy-log detail. The
ai.preampConfiguration Profile carryingenrollmentTokenis not present on the device yet. The.pkgpreinstall gates on/Library/Managed Preferences/ai.preamp.plistcontaining anenrollmentTokenkey. Confirm the profile has installed before the policy runs (step 6). bootstrap.envcontains the literal string$EMAIL(or$REALNAME). Identity is being passed via a script parameter, which JAMF does not substitute. Move identity to theai.preamp.identityConfiguration Profile and read it viadefaults read(step 3 and step 4).- Console user is
rootat install time (login window, fresh image before first login). The postinstall logsno console user; deferring enroll until next policy runand leaves the bootstrap file in place. The next JAMF policy run picks it up. - Bootstrap env file is malformed (typo in a key, missing
=). The agent’s parser rejects malformed lines andpreamp enrollexits non-zero, visible in the JAMF policy log. The bootstrap file stays in place for diagnosis. - Email is outside the org’s verified domains. Enroll succeeds but the device lands in the unattributed bucket. Verify your org domains and retry; the bootstrap file is removed on first successful enroll regardless of attribution outcome.
Uninstall
Deploy preamp-uninstaller-<version>.pkg via the same JAMF policy mechanism. The uninstaller pkgutil --forgets itself so repeated runs are safe. If you set allowUninstall: true in the ai.preamp Configuration Profile, the uninstaller also removes per-user data trees.
Trust note
The org token is sensitive. It appears in JAMF policy logs when passed as Parameter 4, unless logging is suppressed for the bootstrap script step. Reading the token from the ai.preamp Configuration Profile instead (step 4) keeps it out of the policy run log. Treat it like any other secret in your MDM tenant, and rotate via app.preamp.ai → Settings → Enrollment tokens → Revoke if exposed. The postinstall removes the on-disk bootstrap file as soon as enroll succeeds; if you see the file lingering on a managed Mac, that’s a signal enroll didn’t complete.