fa76fd4a73
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
136 lines
7.5 KiB
Markdown
136 lines
7.5 KiB
Markdown
# Mac setup design — 2026-09-15
|
|
|
|
Design for turning the stock MacBook Pro (16" 2021 M1 Pro, macOS 26.2 Tahoe)
|
|
into a quiet, Linux-feeling, Ableton-first machine, managed over SSH from
|
|
steel141. Inventory baseline: `../reference/inventory-2026-09-15.md`.
|
|
|
|
## Goals (priority order)
|
|
|
|
1. Ableton Live 12 runs clean: no sleep/App Nap/notifications mid-session,
|
|
project files never touched by cloud sync, backed up to tank.
|
|
2. Feels like Linux to a bash user: GNU userland unprefixed, `ip a` works,
|
|
kitty, bash 5, fast key repeat, no press-and-hold accents, window snapping.
|
|
3. Stock macOS noise off: Dock stripped, Spotlight web/Siri suggestions off,
|
|
Photos analysis / Game Center / Handoff / iPhone Mirroring / Screen Time off.
|
|
4. Homelab reachable: tank over SMB, ssh aliases, Gitea, Tailscale.
|
|
|
|
## Non-goals
|
|
|
|
- Disabling SIP, Gatekeeper, or FileVault. All stay on.
|
|
- Removing anything under `/System/Applications` (sealed volume). Hide from Dock only.
|
|
- Swapping Cmd<->Ctrl globally. Live's shortcuts are Cmd-native on Mac.
|
|
- yabai (needs partial SIP disable). Tiling is AeroSpace if wanted later; Rectangle now.
|
|
- Running samples/projects off the SMB share. Local disk only; SMB is a source to copy from.
|
|
- Time Machine (over SMB it's fragile and backs up the whole disk; rsync of the
|
|
folders that matter is simpler and Linux-familiar).
|
|
|
|
## Decisions taken in this design (defaults — override in DECISIONS.md)
|
|
|
|
| Fork | Choice | Why |
|
|
|---|---|---|
|
|
| Login shell | Homebrew bash 5, set via `chsh` after adding to `/etc/shells` | Seth's steel141 shell is bash; macOS ships bash 3.2. zsh stays installed. |
|
|
| Cmd/Ctrl | Untouched | Live + every Mac tutorial assume Cmd. kitty handles Ctrl+Shift+C/V itself. |
|
|
| Window snapping | Rectangle (Homebrew cask) | Zero-config snapping. Upgrade path: AeroSpace if tiling turns out to matter. |
|
|
| Backup | launchd user agent -> `rsync -a --delete` of `~/Music/Ableton` and `~/Documents` to `pve173:/tank/backups/mac/` nightly over SSH | Transparent, one file, restorable with plain rsync. Needs a Mac->pve173 SSH key. |
|
|
| Hostname | **PARAMETER — not yet chosen** | Seth names machines (`bebop`, `yoga`, `steel141`). `setup.sh` takes it as `HOSTNAME=`. |
|
|
| iCloud | Account stays (Find My, Keychain). iCloud Drive "Desktop & Documents" sync OFF | Sync mid-save corrupts/evicts DAW project files. GUI-only toggle -> manual checklist. |
|
|
| Spotlight | Indexing stays ON; Siri Suggestions + web results OFF | Finder search still useful; Live's browser has its own index. |
|
|
|
|
## Components
|
|
|
|
All live in `~/bin/mac/`. Pushed to `git.sethpc.xyz/Seth/mac`. Applied by
|
|
`ssh mac` from steel141 (seth is the console user, so `defaults write` +
|
|
`killall Dock/Finder/SystemUIServer` take effect from an SSH session).
|
|
|
|
### `Brewfile`
|
|
Single manifest, applied with `brew bundle --file=Brewfile`. Contents:
|
|
|
|
- Formulae: `bash coreutils findutils gnu-sed grep gawk gnu-tar iproute2mac
|
|
tmux htop ripgrep fd jq wget rsync git tree`
|
|
- Casks: `kitty rectangle tailscale`
|
|
- NOT in Brewfile: Ableton Live (licensed download from ableton.com, manual).
|
|
|
|
### `scripts/setup.sh`
|
|
Idempotent bash, `set -euo pipefail`, run on the Mac as seth. Sections, in order:
|
|
|
|
1. **preflight** — refuse if not arm64 macOS 26.x; require `HOSTNAME` env var;
|
|
`xcode-select --install` if CLT missing (blocks on a GUI prompt the first
|
|
time — documented).
|
|
2. **backup** — for each `defaults` domain about to be written, `defaults
|
|
export <domain> ~/.mac-setup-backup/<domain>-<epoch>.plist` (skip if domain
|
|
absent). Also `pmset -g custom` and `launchctl print gui/$UID` to the same dir.
|
|
This dir is rsync'd back to `~/bin/mac/.backup/` by the runner on steel141.
|
|
3. **brew** — install Homebrew if missing; `brew bundle`; write shellenv +
|
|
gnubin PATH block into `~/.bash_profile` (guarded by marker comments so
|
|
re-runs don't duplicate).
|
|
4. **shell** — add `/opt/homebrew/bin/bash` to `/etc/shells` if absent;
|
|
`chsh -s` if current shell differs.
|
|
5. **hostname** — `scutil --set ComputerName/LocalHostName/HostName $HOSTNAME`.
|
|
6. **defaults (Linux feel)** — key repeat `KeyRepeat=2 InitialKeyRepeat=15`;
|
|
`ApplePressAndHoldEnabled=false`; natural scrolling off; Finder: path bar,
|
|
status bar, all extensions, `~` as new-window target, list view, no
|
|
`.DS_Store` on network/USB volumes; no window animations
|
|
(`NSAutomaticWindowAnimationsEnabled=false`); hot corners cleared.
|
|
7. **defaults (debloat)** — Dock: autohide, no recents, `persistent-apps`
|
|
rewritten to Finder/kitty/Live/System Settings (Live entry only if
|
|
`/Applications/Ableton Live 12*.app` exists); Spotlight Siri suggestions
|
|
off; Game Center + Handoff (`NSUserActivityTrackingEnabled`) + Screen Time
|
|
related agents disabled with `launchctl disable gui/$UID/<label>` only after
|
|
the label is confirmed present on this OS. Remove the "SparkFun Pro Micro"
|
|
PPP network service (`networksetup -removenetworkservice`).
|
|
8. **power (DAW)** — `sudo pmset -c sleep 0 displaysleep 0 disksleep 0
|
|
powernap 0`; battery profile untouched. App Nap off for Live via
|
|
`defaults write com.ableton.live NSAppSleepDisabled -bool true`.
|
|
9. **homelab** — `~/.ssh/config` seeded with the steel141 aliases (pve*,
|
|
bebop, etc.); tank SMB mount instructions written (mount itself is GUI /
|
|
`mount_smbfs` at login — see checklist); Tailscale cask installed, login is GUI.
|
|
10. **backup agent** — install `~/Library/LaunchAgents/xyz.sethpc.mac-backup.plist`
|
|
(StartCalendarInterval 03:30) running `scripts/backup.sh` (the rsync).
|
|
11. **apply** — `killall Dock Finder SystemUIServer`.
|
|
|
|
Each section prints `[skip]` when already in desired state. No section
|
|
prompts except the CLT install and `sudo` for pmset/chsh/hostname.
|
|
|
|
### `scripts/backup.sh`
|
|
`rsync -a --delete -e ssh ~/Music/Ableton ~/Documents root@192.168.0.173:/tank/backups/mac/`.
|
|
Logs to `~/Library/Logs/mac-backup.log`. Uses claude-style key
|
|
`~/.ssh/id_ed25519` generated on the Mac and installed on pve173 (manual step,
|
|
one-time).
|
|
|
|
### `docs/manual-checklist.md`
|
|
GUI-only steps on Tahoe, in order, each with the exact Settings path:
|
|
iCloud Drive Desktop&Documents off; Photos analysis off; Screen Time off;
|
|
iPhone Mirroring off; Focus mode "DAW" (all notifications silenced, shown in
|
|
Control Center); Rectangle accessibility grant; kitty full-disk-access grant
|
|
(for `~/Music/Ableton` under TCC); Tailscale login; Live install + Suite Packs
|
|
download; audio interface buffer/sample rate in Live once one is attached.
|
|
|
|
## Verification
|
|
|
|
- `setup.sh` run twice in a row: second run is all `[skip]` lines, exit 0.
|
|
- `ip a`, `ls --color`, `sed --version` (GNU), `echo $BASH_VERSION` -> 5.x,
|
|
`hostname` -> chosen name — all over `ssh mac`.
|
|
- `pmset -g custom` shows AC `sleep 0 powernap 0`, battery unchanged.
|
|
- `defaults read com.apple.dock persistent-apps` shows only the 4 entries.
|
|
- `backup.sh` dry-run (`-n`) lists files; real run creates
|
|
`/tank/backups/mac/Ableton` on pve173.
|
|
- Live: open a project, leave it 15 min on AC, confirm no sleep and no
|
|
notifications appear (Focus on).
|
|
|
|
## Rollback
|
|
|
|
Every `defaults` domain has a pre-write plist in `.backup/`; restore with
|
|
`defaults import <domain> <file>` + `killall Dock Finder`. `pmset -g custom`
|
|
snapshot restores with the same flags. `chsh -s /bin/zsh` reverts shell.
|
|
`brew bundle cleanup` / `brew uninstall` for packages. Nothing in this design
|
|
is irreversible.
|
|
|
|
## Order of operations
|
|
|
|
1. Seth picks hostname -> `DECISIONS.md`.
|
|
2. Write `Brewfile`, `setup.sh`, `backup.sh`, `manual-checklist.md`.
|
|
3. Run `setup.sh` over SSH (CLT prompt needs Seth at the lid once).
|
|
4. Seth walks `manual-checklist.md`.
|
|
5. Install Live, attach interface, verify.
|
|
6. Handoff.
|