3.7 KiB

Server Hardening

Template for Part 2 of the setup script. All sudo commands.

Power Management

sudo pmset -a displaysleep 0 disksleep 0 sleep 0 \
  powernap 0 autorestart 1 networkoversleep 1

Application Firewall

FW=/usr/libexec/ApplicationFirewall/socketfilterfw
sudo $FW --setglobalstate on
sudo $FW --setallowsigned on
sudo $FW --setstealthmode on

SMB Guest Access

WARNING: Never hardcode share names. macOS uses Unicode curly quotes (' U+2019) in default names like "Mac's Public Folder", which silently breaks sharing -r with straight quotes. Always parse dynamically:

# Remove ALL share points dynamically
sharing -l | grep "^name:" | sed 's/name:[[:space:]]*//' | \
  while read -r name; do
    sudo sharing -r "$name" 2>/dev/null && \
      echo "removed: $name" || echo "skip: $name"
  done

SMBPREF=/Library/Preferences/SystemConfiguration/com.apple.smb.server
sudo defaults write $SMBPREF AllowGuestAccess -bool false

Consumer Launch Agents

Disable via launchctl disable gui/$UID/<label>. This persists across reboots without modifying plists (SIP-safe).

Services to disable:

com.apple.Siri.agent
com.apple.siriactionsd
com.apple.siriknowledged
com.apple.siriinferenced
com.apple.sirittsd
com.apple.siri-distributed-evaluation
com.apple.cloudphotod
com.apple.CloudPhotosConfiguration
com.apple.photolibraryd
com.apple.gamed
com.apple.GameController.gamecontrolleragentd
com.apple.GamePolicyAgent
com.apple.newsd
com.apple.weatherd
com.apple.tipsd
com.apple.Maps.mapssyncd
com.apple.findmymacmessenger
com.apple.icloud.findmydeviced.findmydevice-user-agent
com.apple.homed
com.apple.homeenergyd
com.apple.itunescloudd

NOT disabled (keep these): Safari agents, Zoom, Google/Chrome.

Pattern:

UID_NUM=$(id -u)
for svc in <list>; do
  launchctl disable "gui/$UID_NUM/$svc" 2>/dev/null && \
    echo "  disabled: $svc" || echo "  skip: $svc"
done

Hostname

sudo scutil --set ComputerName "<name>"
sudo scutil --set HostName "<name>"
sudo scutil --set LocalHostName "<name>"

Spotlight

sudo mdutil -a -i off

Screen Sharing (VNC)

Use ARD kickstart — launchctl load/bootstrap for screensharing.plist fails with I/O errors on modern macOS. The kickstart binary is the official way.

Important: must use -allowAccessFor -allUsers and set VNC legacy mode with an explicit password. Using -specifiedUsers can result in broken naprivs values that cause auth failures.

KICKSTART=/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart

# Clean start — deactivate first if re-running
sudo $KICKSTART -deactivate -stop

# Activate with VNC legacy password (for non-macOS clients)
sudo $KICKSTART \
  -activate -configure \
  -allowAccessFor -allUsers \
  -privs -all \
  -clientopts -setvnclegacy -vnclegacy yes \
  -setvncpw -vncpw <PASSWORD> \
  -restart -agent

Connect via vnc://<tailscale-ip> or any VNC client on port 5900. Over Tailscale, no extra firewall rules needed.

Visual Effects

Disable Liquid Glass, transparency, and animations to save GPU/CPU on a headless server:

defaults write com.apple.universalaccess reduceTransparency -bool true
defaults write com.apple.universalaccess reduceMotion -bool true
defaults write NSGlobalDomain NSAutomaticWindowAnimationsEnabled -bool false
defaults write com.apple.dock launchanim -bool false
defaults write com.apple.dock expose-animation-duration -float 0.1
defaults write NSGlobalDomain NSWindowResizeTime -float 0.001
killall Dock 2>/dev/null || true

Note: these are user-level defaults (no sudo needed).

Software Update

Keep auto-check, defer auto-install:

sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate \
  AutomaticInstall -bool false