Created
March 8, 2026 13:26
-
-
Save dzogrim/a4891263766eb917466ae0a4daf8f5ea to your computer and use it in GitHub Desktop.
macOS Server Audit Script & Migration Bundle Export (legacy)
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 | |
| # | |
| # macOS Server Audit Script | |
| # ------------------------------------------------------------ | |
| # Purpose | |
| # Generate a comprehensive audit snapshot of a macOS server. | |
| # | |
| # Designed for: | |
| # • server migration | |
| # • incident investigation | |
| # • infrastructure documentation | |
| # | |
| # Output | |
| # Creates a timestamped directory containing: | |
| # | |
| # /tmp/macos_audit_HOST_TIMESTAMP/ | |
| # report.txt | |
| # network/ | |
| # sharing/ | |
| # users/ | |
| # | |
| # Compatibility | |
| # Tested with macOS High Sierra (10.13) and later. | |
| # | |
| # Author | |
| # Infra / SRE style auditing script | |
| # | |
| set -u | |
| ######################################## | |
| # Runtime metadata | |
| ######################################## | |
| HOST=$(hostname -s) | |
| DATE=$(date +%Y%m%d_%H%M) | |
| BASE="/tmp/macos_audit_${HOST}_${DATE}" | |
| REPORT="$BASE/report.txt" | |
| mkdir -p "$BASE" | |
| # Duplicate stdout to both console and report file | |
| exec > >(tee -a "$REPORT") 2>&1 | |
| ######################################## | |
| # Utility functions | |
| ######################################## | |
| section() { | |
| echo | |
| echo "=================================================" | |
| echo "$1" | |
| echo "=================================================" | |
| } | |
| run() { | |
| local TITLE="$1" | |
| shift | |
| echo | |
| echo "----- $TITLE -----" | |
| "$@" 2>/dev/null || true | |
| } | |
| ######################################## | |
| # Header | |
| ######################################## | |
| section "MACOS SERVER AUDIT" | |
| echo "Host: $HOST" | |
| echo "Date: $(date)" | |
| echo "OS: $(sw_vers -productVersion)" | |
| echo "Kernel: $(uname -a)" | |
| ######################################## | |
| # Hardware | |
| ######################################## | |
| section "HARDWARE" | |
| run "Hardware profile" system_profiler SPHardwareDataType | |
| run "System version" sw_vers | |
| run "Uptime" uptime | |
| ######################################## | |
| # CPU / Memory | |
| ######################################## | |
| section "CPU AND MEMORY" | |
| run "CPU model" sysctl -n machdep.cpu.brand_string | |
| run "Total memory" sysctl hw.memsize | |
| run "Virtual memory statistics" vm_stat | |
| ######################################## | |
| # Network stack | |
| ######################################## | |
| section "NETWORK CONFIGURATION" | |
| run "Interfaces" ifconfig -a | |
| run "Routing table" netstat -rn | |
| run "Active connections" netstat -an | grep ESTABLISHED | |
| ######################################## | |
| # Listening services | |
| ######################################## | |
| section "NETWORK SERVICES (LISTENING PORTS)" | |
| mkdir -p "$BASE/network" | |
| lsof -i -P -n | grep LISTEN \ | |
| > "$BASE/network/listening_ports.txt" | |
| echo "Saved to: $BASE/network/listening_ports.txt" | |
| cat "$BASE/network/listening_ports.txt" | |
| ######################################## | |
| # File sharing | |
| ######################################## | |
| section "FILE SHARING" | |
| run "Sharing configuration" sharing -l | |
| run "SMB share status" smbutil statshares -a | |
| mkdir -p "$BASE/sharing" | |
| sharing -l \ | |
| > "$BASE/sharing/sharing_config.txt" | |
| echo "Sharing configuration exported to:" | |
| echo "$BASE/sharing/sharing_config.txt" | |
| ######################################## | |
| # Users and groups | |
| ######################################## | |
| section "USERS AND GROUPS" | |
| mkdir -p "$BASE/users" | |
| dscl . list /Users > "$BASE/users/users.txt" | |
| dscl . list /Groups > "$BASE/users/groups.txt" | |
| dscl . -read /Groups/admin > "$BASE/users/admin_group.txt" | |
| echo "Exported user directory data:" | |
| echo " $BASE/users/users.txt" | |
| echo " $BASE/users/groups.txt" | |
| echo " $BASE/users/admin_group.txt" | |
| ######################################## | |
| # Processes | |
| ######################################## | |
| section "PROCESS STATE" | |
| run "Running processes" ps aux | |
| run "Top CPU usage snapshot" top -l 1 -o cpu | head -40 | |
| run "Top memory usage snapshot" top -l 1 -o rsize | head -40 | |
| ######################################## | |
| # Launchd services | |
| ######################################## | |
| section "LAUNCHD SERVICES" | |
| run "LaunchDaemons" ls -la /Library/LaunchDaemons | |
| run "LaunchAgents" ls -la /Library/LaunchAgents | |
| run "User LaunchAgents" ls -la ~/Library/LaunchAgents | |
| run "Loaded launchd services" launchctl list | |
| ######################################## | |
| # Scheduled tasks | |
| ######################################## | |
| section "SCHEDULED TASKS" | |
| run "Root crontab" crontab -l | |
| run "System crontab" cat /etc/crontab | |
| run "Periodic daily jobs" ls -la /etc/periodic/daily | |
| run "Periodic weekly jobs" ls -la /etc/periodic/weekly | |
| run "Periodic monthly jobs" ls -la /etc/periodic/monthly | |
| ######################################## | |
| # Installed software | |
| ######################################## | |
| section "SOFTWARE INVENTORY" | |
| run "Applications" ls /Applications | |
| run "Installed packages" pkgutil --pkgs | |
| echo | |
| echo "Homebrew packages:" | |
| if command -v brew >/dev/null; then | |
| brew list | |
| else | |
| echo "Homebrew not installed" | |
| fi | |
| ######################################## | |
| # Storage | |
| ######################################## | |
| section "STORAGE" | |
| run "Disk layout" diskutil list | |
| run "Mounted filesystems" mount | |
| run "Filesystem usage" df -h | |
| run "fstab" cat /etc/fstab | |
| ######################################## | |
| # Time Machine | |
| ######################################## | |
| section "TIME MACHINE" | |
| run "Configured destinations" tmutil destinationinfo | |
| ######################################## | |
| # Security configuration | |
| ######################################## | |
| section "SECURITY AND LOGIN" | |
| run "Login items" defaults read loginwindow AutoLaunchedApplicationDictionary | |
| run "Admin users" dscl . -read /Groups/admin GroupMembership | |
| run "sudoers" cat /etc/sudoers | |
| run "SSH configuration" cat /etc/ssh/sshd_config | |
| ######################################## | |
| # Kernel extensions | |
| ######################################## | |
| section "KERNEL EXTENSIONS" | |
| run "Loaded kernel extensions" kextstat | |
| ######################################## | |
| # System logs | |
| ######################################## | |
| section "SYSTEM LOG (LAST 100 ENTRIES)" | |
| run "system.log tail" tail -100 /var/log/system.log | |
| ######################################## | |
| # Completion | |
| ######################################## | |
| section "AUDIT COMPLETE" | |
| echo "Audit directory:" | |
| echo " $BASE" | |
| echo | |
| echo "Main report:" | |
| echo " $REPORT" |
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 | |
| # | |
| # macOS Server Migration Bundle Export | |
| # ------------------------------------------------------------ | |
| # Purpose | |
| # Export all relevant configuration required to rebuild | |
| # a macOS server on new hardware. | |
| # | |
| # This script DOES NOT export large datasets. | |
| # Only configuration, scripts and infrastructure metadata. | |
| # | |
| # Output | |
| # | |
| # /tmp/HOST_migration_bundle_TIMESTAMP/ | |
| # system/ | |
| # network/ | |
| # shares/ | |
| # timemachine/ | |
| # cron/ | |
| # scripts/ | |
| # apps/ | |
| # macports/ | |
| # homebrew/ | |
| # storage/ | |
| # services/ | |
| # ccc/ | |
| # config/ | |
| # ssh/ | |
| # | |
| # plus compressed archive: | |
| # | |
| # HOST_migration_bundle_TIMESTAMP.tar.gz | |
| # | |
| # Use case | |
| # ------------------------------------------------------------ | |
| # Mac Mini Intel Core 2 Duo (mid-2010 legacy server) | |
| # Running Mac OS X 10.13.6 | |
| # → | |
| # Mac Mini Apple Silicon M4 (2025) | |
| # Running macOS 26.3.1 | |
| # | |
| # • Server migration | |
| # • Disaster recovery | |
| # • Infrastructure documentation | |
| # ------------------------------------------------------------ | |
| set -u | |
| ######################################## | |
| # Runtime metadata | |
| ######################################## | |
| HOST=$(hostname -s) | |
| DATE=$(date +%Y%m%d_%H%M) | |
| SERVER_USER="admin" | |
| SERVER_HOME="/Users/$SERVER_USER" | |
| OUTDIR="/tmp/${HOST}_migration_bundle_${DATE}" | |
| ARCHIVE="/tmp/${HOST}_migration_bundle_${DATE}.tar.gz" | |
| mkdir -p "$OUTDIR" | |
| echo | |
| echo "=================================================" | |
| echo " macOS Server Migration Bundle Export" | |
| echo " Host: $HOST" | |
| echo " Date: $(date)" | |
| echo " Output directory: $OUTDIR" | |
| echo "=================================================" | |
| echo | |
| ######################################## | |
| # Helper functions | |
| ######################################## | |
| section() { | |
| echo | |
| echo "-------------------------------------------------" | |
| echo "$1" | |
| echo "-------------------------------------------------" | |
| } | |
| safe_copy() { | |
| SRC="$1" | |
| DST="$2" | |
| if [ -e "$SRC" ]; then | |
| cp -R "$SRC" "$DST" | |
| fi | |
| } | |
| ######################################## | |
| # SYSTEM INFORMATION | |
| ######################################## | |
| section "SYSTEM INFORMATION" | |
| mkdir -p "$OUTDIR/system" | |
| sw_vers > "$OUTDIR/system/os_version.txt" | |
| uname -a > "$OUTDIR/system/kernel.txt" | |
| system_profiler SPHardwareDataType > "$OUTDIR/system/hardware.txt" | |
| ls /Applications > "$OUTDIR/system/applications.txt" | |
| ######################################## | |
| # NETWORK CONFIGURATION | |
| ######################################## | |
| section "NETWORK CONFIGURATION" | |
| mkdir -p "$OUTDIR/network" | |
| ifconfig -a > "$OUTDIR/network/interfaces.txt" | |
| netstat -rn > "$OUTDIR/network/routes.txt" | |
| scutil --get LocalHostName > "$OUTDIR/network/hostname.txt" 2>/dev/null | |
| scutil --get ComputerName > "$OUTDIR/network/computername.txt" 2>/dev/null | |
| ######################################## | |
| # FILE SHARING | |
| ######################################## | |
| section "FILE SHARING CONFIGURATION" | |
| mkdir -p "$OUTDIR/shares" | |
| sharing -l > "$OUTDIR/shares/sharing_config.txt" | |
| smbutil statshares -a > "$OUTDIR/shares/smb_status.txt" 2>/dev/null | |
| ######################################## | |
| # TIME MACHINE | |
| ######################################## | |
| section "TIME MACHINE CONFIGURATION" | |
| mkdir -p "$OUTDIR/timemachine" | |
| tmutil destinationinfo > "$OUTDIR/timemachine/destination.txt" 2>/dev/null | |
| defaults read /Library/Preferences/com.apple.TimeMachine \ | |
| > "$OUTDIR/timemachine/preferences.txt" 2>/dev/null | |
| ######################################## | |
| # CRON / AUTOMATION | |
| ######################################## | |
| section "CRON AND AUTOMATION" | |
| mkdir -p "$OUTDIR/cron" | |
| crontab -l > "$OUTDIR/cron/root_cron.txt" 2>/dev/null | |
| sudo crontab -l > "$OUTDIR/cron/sudo_cron.txt" 2>/dev/null | |
| cat /etc/crontab > "$OUTDIR/cron/system_cron.txt" 2>/dev/null | |
| ######################################## | |
| # CUSTOM SCRIPTS | |
| ######################################## | |
| section "CUSTOM ADMIN SCRIPTS" | |
| mkdir -p "$OUTDIR/scripts" | |
| safe_copy "/opt/Admin" "$OUTDIR/scripts/" | |
| ######################################## | |
| # APPLICATION CONFIGURATIONS | |
| ######################################## | |
| section "APPLICATION CONFIGURATION EXPORT" | |
| mkdir -p "$OUTDIR/apps" | |
| ######################################## | |
| # VUZE CONFIGURATION | |
| ######################################## | |
| VUZE="$SERVER_HOME/Library/Application Support/Vuze" | |
| if [ -d "$VUZE" ]; then | |
| mkdir -p "$OUTDIR/apps/vuze" | |
| for f in \ | |
| azureus.config \ | |
| downloads.config \ | |
| subscriptions.config \ | |
| trackers.config \ | |
| tables.config \ | |
| tag.config | |
| do | |
| safe_copy "$VUZE/$f" "$OUTDIR/apps/vuze/" | |
| done | |
| safe_copy "$VUZE/subs" "$OUTDIR/apps/vuze/" | |
| fi | |
| ######################################## | |
| # DROPBOX CONFIGURATION | |
| ######################################## | |
| DROPBOX_DIR="$SERVER_HOME/.dropbox" | |
| mkdir -p "$OUTDIR/apps/dropbox" | |
| if [ -d "$DROPBOX_DIR" ]; then | |
| echo "Dropbox configuration detected" | |
| for f in host.db info.json; do | |
| if [ -f "$DROPBOX_DIR/$f" ]; then | |
| cp "$DROPBOX_DIR/$f" "$OUTDIR/apps/dropbox/" | |
| fi | |
| done | |
| else | |
| echo "Dropbox configuration not found" | |
| fi | |
| ######################################## | |
| # MACPORTS ENVIRONMENT | |
| ######################################## | |
| section "MACPORTS ENVIRONMENT" | |
| mkdir -p "$OUTDIR/macports" | |
| if command -v port >/dev/null 2>&1; then | |
| port installed > "$OUTDIR/macports/installed_ports.txt" | |
| port echo requested \ | |
| > "$OUTDIR/macports/requested_ports.txt" 2>/dev/null | |
| safe_copy "/opt/local/etc/macports/macports.conf" "$OUTDIR/macports/" | |
| fi | |
| ######################################## | |
| # HOMEBREW ENVIRONMENT | |
| ######################################## | |
| section "HOMEBREW ENVIRONMENT" | |
| mkdir -p "$OUTDIR/homebrew" | |
| if [ -d /usr/local/Cellar ]; then | |
| ls /usr/local/Cellar \ | |
| > "$OUTDIR/homebrew/cellar_packages.txt" | |
| fi | |
| if command -v brew >/dev/null 2>&1; then | |
| BREW_PATH=$(which brew) | |
| BREW_USER=$(ls -ld "$BREW_PATH" | awk '{print $3}') | |
| echo "Detected Homebrew owner: $BREW_USER" | |
| sudo -u "$BREW_USER" brew list \ | |
| > "$OUTDIR/homebrew/brew_packages.txt" 2>/dev/null | |
| sudo -u "$BREW_USER" brew list --cask \ | |
| > "$OUTDIR/homebrew/brew_casks.txt" 2>/dev/null | |
| sudo -u "$BREW_USER" brew config \ | |
| > "$OUTDIR/homebrew/brew_config.txt" 2>/dev/null | |
| else | |
| echo "Homebrew not installed" \ | |
| > "$OUTDIR/homebrew/status.txt" | |
| fi | |
| ######################################## | |
| # STORAGE | |
| ######################################## | |
| section "STORAGE CONFIGURATION" | |
| mkdir -p "$OUTDIR/storage" | |
| diskutil list > "$OUTDIR/storage/disk_layout.txt" | |
| df -h > "$OUTDIR/storage/filesystems.txt" | |
| ######################################## | |
| # PROCESS / NETWORK SERVICES SNAPSHOT | |
| ######################################## | |
| section "PROCESS AND NETWORK SERVICES" | |
| mkdir -p "$OUTDIR/services" | |
| ps aux > "$OUTDIR/services/process_list.txt" | |
| lsof -i -P -n > "$OUTDIR/services/listening_ports.txt" | |
| ######################################## | |
| # CARBON COPY CLONER | |
| ######################################## | |
| section "CARBON COPY CLONER CONFIG" | |
| mkdir -p "$OUTDIR/ccc" | |
| CCC_SYS="/Library/Application Support/com.bombich.ccc" | |
| CCC_USR="$SERVER_HOME/Library/Application Support/com.bombich.ccc" | |
| CCC_FOUND=0 | |
| # Global preferences | |
| if [ -f "$CCC_SYS/GlobalDefaults.plist" ]; then | |
| safe_copy "$CCC_SYS/GlobalDefaults.plist" "$OUTDIR/ccc/" | |
| CCC_FOUND=1 | |
| fi | |
| # User tasks (older installs) | |
| if [ -d "$CCC_USR/Tasks" ]; then | |
| echo "CCC user tasks detected" | |
| safe_copy "$CCC_USR/Tasks" "$OUTDIR/ccc/user_tasks" | |
| CCC_FOUND=1 | |
| fi | |
| # System tasks (CCC v4/v5) | |
| if [ -d "$CCC_SYS/v4/Tasks" ]; then | |
| echo "CCC system tasks detected" | |
| safe_copy "$CCC_SYS/v4/Tasks" "$OUTDIR/ccc/system_tasks" | |
| CCC_FOUND=1 | |
| fi | |
| # Scripts possibly used by tasks | |
| if [ -d "$CCC_USR/Scripts" ]; then | |
| safe_copy "$CCC_USR/Scripts" "$OUTDIR/ccc/user_scripts" | |
| fi | |
| if [ -d "$CCC_SYS/Scripts" ]; then | |
| safe_copy "$CCC_SYS/Scripts" "$OUTDIR/ccc/system_scripts" | |
| fi | |
| # Detect CCC version | |
| CCC_APP="$SERVER_HOME/Applications/Carbon Copy Cloner.app" | |
| if [ -d "$CCC_APP" ]; then | |
| defaults read \ | |
| "$CCC_APP/Contents/Info" \ | |
| CFBundleShortVersionString \ | |
| > "$OUTDIR/ccc/version.txt" 2>/dev/null | |
| fi | |
| ######################################## | |
| # Fallback detection | |
| ######################################## | |
| if [ "$CCC_FOUND" -eq 0 ]; then | |
| echo "CCC configuration not detected via standard paths" | |
| echo "Scanning filesystem for CCC task definitions..." | |
| find "/Library/Application Support/com.bombich.ccc" \ | |
| -name "*.plist" 2>/dev/null \ | |
| > "$OUTDIR/ccc/found_plists.txt" | |
| fi | |
| ######################################## | |
| # SERVER CONFIGURATION FILES | |
| ######################################## | |
| section "SERVER CONFIGURATION FILES" | |
| mkdir -p "$OUTDIR/config" | |
| safe_copy "/Library/Preferences/SystemConfiguration/com.apple.smb.server.plist" "$OUTDIR/config/" | |
| safe_copy "/Library/Preferences/com.apple.TimeMachine.plist" "$OUTDIR/config/" | |
| safe_copy "/etc/exports" "$OUTDIR/config/" | |
| safe_copy "/etc/auto_master" "$OUTDIR/config/" | |
| ######################################## | |
| # SSH CONFIGURATION | |
| ######################################## | |
| section "SSH CONFIGURATION" | |
| mkdir -p "$OUTDIR/ssh" | |
| safe_copy "/etc/ssh/sshd_config" "$OUTDIR/ssh/" | |
| ######################################## | |
| # MANIFEST | |
| ######################################## | |
| section "CREATING MANIFEST" | |
| cat <<EOF > "$OUTDIR/MIGRATION_README.txt" | |
| Mac Server Migration Bundle | |
| =========================== | |
| Context | |
| ------- | |
| This bundle was generated on $(date) from the server: | |
| Hostname: $HOST | |
| Hardware: Mac mini Intel | |
| OS: $(sw_vers -productVersion) | |
| Purpose | |
| ------- | |
| This archive was created as part of a migration process from: | |
| Mac mini Intel (legacy server) | |
| → | |
| Mac mini Apple Silicon (Mac mini M4) | |
| The goal is to capture the configuration and operational context | |
| of the legacy server before decommissioning it. | |
| The bundle allows reconstruction of the services on the new system. | |
| Captured elements | |
| ----------------- | |
| This archive contains configuration and infrastructure metadata: | |
| • System information | |
| • Network configuration | |
| • SMB shares | |
| • Time Machine configuration | |
| • Cron jobs and scheduled tasks | |
| • Custom administrative scripts | |
| • Vuze configuration | |
| • Dropbox configuration | |
| • MacPorts environment | |
| • Homebrew environment | |
| • Disk layout and mounted filesystems | |
| • Running services snapshot | |
| • Carbon Copy Cloner configuration | |
| • SSH configuration | |
| Excluded | |
| -------- | |
| Large datasets and backups are NOT included. | |
| Typical datasets migrated separately: | |
| /Volumes/Elements 12TB | |
| /Volumes/Vault | |
| /Shared Items | |
| Target architecture after migration | |
| ----------------------------------- | |
| The new Mac mini M4 will provide the following services: | |
| • SMB file server (NAS) | |
| • Time Machine network backup | |
| • Carbon Copy Cloner disk mirror | |
| • Vuze torrent service | |
| • Dropbox synchronization | |
| • Scheduled automation scripts (cron) | |
| Notes | |
| ----- | |
| This bundle acts as a documentation snapshot of the legacy | |
| macOS server and can be used for: | |
| • migration validation | |
| • infrastructure documentation | |
| • disaster recovery reference | |
| EOF | |
| ######################################## | |
| # ARCHIVE | |
| ######################################## | |
| section "CREATING ARCHIVE" | |
| tar -czf "$ARCHIVE" -C /tmp "$(basename "$OUTDIR")" | |
| echo | |
| echo "Migration bundle created:" | |
| echo " $ARCHIVE" | |
| echo | |
| echo "Bundle directory:" | |
| echo " $OUTDIR" | |
| echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment