Mac – Generic DMG Installer – JumpCloud
This guide shows how to deploy macOS applications packaged as DMG files using a single generic shell script in JumpCloud Commands. You’ll set the download URL, scope to devices or groups, and handle mounting, copying to /Applications, and cleanup.
On this page
Purpose
Install macOS applications distributed as .dmg files using a single reusable script executed from JumpCloud → Commands. This is ideal for Chrome, Firefox, Slack, and similar DMG-based apps.
Prerequisites
- Admin access to the JumpCloud Admin Portal
- Target macOS devices enrolled in JumpCloud
- A direct DMG download URL or a URL that redirects to a DMG (validated via headers)
- Network egress allowed to the app vendor’s CDN
Tip: If you’re setting up new Macs, see our SOP on Automated macOS Device Enrollment via JumpCloud MDM (ADE + ABM + ZTE)
to make this part of your zero-touch flow.
Step-by-Step Instructions
Step 1 — Create the command
- Log in to JumpCloud Admin Portal.
- Go to Devices → Commands.
- Click + to add a new command.
- Select macOS (Shell).
- Give the command a clear name (for example, Install – Chrome (DMG)).
Step 2 — Configure the script
- In the script, set DownloadUrl="DOWNLOAD_URL" to the app’s DMG link.
- The URL must either:
- End with .dmg, or
- Return a Location header that points to a DMG (the script checks this).
You can quickly verify with:
curl -s --head "<your URL>"
Look for a Location header ending in .dmg.
Step 3 — Scope and run
- Assign the command to the target device(s) or device group.
- Click Save, then Run (or schedule as needed).
- Monitor the command logs for “Copied … to /Applications” and cleanup messages.
Command (use as-is; set the DownloadUrl)
#!/bin/bash
# *** USAGE *** Version: 1.2
# NOTE: Designed for DMG files only (not .pkg, .zip, or DMGs containing .pkg).
# Set the DMG download URL below.
DownloadUrl="DOWNLOAD_URL"
### Modify below this line at your own risk!
# Locate DMG Download Link From URL
regex='^https.*.dmg$'
if [[ $DownloadUrl =~ $regex ]]; then
echo "URL points to direct DMG download"
validLink="True"
else
echo "Searching headers for download links"
urlHead=$(curl -s --head "$DownloadUrl")
locationSearch=$(echo "$urlHead" | grep https:)
if [ -n "$locationSearch" ]; then
locationRaw=$(echo "$locationSearch" | awk '{print $2}')
locationFormatted="$(echo "${locationRaw}" | tr -d '[:space:]')"
regex='^https.*'
if [[ $locationFormatted =~ $regex ]]; then
echo "Download link found"
DownloadUrl="$locationFormatted"
else
echo "No https location download link found in headers"
exit 1
fi
else
echo "No location download link found in headers"
exit 1
fi
fi
# Create Temp Folder
DATE=$(date '+%Y-%m-%d-%H-%M-%S')
TempFolder="Download-$DATE"
mkdir -p "/tmp/$TempFolder"
# Navigate to Temp Folder
cd "/tmp/$TempFolder" || exit
# Download File into Temp Folder
curl -s -O "$DownloadUrl"
# Capture name of Download File
DownloadFile="$(ls)"
echo "Downloaded $DownloadFile to /tmp/$TempFolder"
# Verify DMG File
regex='\.dmg$'
if [[ $DownloadFile =~ $regex ]]; then
DMGFile="$DownloadFile"
echo "DMG File Found: $DMGFile"
else
echo "File: $DownloadFile is not a DMG"
rm -r "/tmp/$TempFolder"
echo "Deleted /tmp/$TempFolder"
exit 1
fi
# Mount DMG File (-nobrowse prevents the volume from popping up in Finder)
hdiutilAttach=$(hdiutil attach "/tmp/$TempFolder/$DMGFile" -nobrowse)
echo "Used hdiutil to mount $DMGFile"
err=$?
if [ ${err} -ne 0 ]; then
echo "Could not mount $DMGFile Error: ${err}"
rm -r "/tmp/$TempFolder"
echo "Deleted /tmp/$TempFolder"
exit 1
fi
regex='\/Volumes\/.*'
if [[ $hdiutilAttach =~ $regex ]]; then
DMGVolume="${BASH_REMATCH[0]}"
echo "Located DMG Volume: $DMGVolume"
else
echo "DMG Volume not found"
rm -r "/tmp/$TempFolder"
echo "Deleted /tmp/$TempFolder"
exit 1
fi
# Identify the mount point for the DMG file
DMGMountPoint=$(hdiutil info | grep "$DMGVolume" | awk '{ print $1 }')
echo "Located DMG Mount Point: $DMGMountPoint"
# Capture name of App file
cd "$DMGVolume" || exit
AppName=$(ls | grep '.app')
cd ~ || exit
echo "Located App: $AppName"
# Test to ensure App is not already installed
ExistingSearch=$(find "/Applications/" -name "$AppName" -depth 1)
if [ -n "$ExistingSearch" ]; then
echo "$AppName already present in /Applications folder"
hdiutil detach "$DMGMountPoint"
echo "Used hdiutil to detach $DMGFile from $DMGMountPoint"
rm -r "/tmp/$TempFolder"
echo "Deleted /tmp/$TempFolder"
exit 1
else
echo "$AppName not present in /Applications folder"
fi
DMGAppPath=$(find "$DMGVolume" -name "*.app" -depth 1)
# Copy the contents of the DMG file to /Applications/
# Preserves all file attributes and ACLs
cp -pPR "$DMGAppPath" /Applications/
err=$?
if [ ${err} -ne 0 ]; then
echo "Could not copy $DMGAppPath Error: ${err}"
hdiutil detach "$DMGMountPoint"
echo "Used hdiutil to detach $DMGFile from $DMGMountPoint"
rm -r "/tmp/$TempFolder"
echo "Deleted /tmp/$TempFolder"
exit 1
fi
echo "Copied $DMGAppPath to /Applications"
# Unmount the DMG file
hdiutil detach "$DMGMountPoint"
echo "Used hdiutil to detach $DMGFile from $DMGMountPoint"
err=$?
if [ ${err} -ne 0 ]; then
echo "Could not detach DMG: $DMGMountPoint Error: ${err}"
fi
# Remove Temp Folder and download
rm -r "/tmp/$TempFolder"
echo "Deleted /tmp/$TempFolder"
Validated DMG download URLs (examples)
- https://dl.google.com/chrome/mac/universal/stable/GGRO/googlechrome.dmg
- https://download.mozilla.org/?product=firefox-latest-ssl&os=osx&lang=en-US
- https://go.microsoft.com/fwlink/p/?linkid=525133
- https://slack.com/ssb/download-osx
Note: Some vendor links redirect; the script resolves the final DMG URL automatically.
Expected result / validation
- Command output shows URL detection, DMG mount, copy to /Applications, detach, and temp cleanup.
- The application appears in /Applications on target Macs and is ready to launch.
- Re-running the command will safely exit if the app already exists.
FAQs
1) Does this support .pkg or .zip?
No. This template is DMG-only. For PKG deployments, use a dedicated PKG installer workflow in JumpCloud.
2) How do I ensure the URL is correct?
Run:
curl -s --head "<URL>"
Confirm the Location header ends in .dmg, or the original URL ends with .dmg.
3) What if the DMG contains a .pkg instead of an .app?
This script expects a top-level .app. If the DMG contains a .pkg, use a PKG install command.
4) Can I scope this per team or department?
Yes. Assign the command to specific device groups to align with your app catalog strategy.
Need help securing your environment?
Talk to a NetNXT security expertStay ahead of the next vulnerability
New KB guides, threat advisories and hardening playbooks from NetNXT's security team — straight to your inbox.
NetNXT will handle your data pursuant to its Privacy Policy.
Like this guide? Join our team.
NetNXT builds security for how modern enterprises actually run.
View open roles