Select Page

Lesson 2 Links, Notes, and Files from Instructor:

Jamf Pro Documentation

Jamf Technical Articles

Self Service+ for macOS Deployment Guide

Apple

Navigational aid

  • Settings > Server > Cloud distribution point
  • Settings > Server > File share distribution points
  • Settings > Network > Sites
  • Settings > Network > Network segments
  • Settings > Self Service > iOS Settings > Self Service > macOS
  • https://JAMF_PRO_URL/healthCheck.html

Examples

curl
Flag Explanation
–max-time or -m Maximum time, in seconds, for the operation to complete
–silent or -s Do not show a progress meter or error messages

Display the Jamf Pro health status

curl -m 10 -s https://JAMF_PRO_URL/healthCheck.html

Files:

1. printNetworkSegment.zsh

#!/bin/zsh –no-rcs

interface=$(route get www.apple.com | awk ‘/interface/{print $NF}’)

network=$(ipconfig getifaddr $interface | awk -F. ‘{print $1″.”$2″.”$3}’)
echo “Starting IP: $network.1”
echo “Ending IP: $network.254”

Lesson 3 Links, Notes, and Files from Instructor:

 

Lesson 3: API Roles and Clients

Last updated February 19, 2026

Objective

Integrate tools into Jamf Pro using API Roles and Clients.

Discussion

  • Jamf Pro API
    • API Authentication
      • API Roles and Clients
      • Bearer Token
    • Integrating Tools
  • Transfer data from or to a server, curl

Resources

Jamf Pro Documentation

Jamf Developer Portal

Jamf Sync

Navigational aid

Settings > System > API Roles and Clients

Examples

curl

Obtain and save a bearer token as a variable

baseURL="JAMF_PRO_URL"
client_id="CLIENT_ID"
client_secret="CLIENT_SECRET"

access_token=$(curl --silent --location \
    --request POST "https://$baseURL/api/oauth/token" \
    --header "Content-Type: application/x-www-form-urlencoded" \
    --data-urlencode "client_id=$client_id" \
    --data-urlencode "grant_type=client_credentials" \
    --data-urlencode "client_secret=$client_secret" | plutil -extract "access_token" raw -)

# Check that bearer token is saved successfully:
curl --silent --header "Authorization: Bearer $access_token" https://$baseURL/api/v2/computers-inventory

Examples from Instructor:

1. printNetworkSegment.zsh

#!/bin/zsh –no-rcs
#

baseURL=”n300-1a.pro.jamf.training”
client_id=”4fe4b78d-a0f6-47b3-a3ea-b50dcb19c0e9″
client_secret=”8tsr4wzbStk17H-Akg4febxrl6sxA9HNdmpfFXpec12Hbm43Fvza84ZnDfKude96″

access_token=$(curl –silent –location \
–request POST “https://$baseURL/api/oauth/token” \
–header “Content-Type: application/x-www-form-urlencoded” \
–data-urlencode “client_id=$client_id” \
–data-urlencode “grant_type=client_credentials” \
–data-urlencode “client_secret=$client_secret” | plutil -extract “access_token” raw -)

# Check that bearer token is saved successfully:
curl –silent –header “Authorization: Bearer $access_token” https://$baseURL/api/v2/computers-inventory | jq .

Lesson 4 Links, Notes, and Files from Instructor:

 

Lesson 4: Enrollment

Last updated February 19, 2026

Objective

Enroll computers and mobile devices with an associated LDAP user.

Discussion

  • Device Enrollment
    • Supervision
  • User-Initiated Enrollment
    • LDAP
  • Enrollment Invitations
    • Enrollment Profile
  • Local Administrator Password Solution (LAPS)
    • Mobile Device Management (MDM)
    • Jamf Management Framework (JMF)
    • API
      • Enablement
      • View Configuration
      • Manage Local Administrator Accounts
        • View accounts and passwords
        • Manage (Accounts)
  • Login and Background Items (macOS 13 or later)

Resources

Jamf 300 Course

Jamf Pro Documentation

Jamf Technical Articles

Jamf

Apple Platform Deployment

Navigational aid

  • Settings > Global > User-initiated enrollment
  • Settings > Computer Management > Security
  • Devices > Enrollment Profiles
  • Computers > Search Inventory > History > Managed Local Administrator Account History
  • https://JAMF_PRO_URL/api/doc

Examples

Jamf Pro API
https://server.pro.jamf.training/api/doc

Lesson 5 Links, Notes, and Files from Instructor:

 

Lesson 5: Framework

Last updated February 19, 2026

Objective

Configure the management framework and create scheduled tasks.

