mirror of
https://github.com/awatertrevi/macos-configuration.git
synced 2026-09-22 11:44:36 +00:00
Track ~/.aws/config (profiles only, never credentials) as a copied config: setup.sh restores it, update.fish refreshes it. Document the S3 state backend setup for resoftware-iac in the README, including the config/credentials profile-header gotcha behind "failed to get shared config profile". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
201 lines
6.8 KiB
Markdown
201 lines
6.8 KiB
Markdown
# macOS Configuration
|
||
|
||
Personal macOS setup. This README is a complete, ordered runbook for setting up a
|
||
fresh machine — follow it top to bottom and you end up with a working environment.
|
||
|
||
Two kinds of files live here:
|
||
|
||
- **Symlinked** — the file in this repo *is* the live config (fish, starship, ssh,
|
||
kube, npm, NuGet). Edit either side, they're the same file.
|
||
- **Copied** — files that can't be symlinked (`/etc/hosts`, Claude/Serena settings,
|
||
the AWS config, the brewfile). Refresh them from the machine with `./update.fish`.
|
||
|
||
## Fresh machine setup — the fast way
|
||
|
||
Get this repo onto the machine (USB stick copy or a clone) and run:
|
||
|
||
```bash
|
||
/bin/bash setup.sh
|
||
```
|
||
|
||
The script is idempotent and does steps 1–9 below automatically: it copies the
|
||
repo to `~/Repositories/personal/macos-configuration` (so it works straight off
|
||
a USB stick), installs Command Line Tools and Homebrew, runs the brew bundle,
|
||
creates all symlinks, restores the copied configs, sets fish as the default
|
||
shell, and installs the .NET SDK. At the end it prints the manual steps that
|
||
remain (1Password/SSH keys, iTerm2 profile import, `gh auth login` + repo
|
||
cloning, WireGuard, app sign-ins).
|
||
|
||
The sections below document what the script does, for reference or manual runs.
|
||
|
||
## Fresh machine setup — step by step
|
||
|
||
### 1. Install Command Line Tools and clone this repo
|
||
|
||
```bash
|
||
xcode-select --install
|
||
mkdir -p ~/Repositories/personal
|
||
git clone https://github.com/awatertrevi/macos-configuration.git ~/Repositories/personal/macos-configuration
|
||
cd ~/Repositories/personal/macos-configuration
|
||
```
|
||
|
||
(First clone happens over HTTPS; once 1Password + SSH are set up below, remotes work over SSH.)
|
||
|
||
### 2. Install Homebrew
|
||
|
||
```bash
|
||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||
```
|
||
|
||
### 3. Install all packages, casks, and VS Code extensions
|
||
|
||
```bash
|
||
brew bundle --file=brewfile
|
||
```
|
||
|
||
This installs everything: CLI tools (fish, gh, node, pnpm, uv, opentofu, …),
|
||
apps (1Password, iTerm2, Docker Desktop, Fork, VS Code, …), fonts, and
|
||
VS Code extensions.
|
||
|
||
### 4. Sign in to 1Password and enable the SSH agent
|
||
|
||
Open 1Password → Settings → Developer → enable **SSH Agent**. The ssh-config
|
||
symlinked below routes all SSH auth through the 1Password agent
|
||
(`~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock`), so the
|
||
private keys never live on disk — only the `.pub` files referenced in
|
||
`ssh-config` need to exist in `~/.ssh/` (1Password can export them, or copy
|
||
them from the old machine).
|
||
|
||
### 5. Symlink configuration files
|
||
|
||
Run from the repo root:
|
||
|
||
```bash
|
||
mkdir -p ~/.config/fish ~/.kube ~/.nuget/NuGet
|
||
ln -sf $(pwd)/fish-config.fish ~/.config/fish/config.fish
|
||
ln -sf $(pwd)/starship.toml ~/.config/starship.toml
|
||
ln -sf $(pwd)/ssh-config ~/.ssh/config
|
||
ln -sf $(pwd)/kube-config ~/.kube/config
|
||
ln -sf $(pwd)/.npmrc ~/.npmrc
|
||
ln -sf $(pwd)/NuGet.Config ~/.nuget/NuGet/NuGet.Config
|
||
```
|
||
|
||
### 6. Restore the copied configs
|
||
|
||
```bash
|
||
mkdir -p ~/.claude ~/.serena ~/.aws
|
||
cp claude-settings.json ~/.claude/settings.json
|
||
cp serena_config.yml ~/.serena/serena_config.yml
|
||
cp aws-config ~/.aws/config
|
||
sudo cp hosts /etc/hosts
|
||
```
|
||
|
||
(`aws-config` only holds profile definitions — the actual AWS credentials are
|
||
set up later, in the "AWS + OpenTofu state access" step.)
|
||
|
||
### 7. Set fish as the default shell
|
||
|
||
```bash
|
||
echo /opt/homebrew/bin/fish | sudo tee -a /etc/shells
|
||
chsh -s /opt/homebrew/bin/fish
|
||
```
|
||
|
||
### 8. Configure iTerm2
|
||
|
||
iTerm2 → Settings → Profiles → Other Actions → **Import JSON Profiles** →
|
||
select `iterm-profile.json`, then set it as the default profile.
|
||
(Requires the Fira Code Nerd Font installed in step 3.)
|
||
|
||
### 9. Install the .NET 10 SDK
|
||
|
||
```bash
|
||
fish install-dotnet10.fish
|
||
```
|
||
|
||
Installs into `~/.dotnet` via the official dotnet-install script and prints the
|
||
`fish_add_path` line to persist it if needed.
|
||
|
||
### 10. Clone work repositories
|
||
|
||
```bash
|
||
gh auth login # authenticate the GitHub CLI first
|
||
fish clone-resoftware-repos.fish
|
||
```
|
||
|
||
Clones every repo in the `resoftware` GitHub org via SSH into
|
||
`~/Repositories/{customer-number}/{repo-name}`, based on each repo's
|
||
`customer-number` custom property. Safe to re-run — existing clones are skipped.
|
||
|
||
### 11. AWS + OpenTofu state access (resoftware-iac)
|
||
|
||
All OpenTofu state for `resoftware-iac` lives in the S3 bucket
|
||
`resoftware-iac-state` (eu-north-1); the backend blocks in that repo reference
|
||
the `resoftware-iac` AWS profile, so `tofu init` fails with *"failed to get
|
||
shared config profile resoftware-iac"* until that profile exists.
|
||
|
||
The `aws-config` restored in step 6 already defines both profiles in
|
||
`~/.aws/config`:
|
||
|
||
- `resoftware-iac` — the `iac` IAM user; used for the S3 state backend and plans.
|
||
- `default` — a root login session (account 693091788121); used for applies via
|
||
`aws configure export-credentials`.
|
||
|
||
What can't live in git and must be set up by hand:
|
||
|
||
```bash
|
||
aws configure --profile resoftware-iac
|
||
```
|
||
|
||
Enter the `iac` user's access key (from 1Password or the old machine's
|
||
`~/.aws/credentials`; or mint a fresh key in the AWS console — IAM is
|
||
deliberately console-managed, not IaC) and region `eu-north-1`. Beware if
|
||
editing the files manually instead: `~/.aws/config` section headers carry a
|
||
`profile ` prefix (`[profile resoftware-iac]`) but `~/.aws/credentials` headers
|
||
do **not** (`[resoftware-iac]`) — mismatching them causes exactly the
|
||
"failed to get shared config profile" error. `aws configure` writes both
|
||
correctly.
|
||
|
||
For applies, also establish the root session once:
|
||
|
||
```bash
|
||
aws login
|
||
```
|
||
|
||
Then restore each stack's gitignored `terraform.tfvars` (Infisical
|
||
machine-identity creds — copy securely from the old machine or refill from
|
||
Infisical; currently only `infra/cloudflare/terraform.tfvars`), and verify:
|
||
|
||
```bash
|
||
aws sts get-caller-identity --profile resoftware-iac
|
||
cd ~/Repositories/kl0000/resoftware-iac/infra/cloudflare && tofu init
|
||
```
|
||
|
||
### 12. WireGuard tunnel to home network (optional)
|
||
|
||
`meerkoet-proxy.conf` is a WireGuard client config for the home (Fritz!Box)
|
||
network. Import it into the WireGuard app (installable from the App Store) via
|
||
**Import Tunnel(s) from File**.
|
||
|
||
### 13. Manual leftovers
|
||
|
||
Things not automated here:
|
||
|
||
- Sign in: iCloud, Chrome/Zen, Slack, Spark, Google Drive, Docker Desktop, Todoist.
|
||
- JetBrains Toolbox → sign in and install the IDEs you use.
|
||
- Grant permissions as apps ask (Bartender, BetterTouchTool, CleanShot, Mos, Cursr).
|
||
- Alfred / BetterTouchTool: restore licenses and sync/import preferences.
|
||
|
||
## Keeping this repo up to date
|
||
|
||
The symlinked files are always current by construction. Refresh the copied ones with:
|
||
|
||
```bash
|
||
./update.fish
|
||
```
|
||
|
||
It re-dumps the brewfile (`brew bundle dump --force`) and re-copies
|
||
`~/.claude/settings.json`, `~/.serena/serena_config.yml`, `~/.aws/config`, and
|
||
`/etc/hosts` into the repo. Review `git diff` afterwards and commit.
|
||
(`~/.aws/credentials` is never tracked.)
|