Skip to main content

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.

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.


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."