Last active
March 23, 2026 13:57
-
-
Save Luke-Rogerson/1cc397ddee8daed8d8eee4035c63aca6 to your computer and use it in GitHub Desktop.
remote-management
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # Usage: | |
| # sudo bash setup-mac-remote.sh | |
| # | |
| # Optional: | |
| # TAILSCALE_AUTH_KEY=tskey-... sudo bash setup-mac-remote.sh | |
| # TAILSCALE_HOSTNAME=my-mac sudo bash setup-mac-remote.sh | |
| log() { | |
| printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | |
| } | |
| require_root() { | |
| if [[ "${EUID}" -ne 0 ]]; then | |
| echo "Run this script with sudo." | |
| exit 1 | |
| fi | |
| } | |
| get_macos_version_major_minor() { | |
| sw_vers -productVersion | awk -F. '{print $1 "." $2}' | |
| } | |
| version_ge() { | |
| # usage: version_ge "12.1" "12.0" | |
| [[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" == "$1" ]] | |
| } | |
| install_tailscale() { | |
| local pkg_url="https://pkgs.tailscale.com/stable/Tailscale-latest-macos.pkg" | |
| local pkg_file="/tmp/Tailscale-latest-macos.pkg" | |
| if [[ -d "/Applications/Tailscale.app" ]]; then | |
| log "Tailscale.app already present in /Applications; skipping install." | |
| return | |
| fi | |
| log "Downloading Tailscale standalone installer..." | |
| curl -fL --retry 3 --retry-delay 2 -o "${pkg_file}" "${pkg_url}" | |
| log "Installing Tailscale..." | |
| installer -pkg "${pkg_file}" -target / | |
| rm -f "${pkg_file}" | |
| log "Tailscale installed." | |
| } | |
| start_tailscale_app() { | |
| if [[ -d "/Applications/Tailscale.app" ]]; then | |
| log "Launching Tailscale.app..." | |
| open -a "/Applications/Tailscale.app" || true | |
| sleep 5 | |
| fi | |
| } | |
| tailscale_up_if_key_present() { | |
| if [[ -z "${TAILSCALE_AUTH_KEY:-}" ]]; then | |
| log "TAILSCALE_AUTH_KEY not set; skipping unattended Tailscale login." | |
| return | |
| fi | |
| local cli="" | |
| local hostname_arg=() | |
| if [[ -x "/Applications/Tailscale.app/Contents/MacOS/Tailscale" ]]; then | |
| cli="/Applications/Tailscale.app/Contents/MacOS/Tailscale" | |
| elif command -v tailscale >/dev/null 2>&1; then | |
| cli="$(command -v tailscale)" | |
| fi | |
| if [[ -z "${cli}" ]]; then | |
| log "Tailscale CLI not found yet; app is installed, but login must be completed manually." | |
| return | |
| fi | |
| if [[ -n "${TAILSCALE_HOSTNAME:-}" ]]; then | |
| hostname_arg=(--hostname="${TAILSCALE_HOSTNAME}") | |
| fi | |
| log "Bringing Tailscale up with auth key..." | |
| "${cli}" up --auth-key="${TAILSCALE_AUTH_KEY}" "${hostname_arg[@]}" || { | |
| echo "tailscale up failed. You may still need to approve the network extension / VPN prompt in macOS." | |
| return 1 | |
| } | |
| log "Tailscale is up." | |
| } | |
| enable_remote_login_admin_only() { | |
| log "Enabling Remote Login (SSH)..." | |
| if ! systemsetup -setremotelogin on; then | |
| echo "Failed to enable Remote Login via systemsetup." | |
| exit 1 | |
| fi | |
| log "Creating SSH access group if needed..." | |
| dseditgroup -o create -q com.apple.access_ssh || true | |
| log "Allowing admin group for SSH..." | |
| dseditgroup -o edit -a admin -t group com.apple.access_ssh || { | |
| echo "Failed to add admin group to com.apple.access_ssh" | |
| exit 1 | |
| } | |
| log "Remote Login enabled; admin group allowed for SSH." | |
| } | |
| enable_screen_sharing_best_effort() { | |
| local ver | |
| ver="$(get_macos_version_major_minor)" | |
| log "Attempting to enable Screen Sharing / Remote Management..." | |
| # This can still activate Remote Management on some older macOS versions, | |
| # but Apple says full Screen Sharing can't be enabled by kickstart on macOS 12.1+. | |
| /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart \ | |
| -activate \ | |
| -configure \ | |
| -access -on \ | |
| -allowAccessFor -allUsers \ | |
| -privs -all \ | |
| -restart -agent -menu >/dev/null 2>&1 || true | |
| if version_ge "${ver}" "12.1"; then | |
| cat <<EOF | |
| WARNING: | |
| Apple documents that on macOS 12.1 and later, Screen Sharing cannot be fully enabled | |
| from the command line alone. You need either: | |
| 1) MDM, or | |
| 2) a one-time manual toggle in: | |
| System Settings -> General -> Sharing -> Screen Sharing / Remote Management | |
| The script attempted best-effort Remote Management activation, but for reliable | |
| interactive screen control on ${ver}, do the GUI step once. | |
| EOF | |
| else | |
| log "Best-effort Screen Sharing/Remote Management command applied." | |
| fi | |
| } | |
| show_status() { | |
| echo | |
| echo "===== Status =====" | |
| echo "Remote Login:" | |
| systemsetup -getremotelogin || true | |
| echo | |
| echo "SSH allow group membership:" | |
| dscl . -read /Groups/com.apple.access_ssh GroupMembership 2>/dev/null || \ | |
| echo "No explicit com.apple.access_ssh group membership found." | |
| echo | |
| echo "Admin group membership:" | |
| dscl . -read /Groups/admin GroupMembership 2>/dev/null || true | |
| echo | |
| echo "Tailscale app:" | |
| if [[ -d "/Applications/Tailscale.app" ]]; then | |
| echo "Installed at /Applications/Tailscale.app" | |
| else | |
| echo "Not found" | |
| fi | |
| } | |
| main() { | |
| require_root | |
| install_tailscale | |
| start_tailscale_app | |
| tailscale_up_if_key_present || true | |
| enable_remote_login_admin_only | |
| enable_screen_sharing_best_effort | |
| show_status | |
| cat <<'EOF' | |
| Done. | |
| Notes: | |
| - If Tailscale shows a macOS prompt to allow the network extension or VPN configuration, | |
| approve it in System Settings. Tailscale documents that this approval is required on macOS. :contentReference[oaicite:3]{index=3} | |
| - For Screen Sharing on macOS 12.1+, finish the one-time manual toggle in Sharing settings, | |
| or use MDM if you want this fully unattended. :contentReference[oaicite:4]{index=4} | |
| EOF | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment