# Migrating Mac Configs to Nix

3 min read
Table of Contents

Declarative approach to setting up my Macbook workstation

So I have the habit of wiping my machine every 3-12 months (Pretty subjective window 🤷) and I usually don’t have a hard time getting my workstation up and running again in an hour. I use chezmoi for my dotfiles configurations, homebrew for my package manager and oh-my-zsh + starship for my terminal prompt. Ansible is a fine tool to automate this process, but it feels a bit clunky running a playbook against macOS. This is where nix-darwin saves the day (or, well, a hour of my time). Creating one Nix flake allows me to declaratively install the packages—CLI and GUI—onto my machine with a simple rebuild command. It also keeps my machine clean by ensuring I don’t have any lingering packages I forgot to delete when testing them out 😁

Installing and configuring nix

I opted to use Determinate Systems’ installer to install Nix since it also comes with a handy uninstaller, just in case I change my mind about Nix. curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install

Homebrew is also installed and managed by nix for Cask (GUI) applications and additional brews not found in nix /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

After that is installed, nix-darwin is next:

Terminal window
# Create a flake
mkdir -p ~/.config/nix-darwin
cd ~/.config/nix-darwin
nix flake init -t nix-darwin/master
sed -i '' "s/simple/$(scutil --get LocalHostName)/" flake.nix
# Install nix-darwin
nix run nix-darwin -- switch --flake ~/.config/nix-darwin

This will create flake.nix inside the ~/.config/nix-darwin directory and install the cli darwin-rebuild to build the flake within macOS

Below is my current config, which will change over time, but it’s great to have it declaratively set within one file. :-)

What I have set

  • Install System packages
  • Install Nerd Fonts
  • Install and manage homebrew packages and casks
    • Zap/Remove anything brews not configured with Nix
  • Use touch ID for sudo commands
{
description = "digitalsoba's nix-darwin system flake";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nix-darwin.url = "github:LnL7/nix-darwin";
nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
nix-homebrew.url = "github:zhaofengli-wip/nix-homebrew";
};
outputs = inputs@{ self, nix-darwin, nixpkgs, nix-homebrew }:
let
configuration = { pkgs, ... }: {
nixpkgs.config.allowUnfree = true;
environment.systemPackages =
[
pkgs.chezmoi
pkgs.fastfetch
pkgs.kind
pkgs.kubernetes-helm
pkgs.kubectx
pkgs.k3d
pkgs.k9s
pkgs.mise
pkgs.neovim
pkgs.starship
pkgs.tmux
pkgs.zsh
];
fonts.packages = with pkgs; [
nerd-fonts.fira-code
nerd-fonts.jetbrains-mono
];
homebrew = {
enable = true;
brews = [
"antidote"
"mas"
];
casks = [
"alfred"
"brave-browser"
"bruno"
"discord"
"firefox"
"ghostty"
"iina"
"jordanbaird-ice"
"orbstack"
"obsidian"
"rectangle"
"spotify"
"the-unarchiver"
"zen-browser"
"zoom"
];
onActivation.cleanup = "zap";
onActivation.autoUpdate = true;
onActivation.upgrade = true;
};
# Necessary for using flakes on this system.
nix.settings.experimental-features = "nix-command flakes";
# Set Git commit hash for darwin-version.
system.configurationRevision = self.rev or self.dirtyRev or null;
# Used for backwards compatibility, please read the changelog before changing.
# $ darwin-rebuild changelog
system.stateVersion = 5;
# The platform the configuration will be used on.
nixpkgs.hostPlatform = "aarch64-darwin";
# System wide configuration options.
security.pam.enableSudoTouchIdAuth = true;
};
in
{
# Build darwin flake using:
# $ darwin-rebuild build --flake .#mysystem
darwinConfigurations."mysystem" = nix-darwin.lib.darwinSystem {
modules = [
configuration
nix-homebrew.darwinModules.nix-homebrew
{
nix-homebrew = {
enable = true;
enableRosetta = true;
user = "digitalsoba";
autoMigrate = true;
};
}
];
};
};
}

Applying changes

Terminal window
darwin-rebuild switch --flake ~/.config/nix-darwin

And in a few minutes, my system is configured and ready to go

Whats Next?

  • Set-up nix on my Framework Laptop running project bluefin
  • Explore Nix home-manager
  • Maybe NixOS in my homelab???

More Posts

# Ansible Collections Migration

1 min read

I had this repo that hosted a role that would bootstrap servers with the good stuff: a default sudo user with a few packages and ssh configs. Mainly used in my homelab or testing things out in a VPS.…

Read