Skip to main content
Question

Jamf School - macOS Script Installations Headache

  • October 17, 2025
  • 3 replies
  • 71 views

dflowers
Forum|alt.badge.img+1

Hi everyone,

I’m hoping someone here can shed some light on an issue that’s been giving me a real headache lately.

I’m currently trying to deploy scripts via Jamf School to install Sophos Endpoint and Datto RMM on macOS devices. I’ve followed all the guidance I could find online (I’ll drop links below to the documentation I’ve been working from), but I’m running into some frustrating inconsistencies:

  • Sophos Endpoint: The script appears to run without any errors, but the installation doesn’t seem to complete successfully. There’s no feedback or logs indicating what might be going wrong.
  • Datto RMM: This one does throw an error, but it’s not very descriptive. I’ll include the exact error message below once I get a chance to pull it again.

I’ve double-checked permissions, script formatting, and the way I’m pushing these out via Jamf School, but I’m still stuck. I’m starting to wonder:

  • Has anyone successfully deployed either of these tools via Jamf School scripts?
  • Is what I’m trying to do even possible within the limitations of Jamf School?
  • Could there be something specific about these installers that Jamf School doesn’t handle well?

Any insights, suggestions, or examples of working deployments would be massively appreciated. Thanks in advance!

Links to guidance I’ve followed: Sophos Guidance, Datto Guidance (Install the Agent on macOS from the Terminal)

Datto Error:

 

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0Warning: Failed to open the file Agent.zip: Read-only file system

  0 27.8M    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (56) Failure writing output to destination, passed 8192 returned 4294967295
unzip:  cannot find or open Agent.zip, Agent.zip.zip or Agent.zip.ZIP.

3 replies

dflowers
Forum|alt.badge.img+1
  • Author
  • New Contributor
  • October 17, 2025

Datto RMM Error we are seeing: 
 

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0Warning: Failed to open the file Agent.zip: Read-only file system

  0 27.8M    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (56) Failure writing output to destination, passed 8192 returned 4294967295
unzip:  cannot find or open Agent.zip, Agent.zip.zip or Agent.zip.ZIP.


Forum|alt.badge.img+11
  • Contributor
  • October 17, 2025

The error you are seeing, seems to indicate that it can write the file to whatever folder the command is executing from. I would also execute it from /tmp/ or /Users/Shared/ and see if it's able to extract the file then. Or from a script within jamdf of course. This assumes that you are replacing the platform and siteid with the correct values.

As far as as script you couldrunfrom jamf this may work, as longs you pass it right parameters

#!/bin/zsh
# Datto RMM (CentraStage) Mac Agent installer
# Usage examples:
#   ./install_datto_agent.zsh --platform concord --site-id 12345
#   ./install_datto_agent.zsh --platform https://concord.centrastage.net --site-id 12345
#   ./install_datto_agent.zsh --url "https://concord.centrastage.net/csm/profile/downloadMacAgent/12345"
#
# Notes:
# - "platform" is the subdomain you see when logged into Datto RMM, e.g. https://concord.centrastage.net
# - "siteID" comes from Site Settings.

set -euo pipefail

# ---------- Defaults ----------
KEEP_ARTIFACTS=0
DOWNLOAD_URL=""
PLATFORM_INPUT=""
SITE_ID=""

usage() {
  cat <<'USAGE'
Datto RMM Mac Agent installer

Options:
  -u, --url <full-url>          Full download URL (takes precedence)
  -p, --platform <platform>     Platform (e.g., "concord" or "https://concord.centrastage.net")
  -s, --site-id <id>            Site ID from Site Settings
  -k, --keep                    Keep downloaded/extracted files for troubleshooting
  -h, --help                    Show this help

Examples:
  ./install_datto_agent.zsh --platform concord --site-id 12345
  ./install_datto_agent.zsh --platform https://concord.centrastage.net --site-id 12345
  ./install_datto_agent.zsh --url "https://concord.centrastage.net/csm/profile/downloadMacAgent/12345"
USAGE
}

# ---------- Parse args ----------
while [[ $# -gt 0 ]]; do
  case "$1" in
    -u|--url)        DOWNLOAD_URL="${2:-}"; shift 2 ;;
    -p|--platform)   PLATFORM_INPUT="${2:-}"; shift 2 ;;
    -s|--site-id|--siteid) SITE_ID="${2:-}"; shift 2 ;;
    -k|--keep)       KEEP_ARTIFACTS=1; shift ;;
    -h|--help)       usage; exit 0 ;;
    *) echo "Unknown option: $1" >&2; usage; exit 1 ;;
  esac
done

