Setup lingkungan kerja macOS untuk tim rekayasa perangkat lunak sering kali terkendala proses manual: menyalakan setelan sistem satu per satu lewat System Settings GUI, menyetujui prompt dialog izin, dan menyinkronkan berkas konfigurasi lokal. Mengadopsi teknik otomasi seperti yang diterapkan pada repositori SkyBlue997/enableMacosAI, konfigurasi sistem macOS dapat diotomasi secara penuh melalui skrip shell yang idempoten tanpa intervensi GUI.

Arsitektur Konfigurasi macOS: defaults vs plutil

macOS menyimpan sebagian besar preferensi pengguna dan sistem dalam berkas Property List (.plist), baik dalam format XML maupun biner. Terdapat dua utilitas CLI utama untuk memanipulasi berkas ini secara terprogram:

  • defaults: Berkomunikasi langsung dengan daemon preferensi sistem (cfprefsd). Setiap perubahan yang ditulis melalui utilitas ini otomatis di-cache dan disinkronkan ke memori subsistem macOS tanpa memerlukan reload manual berkas biner.
  • plutil: Memanipulasi struktur DOM berkas .plist secara langsung di disk (in-place). Berguna untuk array atau dictionary bersarang yang tidak dapat ditangani oleh perintah datar defaults write.

Kesalahan umum adalah memodifikasi berkas preferensi mentah di ~/Library/Preferences/ menggunakan sed atau penyunting teks biasa. Hal ini menyebabkan inkonsistensi status karena daemon cfprefsd memegang cache di memori dan akan menimpa perubahan tersebut kembali ke disk saat proses aplikasi ditutup.

Menulis Skrip Shell Idempoten untuk Patching OS

Idempotensi memastikan skrip dapat dieksekusi berulang kali tanpa mengubah state akhir di luar target yang diinginkan. Contoh berikut mengimplementasikan pengecekan nilai sebelum penulisan dilakukan dan merestart daemon terkait hanya bila terjadi mutasi data.

#!/usr/bin/env bash
set -euo pipefail

apply_default() {
    local domain="$1"
    local key="$2"
    local type="$3"
    local target_value="$4"
    local current_value

    current_value=$(defaults read "$domain" "$key" 2>/dev/null || echo "__NOT_SET__")

    if [ "$current_value" != "$target_value" ]; then
        echo "Patching: ${domain} -> ${key}=${target_value}"
        defaults write "$domain" "$key" "-$type" "$target_value"
        return 0
    fi
    return 1
}

CHANGED=0

# Nonaktifkan auto-capitalization, smart dashes, dan smart quotes
apply_default "NSGlobalDomain" "NSAutomaticCapitalizationEnabled" "bool" "false" && CHANGED=1 || true
apply_default "NSGlobalDomain" "NSAutomaticDashSubstitutionEnabled" "bool" "false" && CHANGED=1 || true
apply_default "NSGlobalDomain" "NSAutomaticQuoteSubstitutionEnabled" "bool" "false" && CHANGED=1 || true

# Finder: Tampilkan ekstensi berkas default dan path bar
apply_default "com.apple.finder" "AppleShowAllExtensions" "bool" "true" && CHANGED=1 || true
apply_default "com.apple.finder" "ShowPathbar" "bool" "true" && CHANGED=1 || true

# Restart subsistem hanya jika terdapat modifikasi nilai
if [ "$CHANGED" -eq 1 ]; then
    echo "Menerapkan perubahan ke runtime UI..."
    killall Finder cfprefsd 2>/dev/null || true
fi

Manipulasi Struktur Bersarang Menggunakan plutil

Untuk memodifikasi array struktural, seperti daftar persistent apps pada Dock tanpa merusak indeks lainnya, gunakan plutil -replace atau plutil -insert.

DOCK_PLIST="$HOME/Library/Preferences/com.apple.dock.plist"

# Verifikasi integritas format plist sebelum dieksekusi
if plutil -lint "$DOCK_PLIST" >/dev/null 2>&1; then
    # Set autohide delay ke 0 menggunakan tipe float
    defaults write com.apple.dock autohide-delay -float 0
    # Menghapus animasi popup Dock
    defaults write com.apple.dock autohide-time-modifier -float 0.15
    killall Dock
fi

Menangani SIP (System Integrity Protection) dan Flag NVRAM

System Integrity Protection (SIP) membatasi modifikasi terhadap direktori /System, /usr (kecuali /usr/local), /bin, dan /sbin, bahkan oleh user root. Skrip provisioning tidak boleh berasumsi bahwa SIP dapat dinonaktifkan secara terprogram dari mode normal.

Peringatan Keamanan: SIP dan flag NVRAM tertentu hanya dapat dimodifikasi dari Recovery OS (csrutil disable). Upaya penulisan NVRAM seperti argumen boot kernel memerlukan hak akses sudo nvram dan akan ditolak oleh kernel jika SIP NVRAM protections aktif.

Dalam skrip otomasi enterprise atau provisioning workstation, pendekatan terbaik adalah mendeteksi status proteksi dan memberikan instruksi terminasi yang jelas jika environment tidak memenuhi syarat:

check_sip_status() {
    if csrutil status | grep -q "enabled"; then
        echo "[INFO] SIP aktif. Batasan proteksi berkas sistem berlaku."
    else
        echo "[WARN] SIP nonaktif. Flag kernel tingkat rendah dapat diakses."
    fi
}

set_nvram_variable() {
    local key="$1"
    local val="$2"
    
    if ! nvram "$key" >/dev/null 2>&1; then
        echo "Menulis NVRAM: $key"
        sudo nvram "$key=$val"
    fi
}

Otomasi Perizinan TCC (Transparency, Consent, and Control)

Subsistem TCC mengontrol akses aplikasi terhadap subsistem sensitif (Full Disk Access, Accessibility, Screen Recording). Basis data TCC disimpan di:

  • User-level: ~/Library/Application Support/com.apple.TCC/TCC.db
  • System-level: /Library/Application Support/com.apple.TCC/TCC.db

TCC.db dilindungi langsung oleh SIP. Upaya manipulasi berkas SQLite ini secara langsung menggunakan skrip (misal: sqlite3 TCC.db "INSERT...") akan gagal dengan pesan eror operation not permitted, kecuali proses shell yang mengeksekusi skrip tersebut telah diberi Full Disk Access secara eksplisit oleh admin via UI.

Strategi patching TCC tanpa intervensi GUI bergantung pada dua pendekatan arsitektur:

  1. Mobile Device Management (MDM) Configuration Profiles: Standar industri yang valid. MDM mengirim payload PrivacyPreferencesPolicyControl (PPPC) menggunakan sertifikat terpercaya. Ini memberikan akses TCC ke binary spesifik tanpa batasan interaktif.
  2. Bootstrap Privilege Escalation: Jika diterapkan pada mesin dev mandiri tanpa MDM, berikan Full Disk Access sekali saja kepada Terminal atau iTerm2. Selanjutnya, binary sub-shell dapat memodifikasi TCC lokal menggunakan tccutil atau kueri SQLite langsung.
# Reset izin TCC jika terjadi korupsi profil (hanya berlaku per service domain)
tccutil reset Accessibility com.googlecode.iterm2

# Verifikasi status readable TCC user
USER_TCC="$HOME/Library/Application Support/com.apple.TCC/TCC.db"
if [ -r "$USER_TCC" ]; then
    echo "Shell memiliki izin baca terhadap TCC database."
else
    echo "Shell dibatasi oleh sandbox TCC. Profil MDM/izin FDA manual dibutuhkan."
fi

Pipeline Idempotensi: Orkes Simultan

Pola akhir dari otomasi OS provisioning adalah mengeksekusi pipeline pengecekan delta. Jangan pernah menjalankan skrip mutasi secara buta di setiap login dev. Struktur pipeline standar:

  • Fase Inspect: Kueri key sistem via defaults read atau hash berkas konfigurasi target.
  • Fase Diff: Bandingkan nilai aktual dengan state yang didefinisikan pada deklarasi skrip tim.
  • Fase Apply: Tulis mutasi hanya jika terjadi perbedaan, kemudian catat riwayat log perubahan.
  • Fase Reload: Kirim sinyal restart hanya ke proses spesifik yang terdampak (misal: killall SystemUIServer).

Dengan menerapkan pola ini, workstation tim developer dapat dipulihkan atau diselaraskan ke baseline standar perusahaan dalam hitungan detik secara deterministik.