Ansible on macOS 14 Sonoma Automation Complete Guide
By Luca Berton · Published 2024-01-01 · Category: installation
Automate macOS 14 (Sonoma) developer workstations and CI agents with Ansible: Homebrew, mas, defaults, launchd, dotfiles, FileVault, and Xcode tooling.
macOS 14 (Sonoma) released October 2023 and remains widely deployed across developer laptops, CI build agents, and design workstations in 2026. Ansible automates the parts of macOS that MDM cannot easily reach: developer tooling, Homebrew packages, dotfiles, environment variables, launchd jobs, and per-project SDKs. This is the master Ansible guide for macOS 14 Sonoma.
macOS 14 Sonoma release facts
| Item | Value | |---|---| | Code name | Sonoma | | GA | 2023-09-26 | | Last security update support | ~2026 | | Default shell | zsh | | System Python | none (install via Homebrew or Xcode CLT) | | Architectures | Apple silicon (arm64), Intel (x86_64) |
See also: Ansible on macOS 15 Sequoia Automation Complete Guide
Ansible-core compatibility
Run the control node on Linux or macOS with ansible-core 2.18+. Managed macOS nodes need:
xcode-select --install # Command Line Tools
sudo softwareupdate --install-rosetta --agree-to-license # Intel-only deps on M-series
Install Python via Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install python@3.13
Inventory
[macos14]
mac-build-01.lab.example.com
mac-build-02.lab.example.com
[macos14:vars]
ansible_user=ansible
ansible_python_interpreter=/opt/homebrew/bin/python3 ; M-series
; ansible_python_interpreter=/usr/local/bin/python3 ; Intel
ansible_become_method=sudo
See also: Ansible on macOS 26 Tahoe Automation Complete Guide
Baseline playbook
- name: macOS 14 Sonoma baseline
hosts: macos14
tasks:
- name: Set hostname
become: true
ansible.builtin.command: scutil --set ComputerName "{{ inventory_hostname_short }}"
changed_when: false
- name: Install Homebrew packages
community.general.homebrew:
name:
- git
- jq
- htop
- wget
- python@3.13
- node@20
- go
- tmux
- mas
state: present
- name: Install macOS apps from App Store
community.general.mas:
id: "{{ item.id }}"
state: present
loop:
- { id: 1333542190 } # 1Password 7
- { id: 497799835 } # Xcode
- name: Install cask apps
community.general.homebrew_cask:
name:
- visual-studio-code
- iterm2
- docker
- rectangle
- google-chrome
state: present
Defaults (preferences) management
- name: Apply macOS user defaults
hosts: macos14
tasks:
- name: Show hidden files in Finder
community.general.osx_defaults:
domain: com.apple.finder
key: AppleShowAllFiles
type: bool
value: true
state: present
- name: Auto-hide dock
community.general.osx_defaults:
domain: com.apple.dock
key: autohide
type: bool
value: true
- name: Restart Finder & Dock
ansible.builtin.shell: killall Finder; killall Dock
changed_when: false
See also: Task Manager in macOS X with Ansible Automation
launchd jobs
- name: Schedule a daily build cache cleaner
hosts: macos14
tasks:
- name: Drop launchd plist
ansible.builtin.copy:
dest: "/Users/{{ ansible_user }}/Library/LaunchAgents/com.example.cleanbuild.plist"
owner: "{{ ansible_user }}"
mode: "0644"
content: |
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>com.example.cleanbuild</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>-lc</string>
<string>rm -rf "$HOME/Library/Developer/Xcode/DerivedData/*"</string>
</array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>3</integer><key>Minute</key><integer>0</integer></dict>
</dict>
</plist>
- name: Load agent
ansible.builtin.command: launchctl bootstrap gui/$(id -u {{ ansible_user }}) /Users/{{ ansible_user }}/Library/LaunchAgents/com.example.cleanbuild.plist
changed_when: false
FileVault and security
- name: Verify FileVault is on
hosts: macos14
become: true
tasks:
- name: Check FileVault
ansible.builtin.command: fdesetup status
register: fv
changed_when: false
failed_when: "'FileVault is On' not in fv.stdout"
Best practices
• Bootstrap Homebrew once, then drive everything withhomebrew, homebrew_cask, mas, and osx_defaults.
• For MDM-managed fleets, let MDM own identity, FileVault, and Gatekeeper; let Ansible own developer tooling.
• Pin Homebrew package versions for CI builders to keep build reproducibility.
• Test on both arm64 and x86_64 if you maintain a mixed fleet.
Conclusion
macOS 14 Sonoma + Ansible turns a fresh Mac into a fully provisioned developer or CI workstation in minutes. Combine homebrew, mas, osx_defaults, and launchd to capture every preference and tool in code.
Category: installation