Skip to content

bhdicaire/macSetup

macSetup

Lint macOS Tahoe Ansible chezmoi 1Password License: MIT

An opinionated Ansible playbook to provision a fresh macOS Tahoe installation on Apple Silicon from scratch β€” without the cruft of a migration or update.

Philosophy: complexity is the enemy of security. Clean slate, automated, reproducible.

What it does

Phase What happens
Bootstrap Xcode CLT β†’ Rosetta 2 β†’ Homebrew β†’ core tools β†’ 1Password CLI
Packages Homebrew formulae, casks (GUI apps), Mac App Store apps via mas
Fonts Homebrew cask fonts + private bundled fonts
macOS defaults Finder, Dock, UX, security, Safari, Mail, BBEdit, Office, and more
dotFiles chezmoi init + apply from bhdicaire/dotFiles with macOS extensions
Services Login items, Automator workflows, GPG agent, file-type associations

On Hal9000 (before wiping):

  1. make capture # snapshot everything
  2. make age-setup # generate age key β†’ 1Password
  3. chezmoi add --encrypt # encrypt private dotfiles
  4. git push # push encrypted dotFiles
  5. make nas-setup # fonts + prefs β†’ NAS

On Dogbert (fresh Tahoe install):

  1. scripts/bootstrap.sh # Xcode CLT, Homebrew, op
  2. eval $(op signin) # authenticate 1Password CLI
  3. make build # full playbook β”œβ”€β”€ bootstrap # tools β”œβ”€β”€ packages # brew, cask, mas β”œβ”€β”€ fonts # bundled fonts β”œβ”€β”€ nas # pull from NAS β”œβ”€β”€ macos # defaults, Dock β”œβ”€β”€ dotfiles # chezmoi public β”œβ”€β”€ private-dotfiles # age key from 1P β†’ decrypt Tier 3 └── services # login items, Karabiner, SetApp
  4. make setapp # guided SetApp install
  5. doc/manual-tasks.md # remaining manual steps


## Before you wipe your current Mac

Run the capture script on your **Sonoma machine**:

```bash
./scripts/capture.sh

This snapshots your Brew list, MAS apps, key preferences, SSH config (public keys only), GPG public keys, Karabiner config, and shell history into a timestamped archive on your Desktop.

Review doc/manual-tasks.md for the checklist of things to handle manually (licence deallocation, private keys into 1Password, etc.).

Setting up a fresh Tahoe machine

Step 1 β€” Boot and sign in

  1. Language: English
  2. Country: Canada
  3. Accessibility: not now
  4. Migration Assistant: skip β€” this is the point
  5. Sign in with your Apple ID
  6. Create your account

Step 2 β€” Bootstrap

Open Terminal and run:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/bhdicaire/macSetup/main/scripts/bootstrap.sh)"

This installs Xcode CLT, Homebrew, Ansible, chezmoi, mas, and other prerequisites. It will prompt you to authenticate the 1Password CLI.

Step 3 β€” Configure

Edit machine-specific settings:

cd ~/Developer/macSetup
$EDITOR host_vars/localhost/main.yml   # computer name, Dock layout, directories
$EDITOR group_vars/all/packages.yml    # add/remove software

Step 4 β€” Run

make build

Grab a coffee. When it finishes, log out and back in for all defaults to take effect.

Step 5 β€” Manual tasks

Follow doc/manual-tasks.md for the remaining manual steps (SetApp, licences, FileVault, etc.).

Selective runs with tags

make build TAGS=brew          # only Homebrew formulae + casks
make build TAGS=mas           # only App Store apps
make build TAGS=defaults      # only macOS system defaults
make build TAGS=dock          # only Dock layout
make build TAGS=dotfiles      # only chezmoi / dotfiles
make build TAGS=security      # only security settings
make build TAGS=fonts         # only font installation

Secrets

No secrets are stored in this repository. All sensitive values are pulled from 1Password at runtime via the op CLI.

# Inject secrets before running (handled automatically by `make build`)
op inject -i group_vars/secrets.yml.tmpl -o group_vars/secrets.yml

See group_vars/secrets.yml.example for the shape of the secrets file.

Repository structure

macSetup/
β”œβ”€β”€ macSetup.yml                    # Main playbook
β”œβ”€β”€ ansible.cfg
β”œβ”€β”€ inventory
β”œβ”€β”€ Makefile
β”œβ”€β”€ requirements.yml                # Ansible Galaxy collections
β”‚
β”œβ”€β”€ group_vars/
β”‚   └── all/
β”‚       β”œβ”€β”€ defaults.yml            # Machine-agnostic defaults
β”‚       β”œβ”€β”€ packages.yml            # All software: brew, cask, mas
β”‚       └── macos.yml               # All osx_defaults by domain
β”‚
β”œβ”€β”€ host_vars/
β”‚   └── localhost/
β”‚       └── main.yml                # THIS machine: name, Dock, dirs
β”‚
β”œβ”€β”€ roles/
β”‚   β”œβ”€β”€ bootstrap/                  # Xcode CLT, Rosetta, Homebrew
β”‚   β”œβ”€β”€ packages/                   # brew, cask, mas installs
β”‚   β”œβ”€β”€ macos/                      # defaults, Dock, Finder, security
β”‚   β”œβ”€β”€ dotfiles/                   # chezmoi init + apply
β”‚   β”œβ”€β”€ fonts/                      # private/bundled fonts
β”‚   └── services/                   # login items, Automator, GPG
β”‚
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ capture.sh                  # Run on OLD machine before wiping
β”‚   └── bootstrap.sh                # Run on NEW machine before Ansible
β”‚
└── doc/
    β”œβ”€β”€ manual-tasks.md             # What can't be automated
    └── chezmoi-macos.md            # Extending dotFiles for macOS

dotFiles integration

The chezmoi dotFiles role initialises bhdicaire/dotFiles and adds macOS-specific configuration via {{ if eq .chezmoi.os "darwin" }} template guards. See doc/chezmoi-macos.md for details on what to add to the dotFiles repo.

Related

Licence

MIT β€” see LICENSE.

About

πŸ”§ Ansible code to build my Mac from scratch

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors