#!/usr/bin/env bash # ControlD MDM Agent — macOS Installer # Usage: sudo bash install-mac.sh set -euo pipefail CONTROLD_TOKEN="${1:?Usage: $0 }" DASHBOARD_URL="${2:?Usage: $0 }" EMPLOYEE_NAME="${3:?Usage: $0 }" CTRLD_DIR="/opt/controld" CTRLD_BIN="${CTRLD_DIR}/ctrld" CTRLD_CONFIG="${CTRLD_DIR}/ctrld.toml" PLIST_PATH="/Library/LaunchDaemons/com.controld.agent.plist" DEVICE_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')" HOSTNAME="$(hostname)" echo "[*] Installing ControlD MDM agent for ${EMPLOYEE_NAME} on ${HOSTNAME}..." # 1. Download ctrld binary echo "[*] Downloading ctrld..." mkdir -p "${CTRLD_DIR}" ARCH="$(uname -m)" if [ "${ARCH}" = "arm64" ]; then CTRLD_URL="https://github.com/Control-D-Inc/ctrld/releases/latest/download/ctrld-darwin-arm64" else CTRLD_URL="https://github.com/Control-D-Inc/ctrld/releases/latest/download/ctrld-darwin-amd64" fi curl -fsSL -o "${CTRLD_BIN}" "${CTRLD_URL}" chmod +x "${CTRLD_BIN}" # 2. Write config echo "[*] Writing ctrld.toml..." cat > "${CTRLD_CONFIG}" < "${PLIST_PATH}" < Label com.controld.agent ProgramArguments ${CTRLD_BIN} run --config ${CTRLD_CONFIG} RunAtLoad KeepAlive StandardOutPath /var/log/controld-agent.log StandardErrorPath /var/log/controld-agent.err PLIST launchctl load -w "${PLIST_PATH}" # 4. Set system DNS to 127.0.0.1 echo "[*] Setting system DNS..." SERVICES=$(networksetup -listallnetworkservices | tail -n +2) while IFS= read -r svc; do networksetup -setdnsservers "$svc" 127.0.0.1 2>/dev/null || true done <<< "$SERVICES" mkdir -p /etc/resolver echo "nameserver 127.0.0.1" > /etc/resolver/default # 5. Register with MDM backend echo "[*] Registering device with MDM backend..." curl -fsSL -X POST "${DASHBOARD_URL}/api/register" \ -H "Content-Type: application/json" \ -d "{ \"device_id\": \"${DEVICE_ID}\", \"hostname\": \"${HOSTNAME}\", \"employee\": \"${EMPLOYEE_NAME}\", \"os\": \"macos\", \"resolver_id\": \"${CONTROLD_TOKEN}\" }" || echo "[!] Warning: Could not reach MDM backend. Device will register on next heartbeat." # 6. Install heartbeat cron (every 5 min) echo "[*] Setting up heartbeat..." HEARTBEAT_SCRIPT="${CTRLD_DIR}/heartbeat.sh" cat > "${HEARTBEAT_SCRIPT}" </dev/null || echo "unknown") curl -fsSL -X POST "${DASHBOARD_URL}/api/heartbeat" \ -H "Content-Type: application/json" \ -d "{\"device_id\": \"${DEVICE_ID}\", \"ip\": \"\${IP}\"}" >/dev/null 2>&1 BEAT chmod +x "${HEARTBEAT_SCRIPT}" (crontab -l 2>/dev/null | grep -v "${HEARTBEAT_SCRIPT}"; echo "*/5 * * * * ${HEARTBEAT_SCRIPT}") | crontab - echo "[+] Installation complete!" echo " Device ID: ${DEVICE_ID}" echo " Config: ${CTRLD_CONFIG}" echo " DNS: 127.0.0.1 -> ControlD (DoH)"