Discussion

  • Login Events
  • Check-in
  • Daemons
  • Agents
  • A document of XML configuration details, man launchd.plist
  • Access XML property lists, defaults
  • Daemon and agent management tool, launchctl
    • Bootout an agent or daemon from memory, bootout
    • Bootstrap an agent or daemon into memory, bootstrap
  • User identity utility, id

Important:

In Jamf training courses, the term “print” is used to represent the action of displaying the output of a command in a script or Terminal window.

Resources

Jamf Pro Documentation

Daemons and Services Programming Guide

Terminal User Guide

Navigational aid

  • Jamf Pro – Settings > Computer management > Check-in
  • macOS
    • /System/Library/LaunchDaemons/
    • /Library/LaunchDaemons/
    • /System/Library/LaunchAgents/
    • /Library/LaunchAgents/
    • ~/Library/LaunchAgents/

Examples

defaults

Print a property list

defaults read /PATH/TO/FILE

Print a specific property

defaults read /PATH/TO/FILE SOME_KEY

Set or modify a property

defaults write /PATH/TO/FILE SOME_KEY -boolean SOME_BOOLEAN
defaults write /PATH/TO/FILE SOME_KEY -integer SOME_INTEGER
defaults write /PATH/TO/FILE SOME_KEY -string SOME_X_VALUE

Remove a property

defaults delete /PATH/TO/FILE SOME_KEY
id

List the current user’s unique ID

id -u

List the unique ID for a user

id -u USER
launchctl

Bootout a user agent or daemon from memory

launchctl bootout gui/<USER_UID> /PATH/TO/FILE

Bootstrap a user agent or daemon into memory

launchctl bootstrap gui/<USER_UID> /PATH/TO/FILE

Bootout a system agent or daemon from memory

launchctl bootout system /PATH/TO/FILE

Bootstrap a system agent or daemon into memory

launchctl bootstrap system /PATH/TO/FILE

Start an agent or daemon with the label identifier

launchctl start LABEL_IDENTIFIER

List running agents or daemons and search for a specified service

launchctl list | grep SERVICE_NAME

Check the formatting on an agent or daemon

plutil -lint /PATH/TO/FILE

Set ownership and permission for a system agent or daemon

chown root:wheel /PATH/TO/FILE
chmod 644 /PATH/TO/FILE

Bootout the Dock agent for user with unique ID 502

launchctl bootout gui/502 
/System/Library/LaunchAgents/com.apple.Dock.plist

Bootstrap the Dock agent for user with unique ID 502

launchctl bootstrap gui/502 
/System/Library/LaunchAgents/com.apple.Dock.plist

Start the Dock process

launchctl start com.apple.Dock.agent

Compose a daemon using the jamf binary

jamf scheduledTask -command "/bin/zsh "'"/PATH/TO/FILE"'"" -name CUSTOM_NAME -runAtLoad true -minute '*/NUMBER_OF_MINUTES/'

Print the current date to a file

date -u +%F\ %T >> /PATH/TO/FILE

Update Jamf management framework

/usr/local/jamf/bin/jamf manage

Bootout a system agent or daemon with label

launchctl bootout system/LABEL_IDENTIFIER
Example agent and daemon

Agent to open the Jamf Learning Hub

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>CUSTOM_LABEL_HERE</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/bin/open</string>
		<string>https://learn.jamf.com</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>

Daemon to call a script on a timer

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>CUSTOM_LABEL_HERE</string>
	<key>ProgramArguments</key>
	<array>
		<string>/bin/zsh</string>
		<string>/PATH/TO/FILE</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>StartInterval</key>
	<integer>NUMBER_OF_SECONDS</integer>
</dict>
</plist>

Examples from Instructor:

1. 01-manipulating-jobs.sh

#!/bin/zsh –no-rcs
# Manipulating LaunchD Tasks

# Shows agents and applications I have in my user context
launchctl list

# Shows all of the launch daemons
sudo launchctl list

# Shows all of the launch daemons, minus any that contain “com.apple”

sudo launchctl list | grep -v com.apple

# Show me the Dock job
launchctl list | grep Dock

# Print the Dock job
launchctl print gui/$(id -u)/com.apple.Dock.agent

# Boot-out/de-register/unload
launchctl bootout gui/$(id -u) /System/Library/LaunchAgents/com.apple.Dock.plist

# Register/load/bootstrap the Dock job back
launchctl bootstrap gui/$(id -u) /System/Library/LaunchAgents/com.apple.Dock.plist

# Tell launchd to actually *start* the ProgramArguments in the job description
launchctl kickstart -p gui/$(id -u)/com.apple.Dock.agent

