NetNXT Logo

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.

November 13, 2025
5 min read
ByNetNXT
On this page
Share this article

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

  1. Log in to JumpCloud Admin Portal.
  2. Go to Devices → Commands.
  3. Click + to add a new command.
  4. Select macOS (Shell).
  5. 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

  1. Assign the command to the target device(s) or device group.
  2. Click Save, then Run (or schedule as needed).
  3. 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)

  1. https://dl.google.com/chrome/mac/universal/stable/GGRO/googlechrome.dmg
  2. https://download.mozilla.org/?product=firefox-latest-ssl&os=osx&lang=en-US
  3. https://go.microsoft.com/fwlink/p/?linkid=525133
  4. 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 expert
Was this article helpful?

Stay 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

Have a question about this guide?

Our security engineers read every message.

Contact us