Smart groups, policies, scripting and extension attributes — the Apple enterprise management standard, end to end.
| Area | Object | What it is | Notes |
|---|---|---|---|
| Scoping | Smart Group | A device or user group whose membership is defined by criteria and recalculated automatically. | The single most important object in Jamf. Scope everything to these, never to static groups. |
| Scoping | Static Group | A manually curated list of specific devices. | Justified for a genuine pilot cohort. If you find yourself maintaining one by hand long-term, it should have been a Smart Group. |
| Scoping | Scope / Limitations / Exclusions | Three separate tiers on every policy and profile: who it targets, what narrows it, and what overrides it. | Exclusions always win. A device in both Scope and Exclusions is excluded — the usual answer to "why isn't this applying?" |
| Delivery | Configuration Profile | A signed settings payload delivered over MDM — Wi-Fi, VPN, certificates, restrictions, FileVault, kernel/system extensions. | Declarative and reversible: remove the profile and the setting reverts. Prefer profiles over scripts whenever a payload exists. |
| Delivery | Policy | An action run by the Jamf binary on the Mac: install a package, run a script, bind, update inventory, cache a file. | Agent-based, unlike profiles. Needs a trigger and an execution frequency — the two fields most often set wrong. |
| Delivery | Trigger | What causes a policy to run: enrollment complete, startup, login, network state change, recurring check-in, or a custom event name. | Custom triggers are invoked with jamf policy -event <name> — the backbone of chained provisioning workflows. |
| Delivery | Execution Frequency | Once per computer, once per user, once per user per computer, once per day/week/month, or ongoing. | "Ongoing" runs at every check-in (roughly every 15 minutes). Setting a heavy install to Ongoing by accident is a classic self-inflicted outage. |
| Delivery | Self Service | An on-device app catalogue where users run policies themselves — installs, printer setup, password reset, VPN config. | The highest-leverage thing Jamf offers. Every policy that could be user-initiated should be, to cut ticket volume. |
| Inventory | Extension Attribute | A custom inventory field populated by a script, a pop-up menu, or text entry. | Lets you build Smart Groups on facts Jamf doesn't natively collect — Activation Lock state, a config file's contents, a specific app's version. |
| Inventory | Inventory Update (recon) | The device reporting its full state back to Jamf. Run via jamf recon. | Smart Group membership only changes after a recon. This is why a policy "doesn't apply" immediately after a change — see the Gotchas tab. |
| Deployment | PreStage Enrollment | The ADE configuration: which Setup Assistant panes to skip, account type, whether enrollment is mandatory and non-removable. | Devices must be assigned to Jamf in Apple Business Manager first. Changes only affect devices that haven't yet enrolled. |
| Deployment | Package (.pkg) | Software uploaded to a distribution point and installed by policy. | Signed installer packages only — dragging a .app into a .pkg without correct ownership is a common failure. Build with pkgbuild or Composer. |
| Deployment | Patch Management | Jamf's title-based version tracking with automated update policies for common third-party apps. | Good for mainstream titles; anything niche still needs AutoPkg or a manual package. |
Understand AND vs OR, and the parentheses
Criteria rows combine with And/Or, and Jamf gives you real parentheses. Without them, mixing And and Or produces results that look arbitrary. Always parenthesise explicitly rather than trusting evaluation order.
Learn the operators that matter
is / is not for exact matches. like / not like for substring matching — this is what you want for OS versions, since "like 15." catches every 15.x release. member of nests one Smart Group inside another, which is how you compose logic cleanly.
Build the four groups every environment needs
Not on latest OS (patch compliance), FileVault not enabled (security compliance), Has not checked in for 30 days (lost/stale devices), and App X not installed (deployment targeting). These four cover most of day-to-day fleet management.
Use "app not installed" for self-healing deployment
Scope an install policy to a Smart Group of Macs lacking the app, at Ongoing frequency. A Mac installs it, next recon removes it from the group, the policy stops targeting it. If someone uninstalls the app it rejoins the group and gets it back — self-healing with no manual intervention.
Remember membership is only as fresh as the last recon
Smart Groups recalculate on inventory update, not continuously. A Mac that just installed something won't leave the "missing app" group until it next reports in. Policies that need immediate re-evaluation should end with jamf recon.
Useful Smart Group criteria
| Goal | Criteria | Notes |
|---|---|---|
| Macs not on the current OS | Operating System Version — not like — 15. | The trailing dot matters; without it "15" also matches 10.15. |
| FileVault not enabled | FileVault 2 Status — is not — Boot Partitions Encrypted | The core encryption-compliance group. Scope a Self Service remediation policy to it. |
| App missing | Application Title — does not have — Slack.app | Drives self-healing installs (step 4 above). |
| App outdated | Application Version — is not — 4.38.0 + Application Title is Slack.app | Needs both rows, or Macs without the app at all match too. |
| Stale / possibly lost | Last Inventory Update — more than x days ago — 30 | Review monthly. Long gaps usually mean offboarded-but-not-wiped hardware. |
| Apple silicon only | Architecture Type — is — arm64 | Essential when scoping anything that ships separate Intel/ARM builds. |
| Low disk space | Boot Drive Available MB — less than — 10000 | Catch Macs that will fail an OS upgrade before you attempt it fleet-wide. |
| Unsupervised / not ADE | Enrollment Method — is not — PreStage enrollment | Finds manually-enrolled Macs that lack supervision-only capabilities. |
| Command | What it does | When you'd use it |
|---|---|---|
sudo jamf policy | Forces a check-in and runs any pending policies. | The first thing to run when testing. Stop waiting for the 15-minute cycle. |
sudo jamf policy -event <name> | Runs only policies bound to that custom trigger. | Chaining provisioning steps in a deterministic order from one script. |
sudo jamf recon | Submits a full inventory update. | After any change that should move a Mac between Smart Groups. End provisioning scripts with it. |
sudo jamf manage | Re-applies the management framework and MDM profile. | Repairing a Mac that shows as enrolled but stopped responding to policies. |
sudo jamf enroll -prompt | Interactively re-enrols the Mac. | Last resort when the framework is broken beyond jamf manage. |
sudo jamf removeFramework | Removes the Jamf binary and management framework entirely. | Decommissioning or migrating to another MDM. Irreversible without re-enrolling. |
jamf displayMessage -message "text" | Shows a basic dialog to the user. | Quick notifications. swiftDialog is far better for anything user-facing and polished. |
sudo jamf log | Shows the Jamf log location and recent activity. | Debugging. The real log lives at /var/log/jamf.log. |
tail -f /var/log/jamf.log | Follows policy execution live. | Watching a policy actually run — the single most useful debugging move. |
sudo jamf checkJSSConnection | Tests connectivity to the Jamf server. | Ruling out network/DNS before investigating policy logic. |
Script parameters — the part that trips everyone up
Extension Attribute example
An EA script must echo its value wrapped in <result> tags. This one reports Activation Lock status, which Jamf doesn't collect natively — then you can build a Smart Group on it.
Zero-touch provisioning with Jamf
Assign devices to Jamf in Apple Business Manager
ABM → Devices → select serials → Edit MDM Server → your Jamf instance. Nothing works until this is done; a Mac not assigned in ABM will never enrol automatically no matter what Jamf is configured to do.
Build the PreStage Enrollment
Skip the Setup Assistant panes you don't want (Siri, Screen Time, Apple ID, Analytics, TouchID). Set enrollment to mandatory and non-removable. Make the first account Standard, not Administrator, and create a hidden management account.
Chain the provisioning with custom triggers
One "enrollment complete" policy runs a script that calls each subsequent stage by custom trigger, in order. This gives you deterministic sequencing, which scoping several independent enrollment-triggered policies does not.
Show progress with swiftDialog
A Mac that appears idle for twenty minutes gets rebooted by an impatient user, breaking provisioning. Drive a swiftDialog progress window from the orchestration script (or use Jamf's own Setup Manager) so each completed step is visible.
Finish with a recon
Always end provisioning with jamf recon so Smart Group membership reflects the newly-installed state immediately, rather than at the next scheduled check-in.
Self Service — the ticket-deflection layer
- Optional software — anything not everyone needs. Users install on demand rather than raising a ticket.
- Printer setup — one policy per printer/location, scoped by building. Removes an entire category of tickets.
- Remediation actions — "Repair Jamf connection", "Re-run enrollment", "Enable FileVault". Users fix themselves, and it's safer than talking someone through Terminal.
- Diagnostics — a policy that runs a script gathering logs and uploads them, so support requests arrive with data attached.
- Give every item a real icon and a plain-English description. An unlabelled catalogue doesn't get used.
- Anything mandatory — security baselines belong in profiles scoped to everyone, not an opt-in button.
- Anything destructive without a confirmation dialog. Self Service has no undo.
- Long-running installs with no progress indication — users will assume it hung and run it repeatedly.
Gotchas
- Scope. Check Exclusions first — they override Scope entirely, and this is the most common cause.
- Smart Group staleness. Membership only updates on recon. Run
sudo jamf reconthensudo jamf policy. - Execution frequency. "Once per computer" means it already ran and won't run again — use Flush Policy Logs to reset it for testing.
- Trigger mismatch. A policy set to "Recurring check-in" won't fire from
jamf policy -event foo. - Policy disabled, or outside its Client Side Limitations date range.
- Watch it live:
tail -f /var/log/jamf.logwhile runningsudo jamf policy.
- macOS blocks apps from Full Disk Access, Screen Recording, Accessibility, camera, and mic until explicitly allowed — user prompts can't be scripted away.
- Use a PPPC (Privacy Preferences Policy Control) profile to pre-approve them. Only MDM-delivered profiles can do this; a script cannot.
- PPPC requires the app's exact bundle ID and code requirement string. Get it with
codesign -dr - /Applications/App.app. - PPPC Utility (from the Mac admin community) generates these profiles correctly — hand-writing the code requirement is error-prone.
- A user needs a Secure Token to enable FileVault or install OS updates. Tokens are granted by an existing token holder, not by MDM alone.
- The first account created on the Mac gets the token — which is why the PreStage account setup matters so much.
- A management account created by script afterwards typically has no token and will fail at FileVault operations. Use a Bootstrap Token, escrowed to Jamf, to solve this properly.
- Verify with
sysadminctl -secureTokenStatus <user>andprofiles status -type bootstraptoken.
- The APNs certificate expires annually. Let it lapse and every Mac silently stops responding to MDM commands.
- Renew with the same Apple ID that created it. A different Apple ID means re-enrolling every device — use a shared team account, never a personal one.
- The ADE/ABM token also expires yearly and needs re-uploading.
- Diarise both. They're the most common self-inflicted Jamf outage by a wide margin.
Tips
Keep a Static Group of your own devices and scope every new policy there before widening. Jamf has no undo, and "Once per computer" at fleet scale is unforgiving.
Jamf Pro has a full REST API plus the newer Jamf Pro API. Bulk edits, reporting, and offboarding automation belong there rather than in the console.
A "once per computer" policy won't re-run on a machine that already has it logged. Policy → Logs → Flush resets that, which is essential during development.
AutoPkg with JSSImporter or jamf-upload keeps third-party app packages current automatically, instead of manually downloading and repackaging each release.
jamf displayMessage is a plain alert. swiftDialog gives branded dialogs, progress bars, and forms — a large upgrade for anything user-facing.
Almost every Jamf problem has been solved publicly already. Jamf Nation's forums and the #jamf channel on Mac Admins Slack are faster than support for most questions.