2. make-agent-to-open-url.sh

#!/bin/zsh –no-rcs
# Whenever anyone logs in, open a specific webpage
# Command the Launch Agent needs to run:
# open
# https://n300-1a.pro.jamf.training

# Label = com….
# ProgramArguments =
# – /usr/bin/open
# – $URL
# RunAtLoad = true

label=”com.demo.open.jamfproserver”
plistPath=”/Library/LaunchAgents/$label.plist”
URL=”https://n300-1a.pro.jamf.training”

#sudo launchctl bootout gui/$(id -u) “$plistPath”
sudo rm “$plistPath”

sudo launchctl bootout gui/$(id -u)/$label

sudo defaults write “$plistPath” Label -string “$label”

sudo defaults write “$plistPath” ProgramArguments -array -string “/usr/bin/open” -string “$URL”

sudo defaults write “$plistPath” RunAtLoad -boolean TRUE

#ls -la $plistPath
sudo chmod 644 “$plistPath”

sudo launchctl bootstrap gui/$(id -u) “$plistPath”

3. 03-fast-recon-8hrs.sh

#!/bin/zsh –no-rcs
# Run Inventory Update at Boot and every 8 hours
# Command to run:
# jamf recon
# Label = $label
# ProgramArguments =
# – path to jamf
# – recon
# RunAtLoad = true
# StartInterval = (int) 60*60*8 = 28,800 seconds

 

label=”com.demo.fastrecon.8hrs”
plistPath=”/Library/LaunchDaemons/$label.plist”

sudo rm “$plistPath”

sudo launchctl bootout system/$label

sudo defaults write “$plistPath” Label -string “$label”

sudo defaults write “$plistPath” ProgramArguments -array -string “/usr/local/bin/jamf” -string “recon”

sudo defaults write “$plistPath” RunAtLoad -boolean TRUE

sudo defaults write “$plistPath” StartInterval -integer 28800

#ls -la $plistPath
sudo chmod 644 “$plistPath”

sudo launchctl bootstrap system “$plistPath”

4. 04-fast-recon-logger.sh

#!/bin/zsh –no-rcs
#

/usr/local/bin/jamf recon

echo “Ran fast recon at $(date)” >> /var/log/recon.log

5. 05-fast-recon-with-script.sh

#!/bin/zsh –no-rcs
# Run Inventory Update at Boot and every 8 hours
# Command to run:
# jamf recon, plus some logging
# Label = $label
# ProgramArguments =
# – path to zsh
# – path to script
# RunAtLoad = true
# StartInterval = (int) 60*60*8 = 28,800 seconds

 

label=”com.demo.fastrecon.8hrs”
plistPath=”/Library/LaunchDaemons/$label.plist”
# Script was just manually placed here in Finder!
scriptPath=”/Library/Scripts/recon-logger.sh”

sudo rm “$plistPath”

sudo launchctl bootout system/$label

sudo defaults write “$plistPath” Label -string “$label”

sudo defaults write “$plistPath” ProgramArguments -array -string “/bin/zsh” -string “$scriptPath”

sudo defaults write “$plistPath” RunAtLoad -boolean TRUE

sudo defaults write “$plistPath” StartInterval -integer 28800

#ls -la $plistPath
sudo chmod 644 “$plistPath”
sudo chmod 744 “$scriptPath”
sudo chown root:wheel “$scriptPath”

sudo launchctl bootstrap system “$plistPath”

Completed Tasks

Task1.sh

#!/bin/zsh –no-rcs
# Task 01 – Compose an agent with the label com.Lesson5Task1.agent to open the Jamf Learning Hub: https://learn.jamf.com.

# Command the Launch Agent needs to run:
# open
# https://learn.jamf.com
# Label = com….
# ProgramArguments =
# – /usr/bin/open
# – $URL
# RunAtLoad = true

label=”com.Lesson5Task1.agent”
plistPath=”/Library/LaunchAgents/$label.plist”
URL=”https://learn.jamf.com”

sudo rm “$plistPath”

sudo defaults write “$plistPath” Label -string “$label”

sudo defaults write “$plistPath” ProgramArguments -array -string “/usr/bin/open” -string “$URL”

sudo defaults write “$plistPath” RunAtLoad -boolean TRUE

#ls -la $plistPath
sudo chmod 644 “$plistPath”

Task2.sh

#!/bin/zsh –no-rcs
# Task 02 – Compose a script to update the management framework and print the current time to the file /Users/Shared/managementTime.txt.
# Manually place this script somewhere on your test Mac’s filesystem (/Library/Scripts, e.g.) so your daemon can run it

/usr/local/bin/jamf manage

