nix-darwin
4 min read

Nix modules for macOS, bringing the declarative system approach of NixOS to macOS. Manages system-wide packages, services, system defaults, Homebrew, fonts, and user environments through a unified Nix configuration.

Prerequisites

Requires Nix or Lix.

To use Lix instead of upstream Nix:

nix
nix.package = pkgs.lix;


nix
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nix-darwin = {
url = "github:nix-darwin/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs = { self, nixpkgs, nix-darwin, home-manager, ... }: {
darwinConfigurations."my-mac" = nix-darwin.lib.darwinSystem {
system = "aarch64-darwin"; # or "x86_64-darwin" for Intel
modules = [
./configuration.nix
home-manager.darwinModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.alice = import ./home.nix;
}
];
};
};
}

Bootstrap

sh
sudo mkdir -p /etc/nix-darwin
sudo chown $(id -nu):$(id -ng) /etc/nix-darwin
cd /etc/nix-darwin
nix flake init -t nix-darwin/master
sed -i '' "s/simple/$(scutil --get LocalHostName)/" flake.nix
sudo nix run nix-darwin/master#darwin-rebuild -- switch

Commands

sh
darwin-rebuild switch # build and activate new configuration
darwin-rebuild build # build without activating
darwin-rebuild check # check configuration for errors
darwin-rebuild news # show recent nix-darwin changelog
darwin-help # open HTML documentation locally
man 5 configuration.nix # option reference man page
sudo darwin-uninstaller # remove nix-darwin

Configuration Reference

Packages

nix
environment.systemPackages = with pkgs; [
git curl wget jq ripgrep fd
neovim tmux
];

Nix Settings

nix
nix.settings = {
experimental-features = [ "nix-command" "flakes" ];
substituters = [
"https://cache.nixos.org"
"https://nix-community.cachix.org"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dde0558bUxda7lCRpFGPE+ygQDH3oyBZQ="
];
trusted-users = [ "@admin" ];
};
nix.optimise.automatic = true;
nix.gc = {
automatic = true;
interval.Day = 7;
options = "--delete-older-than 30d";
};

Homebrew Integration

Requires Homebrew to be installed separately. nix-darwin manages the installed set declaratively.

nix
homebrew = {
enable = true;
onActivation = {
autoUpdate = true;
cleanup = "zap"; # remove unlisted formulae/casks
};
brews = [ "ffmpeg" "imagemagick" ];
casks = [
"firefox" "iterm2" "raycast"
"visual-studio-code"
];
masApps = {
"Xcode" = 497799835;
};
};

System Defaults

nix
system.defaults = {
NSGlobalDomain = {
AppleInterfaceStyle = "Dark";
AppleShowAllExtensions = true;
NSAutomaticSpellingCorrectionEnabled = false;
NSAutomaticQuoteSubstitutionEnabled = false;
KeyRepeat = 2;
InitialKeyRepeat = 15;
"com.apple.swipescrolldirection" = false; # natural scroll off
};

dock = {
autohide = true;
autohide-delay = 0.0;
show-recents = false;
minimize-to-application = true;
orientation = "bottom";
tilesize = 48;
static-only = true; # only show open apps
persistent-apps = [];
};

finder = {
AppleShowAllFiles = true;
ShowPathbar = true;
ShowStatusBar = true;
FXPreferredViewStyle = "clmv"; # column view
FXRemoveOldTrashItems = true;
_FXShowPosixPathInTitle = true;
NewWindowTarget = "Home";
};

trackpad = {
Clicking = true; # tap to click
TrackpadThreeFingerDrag = true;
};

screencapture.location = "~/Desktop";
screensaver.askForPasswordDelay = 0;

loginwindow = {
GuestEnabled = false;
SHOWFULLNAME = true;
};
};

Fonts

nix
fonts.packages = with pkgs; [
nerd-fonts.jetbrains-mono
nerd-fonts.fira-code
inter
];

Users

nix
users.users.alice = {
name = "alice";
home = "/Users/alice";
shell = pkgs.zsh;
};

Shell

nix
programs.zsh.enable = true; # required for zsh as default shell
programs.fish.enable = true;

environment.shells = [ pkgs.zsh pkgs.fish ];
environment.loginShell = pkgs.zsh;

Services

nix
services.nix-daemon.enable = true; # required for multi-user nix

# Yabai window manager
services.yabai = {
enable = true;
config = {
layout = "bsp";
window_gap = 8;
};
};

# skhd hotkey daemon
services.skhd = {
enable = true;
skhdConfig = ''
alt - return : open -na kitty
'';
};

launchd Agents / Daemons

nix
# User agent (runs as logged-in user)
launchd.user.agents.my-sync = {
serviceConfig = {
ProgramArguments = [ "${pkgs.rsync}/bin/rsync" "-avz" "/src/" "/dst/" ];
StartInterval = 3600;
RunAtLoad = true;
StandardOutPath = "/tmp/my-sync.log";
StandardErrorPath = "/tmp/my-sync.err";
};
};

# System daemon (runs as root)
launchd.daemons.my-daemon = {
serviceConfig = {
ProgramArguments = [ "${pkgs.myapp}/bin/myapp" "--daemon" ];
KeepAlive = true;
RunAtLoad = true;
};
};

Activation Scripts

Run arbitrary shell commands during darwin-rebuild switch:

nix
system.activationScripts.extraActivation.text = ''
# Accept Xcode license silently
sudo xcodebuild -license accept 2>/dev/null || true
# Install Rosetta on Apple Silicon
softwareupdate --install-rosetta --agree-to-license 2>/dev/null || true
'';

# Run after packages are linked
system.activationScripts.postActivation.text = ''
defaults write com.apple.finder ShowHardDrivesOnDesktop -bool true
'';

Environment Variables

nix
environment.variables = {
EDITOR = "nvim";
LANG = "en_US.UTF-8";
};

Channels (Alternative, Non-Flake)

sh
sudo nix-channel --add https://github.com/nix-darwin/nix-darwin/archive/master.tar.gz darwin
sudo nix-channel --update
nix-build '<darwin>' -A darwin-rebuild
sudo ./result/bin/darwin-rebuild switch -I darwin-config=/etc/nix-darwin/configuration.nix

Documentation

• Local: darwin-help
• Man: man 5 configuration.nix

Uninstalling

sh
sudo darwin-uninstaller
# or
sudo nix run nix-darwin#darwin-uninstaller