Declarative macOS system configuration using Nix and nix-darwin
This repository contains a Nix Flake that declaratively manages:
- System packages — CLI tools installed via Nix
- Homebrew casks & Mac App Store apps — GUI applications managed through nix-homebrew
- macOS system preferences — Dock, Finder, login window, and Control Center settings
The configuration is split into focused modules for easier maintenance:
nix-darwin/
├── flake.nix # Flake inputs and module wiring
├── flake.lock # Pinned dependency versions
├── modules/
│ ├── packages.nix # Nix system packages (CLI tools)
│ ├── homebrew.nix # Homebrew brews, casks, and Mac App Store apps
│ └── system.nix # macOS system preferences and nix settings
├── LICENSE
└── README.md
| File | Purpose | When to edit |
|---|---|---|
flake.nix |
Defines flake inputs and wires modules together | Adding new flake inputs or modules |
modules/packages.nix |
Nix CLI packages (environment.systemPackages) |
Adding or removing CLI tools |
modules/homebrew.nix |
Homebrew brews, casks, and Mac App Store apps | Adding or removing GUI apps |
modules/system.nix |
macOS defaults (Dock, Finder, etc.) and nix settings | Changing system preferences |
- macOS on Apple Silicon (
aarch64-darwin) - An administrator account
- A working internet connection
softwareupdate --install-rosettaNix will try to create these files and complain is they already exist.
sudo mv /etc/bashrc /etc/bashrc.before-nix-darwin
sudo mv /etc/zshrc /etc/zshrc.before-nix-darwin
Install Nix using the official multi-user installer:
sh <(curl -L https://nixos.org/nix/install)After installation, restart your terminal and verify Nix is working:
nix-shell -p fastfetch --run fastfetchNote
nix-shell -p <package> lets you temporarily use a package without permanently installing it.
Flakes are an experimental Nix feature that must be explicitly enabled. If you haven't enabled them system-wide yet, you can pass the flag inline:
--extra-experimental-features 'nix-command flakes'This is configured permanently in this flake via:
nix.settings.experimental-features = "nix-command flakes";git clone https://github.com/stevenplatt/nix-darwin.git ~/Documents/github/nix-darwin
cd ~/Documents/github/nix-darwinIf this is a fresh machine and nix-darwin is not yet installed, bootstrap it by running:
sudo nix run nix-darwin --extra-experimental-features 'nix-command flakes' -- switch --flake .#Stevens-MacBook-AirImportant
The hostname after # must match your Mac's hostname. This flake uses Stevens-MacBook-Air. You can check yours with hostname.
Once nix-darwin is installed, apply changes with:
sudo darwin-rebuild switch --flake ~/Documents/github/nix-darwin#Stevens-MacBook-AirTip
Always use ./ or the full path to the flake directory. Using just the directory name (e.g., nix-darwin) causes Nix to look up the flake registry instead of the local directory.
nix flake update --flake ~/Documents/github/nix-darwinsudo darwin-rebuild switch --flake ~/Documents/github/nix-darwin#Stevens-MacBook-AirCLI tools installed in the system profile. Browse available packages at search.nixos.org.
| Package | Description |
|---|---|
vim |
Text editor |
awscli2 |
AWS CLI v2 |
google-cloud-sdk |
Google Cloud SDK |
kubectl |
Kubernetes CLI |
kubernetes-helm |
Helm package manager |
ansible |
Automation tool |
fastfetch |
System info display |
Managed declaratively through nix-homebrew. These are installed and kept in sync automatically.
| Cask |
|---|
affinity |
antigravity |
applite |
balenaetcher |
discord |
docker-desktop |
google-chrome |
lens |
logi-options+ |
slack |
the-unarchiver |
zoom |
zotero |
Installed via mas (Mac App Store CLI). Each entry needs the app's numeric ID.
| App | ID |
|---|---|
| Davinci Resolve | 571213070 |
| Mela | 1568924476 |
| Slack | 803453959 |
| Swift Playground | 1496833156 |
310633997 |
|
| XCode | 497799835 |
Configured under system.defaults. Reference all available options at MyNixOS.
| Setting | Value |
|---|---|
| Dock autohide | true |
| Dock orientation | left |
| Finder view style | Column view |
| Finder show path bar | true |
| Finder show hidden files | true |
| Finder default folder | Documents |
| Guest account | Disabled |
| Battery show percentage | true |
| Hot corner (top-right) | Mission Control |
| Setting | Description |
|---|---|
onActivation.cleanup = "zap" |
Remove packages installed outside of Nix |
onActivation.autoUpdate = true |
Auto-update Homebrew on activation |
onActivation.upgrade = true |
Upgrade all casks on activation |
mutableTaps = false |
Prevent imperative brew tap commands |
Add the package to the list in modules/packages.nix:
environment.systemPackages = with pkgs; [
vim
your-new-package # ← add here
];Add the cask name to homebrew.casks in modules/homebrew.nix:
homebrew.casks = [
"your-new-cask" # ← add here
];Find the app's numeric ID (visible in the App Store URL) and add it to homebrew.masApps in modules/homebrew.nix:
homebrew.masApps = {
"App Name" = 123456789; # ← add here
};Browse available options at MyNixOS — system.defaults and add them under system.defaults in modules/system.nix:
system.defaults = {
dock.autohide = true;
# Add more settings here
};Then rebuild:
sudo darwin-rebuild switch --flake ~/Documents/github/nix-darwin#Stevens-MacBook-Air