nix-darwin¶
Overview¶
nix-darwin brings a NixOS-like module system to macOS: declare system packages, services, defaults, and related settings in Nix, then activate with darwin-rebuild. It is not NixOS—there is no Linux systemd, no NixOS install ISO, and activation targets macOS mechanisms (notably launchd and macOS defaults) rather than a full Linux rootfs rebuild.
The project lives under the nix-darwin org (github:nix-darwin/nix-darwin). Upstream positions it as “/etc/nixos/configuration.nix for macOS”: familiar module composition over Nixpkgs, aimed at declarative Mac system config. Maturity and coverage differ from NixOS—many options are Darwin-specific; consult the reference manual rather than assuming NixOS option names work unchanged.
For the ecosystem role among other module stacks, see module ecosystems: nix-darwin. For Nix on non-NixOS Linux, see Nix on other distros. Contrast (Linux guest / foreign OS, not Darwin modules): WSL and foreign OS.
Details¶
What it configures¶
Typical system-level concerns (exact options: see the manual):
- Packages on the system profile (
environment.systemPackagesand related environment options). - launchd agents/daemons and other Darwin service wiring.
- macOS defaults (plist /
defaults-style settings) where modules exist. - Optional Homebrew integration (
homebrew.*) that can drivebrew bundleduring activation—useful for casks and software not packaged in Nixpkgs; not required for a Nix-only setup.homebrew.enabledefaults tofalseand does not install Homebrew itself.
User dotfiles and per-user environments are usually left to Home Manager, either standalone or as a nix-darwin module (below).
Activation vs NixOS¶
| NixOS | nix-darwin | |
|---|---|---|
| Rebuild CLI | nixos-rebuild |
darwin-rebuild |
| Flake output | nixosConfigurations |
darwinConfigurations |
| Builder | nixosSystem |
darwinSystem |
| Init / services | systemd | launchd (and Darwin activation scripts) |
| Scope | Full OS (kernel, modules, …) | macOS host config layered on Apple’s OS |
Same module style (options, mkIf, imports); different option set and activation backend. Flake-shaped cousins: nixosConfigurations workflows.
Apple Silicon vs Intel¶
Set nixpkgs.hostPlatform in configuration to the machine’s Nix platform (upstream getting-started checklist):
| Hardware | nixpkgs.hostPlatform |
|---|---|
| Apple Silicon | aarch64-darwin |
| Intel | x86_64-darwin |
The option specifies where the nix-darwin configuration will run (manual: nixpkgs.hostPlatform). Prefer it over the older nixpkgs.system string when both are available. Wrong platform produces wrong-arch packages and build failures—match the Mac you activate on.
Flakes and darwin-rebuild¶
Upstream recommends flakes for new setups. A flake exposes darwinConfigurations.<name> via nix-darwin.lib.darwinSystem. After darwin-rebuild is on PATH, apply with:
Replace hostname with the attr name in darwinConfigurations (commonly the machine’s LocalHostName from scutil --get LocalHostName). First install often uses nix run against the nix-darwin flake to invoke darwin-rebuild before it is installed locally—see the project README.
Flake pins (nix-darwin ↔ nixpkgs)¶
Release branches track Nixpkgs. Illustrative pairing as of 2026-08 (from the nix-darwin README; adjust when you upgrade):
| Track | nix-darwin input | Typical nixpkgs input |
|---|---|---|
| Unstable | github:nix-darwin/nix-darwin/master |
github:NixOS/nixpkgs/nixpkgs-unstable |
| 26.05 | github:nix-darwin/nix-darwin/nix-darwin-26.05 |
github:NixOS/nixpkgs/nixpkgs-26.05-darwin |
Pin both inputs and keep them on matching tracks. Use nix-darwin.inputs.nixpkgs.follows = "nixpkgs" so nix-darwin evaluates against your nixpkgs pin rather than a second, drifting copy. Mismatched release lines (e.g. nix-darwin-26.05 with a random unstable nixpkgs, or the reverse) are a common source of eval and module breakage.
Template init mirrors the same tracks: nix flake init -t nix-darwin/master vs nix flake init -t nix-darwin/nix-darwin-26.05.
Home Manager¶
Home Manager ships a Darwin module: include home-manager.darwinModules.home-manager in the darwinSystem modules list, then set home-manager.users.<name>. System and user configs rebuild together on darwin-rebuild switch. Compare entry modes in Standalone vs NixOS module (the Darwin path is the macOS analogue of the NixOS module integration). Full flake wiring: Home Manager — nix-darwin module.
Common companion options (same names as the NixOS HM module path):
home-manager.useGlobalPkgs— share the systempkgswith Home Manager.home-manager.useUserPackages— install user packages into the user profile.home-manager.extraSpecialArgs— pass flakeinputs(or other values) intohome.nix.
Standalone Home Manager remains valid on macOS if you want user config on a different cadence than darwin-rebuild.
Common failure modes¶
- Activation needs elevated privileges. Upstream install and switch examples use
sudo darwin-rebuild switch(andsudo nix run …#darwin-rebuild -- switchbeforedarwin-rebuildis onPATH). Privilege errors usually mean the command was run without that elevation. - Wrong flake attribute.
--flake .#namemust match a key underdarwinConfigurations. Upstream expects that name to matchscutil --get LocalHostNamewhen following the getting-started sed/rename flow; a typo or ComputerName vs LocalHostName mix-up yields “attribute missing” style failures. - Assuming systemd / NixOS options. Services and timers are launchd-backed. Do not copy
systemd.services.*or other Linux-only NixOS options into Darwin configs; look up Darwin option names in the nix-darwin manual. - Homebrew is optional. Enabling
homebrew.*is not required for a working Nix-only system. When used,homebrew.enablemanages Brewfile-driven installs during activation; Homebrew must already be installed separately (manual note onhomebrew.enable). - Input skew. See Flake pins—unfollowed or cross-track nixpkgs/nix-darwin pins cause hard-to-debug eval errors.
Docs and local help¶
- Online option reference: nix-darwin manual; locally
darwin-helporman 5 configuration.nix.
Examples¶
Minimal flake shape (hostname and modules are illustrative; pin pair as of 2026-08):
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nix-darwin.url = "github:nix-darwin/nix-darwin/master";
nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs@{ self, nix-darwin, nixpkgs }: {
darwinConfigurations."Johns-MacBook" = nix-darwin.lib.darwinSystem {
modules = [
./configuration.nix
# configuration.nix should set nixpkgs.hostPlatform
# to "aarch64-darwin" or "x86_64-darwin"
];
};
};
}
Apply from the flake directory:
With Home Manager as a Darwin module (illustrative; see HM nix-darwin flake docs for the full template):
# flake inputs also need home-manager; then inside darwinSystem:
modules = [
./configuration.nix
home-manager.darwinModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.alice = ./home.nix;
}
];
See also¶
- Standalone vs NixOS module — Home Manager entry modes (including Darwin module)
- Nix on other distros — Nix without NixOS on Linux
- WSL and foreign OS — foreign Linux / NixOS-WSL contrast (not Darwin)
- Module ecosystems: nix-darwin — placement among module stacks
- nixosConfigurations workflows — flake cousin on NixOS
- NixOS module system — shared module mechanics
- nix-darwin with Home Manager — worked Darwin + HM flake walkthrough
References¶
- nix-darwin/nix-darwin — source, README, install/uninstall
- nix-darwin site — project landing page
- nix-darwin reference manual — options reference (
nixpkgs.hostPlatform,homebrew.*, …) - Home Manager: nix-darwin flake module —
darwinModules.home-managerintegration