# ---------- Root elevation for installer ----------
if [[ $EUID -ne 0 ]]; then
  echo "[*] Elevating to root..."
  exec sudo /bin/zsh "$0" "$@"
fi

# ---------- Build/validate URL if not provided ----------
normalize_platform() {
  local in="$1"
  # Strip scheme and path
  in="${in#*://}"
  in="${in%%/*}"
  # Append domain if user only provided the subdomain
  if [[ "$in" != *".centrastage.net" ]]; then
    in="${in}.centrastage.net"
  fi
  printf "%s" "https://${in}"
}

if [[ -z "$DOWNLOAD_URL" ]]; then
  if [[ -z "$PLATFORM_INPUT" || -z "$SITE_ID" ]]; then
    echo "[!] You must provide either --url OR both --platform and --site-id." >&2
    usage
    exit 2
  fi
  PLATFORM_BASE="$(normalize_platform "$PLATFORM_INPUT")"
  DOWNLOAD_URL="${PLATFORM_BASE}/csm/profile/downloadMacAgent/${SITE_ID}"
fi

echo "[*] Using download URL:"
echo "    ${DOWNLOAD_URL}"

# ---------- Workspace ----------
WORKDIR="$(/usr/bin/mktemp -d "/private/tmp/datto-agent.XXXXXX")"
ZIP="${WORKDIR}/Agent.zip"
EXTRACT_DIR="${WORKDIR}/extract"
mkdir -p "$EXTRACT_DIR"

cleanup() {
  if [[ $KEEP_ARTIFACTS -eq 0 ]]; then
    rm -rf "$WORKDIR" || true
  else
    echo "[i] Keeping artifacts in: $WORKDIR"
  fi
}
trap cleanup EXIT

# ---------- Download ----------
echo "[*] Downloading Agent.zip ..."
/usr/bin/curl -LfsS -o "$ZIP" "$DOWNLOAD_URL"

if [[ ! -s "$ZIP" ]]; then
  echo "[!] Download failed or file is empty: $ZIP" >&2
  exit 3
fi

# ---------- Extract ----------
echo "[*] Extracting Agent.zip ..."
/usr/bin/unzip -q "$ZIP" -d "$EXTRACT_DIR"

# ---------- Locate pkg ----------
DEFAULT_PKG_PATH="${EXTRACT_DIR}/AgentSetup/CAG.pkg"
PKG_PATH=""

if [[ -f "$DEFAULT_PKG_PATH" ]]; then
  PKG_PATH="$DEFAULT_PKG_PATH"
else
  # Prefer CAG.pkg if present; otherwise any .pkg
  FOUND_CAG=$(/usr/bin/find "$EXTRACT_DIR" -maxdepth 4 -type f -name "CAG.pkg" -print -quit 2>/dev/null || true)
  if [[ -n "${FOUND_CAG}" && -f "${FOUND_CAG}" ]]; then
    PKG_PATH="${FOUND_CAG}"
  else
    FOUND_ANY=$(/usr/bin/find "$EXTRACT_DIR" -maxdepth 4 -type f -name "*.pkg" -print -quit 2>/dev/null || true)
    if [[ -n "${FOUND_ANY}" && -f "${FOUND_ANY}" ]]; then
      PKG_PATH="${FOUND_ANY}"
      echo "[!] 'AgentSetup/CAG.pkg' not found; using discovered package: ${PKG_PATH}"
    fi
  fi
fi

if [[ -z "$PKG_PATH" ]]; then
  echo "[!] No .pkg found inside the extracted archive." >&2
  /bin/ls -laR "$EXTRACT_DIR" || true
  exit 4
fi

# ---------- Install ----------
echo "[*] Installing: ${PKG_PATH}"
/usr/sbin/installer -pkg "$PKG_PATH" -target /

rc=$?
if [[ $rc -ne 0 ]]; then
  echo "[!] Installer exited with code $rc" >&2
  exit $rc
fi

echo "[✓] Datto RMM agent installed successfully."

 


dflowers
Forum|alt.badge.img+1
  • Author
  • New Contributor
  • October 20, 2025

We’ve decided to install this software manually on our mac’s as we couldn’t get ths working via Jamf School script deployment due to time constraints. 

The scripts we we trying to use via Jamf School worked with no issue when being ran from terminal on the mac we were testing. It did however prompt for the installaion of Rosetta 2 on the first install. 

Rather confusing and frustrating to find that the Jamf School script engine appears to work in a different way in comparison to Jamf Pro. I mentioned this because the Sophos deployment guidance related to Jamf Pro and this didn’t work when deploying the script from Jamf School.