Back up (or restore) Jamf Pro objects with PowerShell

I recently started working a lot with Jamf Pro and have been enjoying it quite a bit.
Coming from a heavy background in Intune, there is a lot to learn an understand with a new MDM. This post is about a tool I wrote to help myself and hopefully others with a similar situation.
If you’re tinkering with any system, ideally, you’d take a snapshot before making changes—so why not your Jamf configs? I’ve messed around with clunky backup methods before, but they left me hoping for more functionality. Restores were a pain, everything dumped back at once, names clashed, and versioning was a guessing game. Then I caught "Back to the Future: Backing Up All (most) of The Objects in Jamf Pro" from JNUC 2023, and it flipped a switch. I had to build something better for myself.
Enter PsJamfBackupRestore, a PowerShell tool set that backs up and restores your Jamf Pro setup with finesse. While new and in a alpha state, it's got:
- Selective backups—grab just Computers, Scripts, Policies, or whatever you pick.
- Support for tons of config types, from Profiles to Prestages.
- Authentication your way: Username/Password or OAuth Client ID/Secret.
- Clean backups to a JAMF_Backup folder, organized by resource.
- Token smarts—auto-renewal and cleanup included.
Usage
Kick things off by cloning the repo:
git clone https://github.com/jorgeasaurus/PsJamfBackupRestore.git
Set-Location PsJamfBackupRestore
Tweaking config.ps1 with your Jamf Pro details—URL, credentials,etc:
[hashtable]$script:Config = @{
BaseUrl = "https://example.jamfcloud.com"
Username = "username" # Leave empty if using API credentials
Password = "password" # Leave empty if using API credentials
#clientId = "your-client-id" # Fill if using API credentials
#clientSecret = "your-client-secret"# Fill if using API credentials
DataFolder = Join-Path (Get-Location) "JAMF_Backup"
ApiVersion = "classic" # Use 'v1','v2' or 'classic'
Token = $null
}
Load the configs and functions:
. (Join-Path (Get-Location) "config.ps1")
. (Join-Path (Get-Location) "JamfBackupRestoreFunctions.ps1")
Then dive in. Here’s the rundown:
Request a token from Jamf
$tokenParams = @{
Username = $script:Config.Username
Password = $script:Config.Password
JamfProUrl = $script:Config.JamfProUrl
}
$script:Config.Token = Get-JamfToken @tokenParams
Backup Everything: Snag all Scripts (or any resource) and nuke old backups (optional):
Download-JamfObjects -Resource "scripts" -ClearExports
Backup One Thing: Grab a specific config by ID:
Download-JamfObject -ID "3" -Resource "osxconfigurationprofiles"
Restore a Single Object: Push an updated object back:
Upload-JamfObject -Token $Config.Token -FilePath "JAMF_Backup/policies/3_Google_Chrome.xml" -Resource "policies" -Id "3" -Update
Create Something New: Add a fresh category:
Upload-JamfObject -Token $Config.Token -FilePath "JAMF_Backup/categories/Security.xml" -Resource "categories"
Restore a Batch: Bring back all Policies:
Upload-JamfObjects -Resource "policies"
Clean Up: Revoke your token when you’re done:
Invalidate-JamfToken -Token $Config.Token
Check the repo’s README for the full playbook.
How It Works
This script chats with the Jamf API, juggling Classic (/JSSResource) and v1 (/api/v1/) endpoints—v2’s wired up too, just waiting for Jamf to fully support it. You set your creds in $Config (Username/Password or OAuth), and it pulls down resources as JSON or XML, depending on the API. Scripts get a bonus .sh file alongside their metadata. Everything lands in JAMF_Backup, split by type—think policies/1_Policy_Name.xml or scripts/2_Script_Name.sh. Tokens renew automatically, and you can zap them when you’re done for security.
What’s Next?
- I hope to add more supported api endpoints.
- Possibly a console gui for more interactive use.
- Functionality to post the exports in a repository.
Anyway, any feedback is welcome, pull requests also encouraged.