How I set up a new Mac

November 17, 2021

As I recently blogged, I just upgraded to macOS Monterey taking it as an opportunity to start from a clean, fresh, pristine system. This means I had to set up everything again, which is not a big deal, but for the sake of remembering it and making it even faster next time, I figured I’d write about it.

This is the kind of blog post that’s mostly for my personal interest, but if you got there somehow, you might take inspiration from my settings, who knows!

But first, let’s ask the following question.

Why start fresh?

While I could totally have migrated all my data from Big Sur, I like to start from a clean slate every year or two, to get rid of all the unnecessary garbage that accumulated over the years.

Wait, what garbage? Well, let me explain.

Every time you update a software (including the OS), there’s no guarantee that the state you’ll be in after the update would be the same as if you installed the new version directly on a fresh system. Actually, the opposite is pretty much guaranteed.

Most of the time this is not a big deal. Maybe you’re stuck with the default settings of the version you originally installed instead of the ones that would otherwise come with the latest version (i.e. Git always defaults to master and you have to explicitly configure it to use main, or any small things like this).

Or maybe some commands or tasks might run slightly slower because of accumulated “bloat” related to things you don’t use anymore and forgot about (keys, passwords, certificates, trusted IP lists and whatnot from stuff you connected to once or at least stopped connecting to ages ago, the list of known Wi-Fi networks and ~/.ssh/known_hosts being a typical example).

While the above are pretty inoffensive cases, this kind of undefined state drifts might cause more sneaky bugs, and “works on that machine” kind of answers when you try to figure them out.

The same is also true when you uninstall a software; there’s no guarantee that the state you’ll be in after the removal will match the one you would have been in if you didn’t install it in the first place. And again, the opposite is pretty much guaranteed.

NixOS solves some of those issues, but in the real world, you’re likely gonna want to use many programs that are not designed and packaged to be stateless, deterministic, reproducible and purely functional, and using wrappers (or wrapping them yourself) often comes at a tremendous cost in time and convenience.

My tradeoff so far? A fresh reinstall every other year, or whenever I feel like I’ve fucked around enough with that system’s state to be worth a clean start.

New system setup

Here’s the things I do when I log in the first time on my freshly installed system.

Note: I could have installed Firefox and iTerm2 with Homebrew (which I add later) but for some reason there’s a few programs I kinda like to install on their own. Don’t ask me why.

But now I think about it, it’s probably because Homebrew became so ridiculously slow to update its repository and the installed software that I’d rather keep the ones I want to be the most up-to-date separate from Homebrew.

I’ll otherwise update Homebrew once a month or two, or when I need to install something new with it, and it forces me to upgrade everything else at the same time.

As a general rule of thumb, everything graphical I tend to install on its own, and all the CLI stuff is with Homebrew.

Now I’m ready to configure the system preferences, iTerm2 settings and my terminal-environment.

System preferences

iTerm2 preferences

Terminal environment

First, install Homebrew with whatever is the current recommended way. Install it in the default place because otherwise it won’t be able to leverage many prebuilt binaries that hardcode the default prefix in them, and it’s utterly slow to compile everything. I’d be running Gentoo if that’s what I wanted FFS. Also if you want to run Homebrew on a multi-user system, read that first.

Then, make a SSH keypair or copy an existing one in ~/.ssh. I usually run ssh-keygen either way just to let it create the directory with the proper permissions, even if I’ll override the key later.


Clone my dotfiles directory and install my Mac preset (mainly my Zsh, Vim and Git settings).

git clone
cd dotfiles
make mac

Edit my default ~/.zshrc and ~/.zshenv templates and comment or uncomment some of the stuff there that I may need, mainly enabling my asdf helper (see below).

vim ~/.zshrc ~/.zshenv

Install whatever software I pretty much always use with Homebrew.

brew install rg fzf imagemagick ffmpeg ncdu htop

Install the asdf plugins I need and whatever version is in my ~/.tool-versions. My ~/.zshrc automatically installs asdf on the first invocation so no need to do that manually.

asdf plugin add nodejs
# asdf plugin add python
# asdf plugin add ruby
# asdf plugin add elixir
# asdf plugin add erlang
asdf install

Wrapping up

That’s pretty much the gist! This is a fairly straightforward and not very time consuming checklist, and the main things that need to be automated (my dotfiles) are.

I don’t think it’s worth automating my macOS system preferences somehow as they might change in future versions anyways. Same thing for iTerm2, where I definitely don’t want to copy over my whole configuration file from an old installation, I’d rather start from the latest and greatest defaults and just tweak what I need on top of it.

Everything else is very specific to the current machine I’m setting up and I leave them to my discretion at the time of installing.

If you read until there, I hope that you learnt something, or that it inspired you to document your base setup in a similar way. Cheers!

Want to leave a comment?

Join the discussion on Twitter or send me an email! 💌
This post helped you? Buy me a coffee! 🍻