echo “Updated management framework at $(date)” >> /Users/Shared/managementTime.txt

Task3.sh

#!/bin/zsh –no-rcs
# Task 03 – Compose a daemon with the label com.Lesson5Task3.daemon to execute the script from Task 2 with a timed interval of 20 minutes.

# Command to run:
# a script that runs jamf manage, plus some logging
# Label = $label
# ProgramArguments =
# – path to zsh
# – path to script
# RunAtLoad = true
# StartInterval = (int) 60*20 = 1200 seconds

label=”com.Lesson5Task3.daemon”
plistPath=”/Library/LaunchDaemons/$label.plist”
# Script was just manually placed here in Finder!
scriptPath=”/Library/Scripts/Task-02.sh”

sudo rm “$plistPath”

sudo defaults write “$plistPath” Label -string “$label”

sudo defaults write “$plistPath” ProgramArguments -array -string “/bin/zsh” -string “$scriptPath”

#Technically we don’t really need this to happen right at boot, so this can be ommitted.
#sudo defaults write “$plistPath” RunAtLoad -boolean TRUE

sudo defaults write “$plistPath” StartInterval -integer 1200

#ls -la $plistPath
sudo chmod 644 “$plistPath”
sudo chmod 744 “$scriptPath”
sudo chown root:wheel “$scriptPath”

 

Task4.sh

#!/bin/zsh –no-rcs
# Task 04 – Bootstrap the agent and daemon from Tasks 1 and 3

# Bootstrap Agent
label=”com.Lesson5Task1.agent”
plistPath=”/Library/LaunchAgents/$label.plist”

launchctl bootout gui/$(id -u)/$label
launchctl bootstrap gui/$(id -u) “$plistPath”

# Bootstrap Daemon
label=”com.Lesson5Task3.daemon”
plistPath=”/Library/LaunchDaemons/$label.plist”

sudo launchctl bootout system/$label
sudo launchctl bootstrap system “$plistPath”

Lesson 6 Links, Notes, and Files from Instructor:

 

Lesson 6: User Management

Last updated February 19, 2026

Objective

Configure settings and preferences for users.

Discussion

  • Mobile device configuration profiles
    • Notifications
  • Computer configuration profiles
    • Computer-level configuration profiles
      • Notifications
      • Application & Custom Settings
        • defaults
        • plutil
          • Property list utility
        • Custom Schemas
          • Managed App Schema Builder
    • User-level configuration profiles
      • MDM capable user
      • Mail
  • Payload variables

Resources

Jamf Pro Documentation

Jamf

Apple Platform Deployment

Third-party GitHub repositories

JSONLint

Command manual pages

Navigational aid

  • Jamf Pro
    • Computers > Configuration Profiles
    • Devices > Configuration Profiles
  • macOS
    • /Library/Preferences/
    • ~/Library/Preferences/
    • /Library/Managed Preferences/

Examples

defaults

Print a property list

defaults read /PATH/TO/FILE

Print a specific property

defaults read /PATH/TO/FILE SOME_KEY

Set or modify a property

defaults write /PATH/TO/FILE SOME_KEY -boolean BOOLEAN_VALUE 
defaults write /PATH/TO/FILE SOME_KEY -integer CUSTOM_INTEGER
defaults write /PATH/TO/FILE SOME_KEY -string CUSTOM_VALUE

Remove a property

defaults delete /PATH/TO/FILE SOME_KEY
Safari

Enforce Safari Smart Search Field setting

defaults write ~/Desktop/com.apple.Safari ShowFullURLInSmartSearchField -boolean true

Enforce Safari window behavior

defaults write ~/Desktop/com.apple.Safari.plist NewWindowBehavior -integer 0

Enforce Safari homepage behavior

defaults write ~/Desktop/com.apple.Safari.plist HomePage https://trainingcatalog.jamf.com

Set Safari homepage

defaults write ~/Desktop/com.apple.Safari.SandboxBroker.plist Homepage https://trainingcatalog.jamf.com
Convert a binary encoded file to XML
plutil -convert xml1 /PATH/TO/FILE
Dock Custom Schema
Item Value
Preference Domain com.apple.dock
Domain Description Manage the dock location
Key Description of Key Value Type
orientation Dock location String

Examples from Instructor:

1. find-key-name-from-log-stream.sh

#!/bin/zsh –no-rcs
# Pull Preference Key changes from the Unified Log Stream
# Will need “Enable Private Log Data” Profile manually installed from
# https://eclecticlight.co/2026/04/30/control-what-gets-written-to-the-log/
# to see key names in output

