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;
Flake Setup (Recommended)
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