/usr/bin/log stream –info –debug –predicate ‘process==”cfprefsd” && eventMessage CONTAINS “wrote the key”‘

2. write-out-secure-kb-entry-plist.sh

#!/bin/zsh –no-rcs
# Write out Secure Keyboard Entry setting to the desktop

# Key: SecureKeyboardEntry
# Type: Boolean
# Value: TRUE

defaults write ~/Desktop/securekeyboardentry.plist SecureKeyboardEntry -boolean TRUE

# Convert to XML plist

plutil -convert xml1 ~/Desktop/securekeyboardentry.plist -o ~/Desktop/securekeyboardentry-xml.plist

3. com.apple.dock.json

{
“_appTitle”: “Dock”,
“_exported”: “MASB”,
“title”: “com.apple.dock”,
“description”: “”,
“properties”: {
“orientation”: {
“title”: “Dock Orientation”,
“description”: “orientation”,
“default”: “bottom”,
“property_order”: 5,
“type”: “string”,
“options”: {
“enum_titles”: [“Screen Left”, “Screen Bottom”, “Screen Right”],
“infoText”: “”
},
“enum”: [“left”, “bottom”, “right”]
}
}
}

4. com.apple.Safari.plist

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
      <key>ShowFullURLInSmartSearchField</key>
      <true/>
</dict>
</plist>

5. com.krill.CodeRunner.json

{
“_appTitle”: “CodeRunner”,
“_exported”: “MASB”,
“title”: “com.krill.CodeRunner”,
“description”: “”,
“properties”: {
“AskToSaveWhenQuitting”: {
“title”: “Ask To Save When Quitting”,
“description”: “AskToSaveWhenQuitting”,
“default”: false,
“property_order”: 5,
“type”: “boolean”,
“options”: {
“infoText”: “”
}
},
“DefaultTabModeWidth”: {
“title”: “Default Tab Width”,
“description”: “DefaultTabModeWidth”,
“property_order”: 10,
“type”: “integer”,
“options”: {
“enum_titles”: [“Two”, “Three”, “Four”, “Six”, “Eight”],
“infoText”: “”
},
“enum”: [2,3,4,6,8]
},
“ColorTheme”: {
“title”: “Theme”,
“description”: “ColorTheme”,
“property_order”: 15,
“type”: “string”,
“options”: {
“enum_titles”: [“Blackboard”, “Mac Classic”, “Spacegrey”, “Sunburst”, “Dusk”],
“infoText”: “”
},
“enum”: [“Blackboard”, “Mac Classic”, “Spacegrey”, “Sunburst”, “Dusk”]
}
}
}

Lesson 7 Links, Notes, and Files from Instructor:

Lesson 7: Managed Login Items

Last updated February 19, 2026

Objective

Safelist and manage scheduled tasks and third-party helper apps.

Discussion

  • Managed Login Items
    • Apps
    • Agents
    • Daemons
    • Executables
  • Rule Type
    • Bundle identifier
    • Bundle identifier prefix
    • Label
    • Label prefix
    • Team identifier
  • Rule Values

Resources

Jamf Pro Documentation

Apple Platform Deployment

Navigational aid

  • Jamf Pro – Computers > Configuration Profiles > Managed Login Items
  • macOS – System Settings > General > Login Items

Examples

Bundle Identifier

Obtain the bundle identifier and team id for an app

codesign --display --verbose /Applications/APPLICATION.app

Obtain the bundle identifier for an executable

codesign --display --verbose /PATH/TO/BINARY
Label

Print the labels of active agents or daemons

launchctl list

Print the label of an agent or daemon

defaults read /PATH/TO/FILE.plist Label

Completed Tasks and Examples:

get-teamID-bundleID.sh

#!/bin/zsh –no-rcs
# codesign – get Team ID or Bundle ID

codesign –display –verbose /Applications/OneDrive.app

#Executable=/Applications/OneDrive.app/Contents/MacOS/OneDrive
#Identifier=com.microsoft.OneDrive <<—- BUNDLE ID
#Format=app bundle with Mach-O universal (x86_64 arm64)
#CodeDirectory v=20500 size=119330 flags=0x10000(runtime) hashes=3718+7 location=embedded
#Signature size=9012
#Timestamp=Jul 10, 2026 at 6:33:49 PM
#Info.plist entries=38
#TeamIdentifier=UBF8T346G9 <<—— TEAM ID
#Runtime Version=26.0.0
#Sealed Resources version=2 rules=13 files=946
#Internal requirements count=1 size=184

echo; echo

codesign –display –verbose /Applications/zoom.us.app/

echo; echo

codesign –display –verbose /Applications/Google\ Chrome.app/