nix-darwin with Home Manager¶
Overview¶
This walkthrough wires Home Manager into a flake as a nix-darwin module: one darwinConfigurations.<name> output evaluates macOS system modules and per-user home modules together, and a single darwin-rebuild switch activates both. That is the opposite of standalone homeConfigurations, where user profiles are built and switched with home-manager switch independently of the host.
The pattern fits a Mac where dotfiles should stay aligned with system packages and defaults, share one pkgs via home-manager.useGlobalPkgs, and ride the same generation cadence as nix-darwin. Pins below use master / nixpkgs-unstable as an illustrative unstable track (mid-2026); swap to matching 26.05 branches when you want a stable release line—see nix-darwin.
Details¶
Domains composed¶
| Domain | Role in this example |
|---|---|
| Flake (concept) | Inputs, lock, and darwinConfigurations output |
| homeConfigurations | Contrast only — not used when HM is embedded |
| nixosConfigurations | Flake cousin on NixOS (nixos-rebuild, not darwin-rebuild) |
| Experimental flakes / nix-command | Required for nix flake and --flake rebuilds |
| Module system | Shared option/import mechanics (different option tree on Darwin) |
| Standalone vs NixOS module | Integration modes; Darwin path is the macOS analogue |
| nix-darwin | Activation, platform, pins, HM module import |
| Module ecosystems: nix-darwin | Placement among module stacks |
Home Manager’s flake integration is experimental; pin the home-manager input to a release branch that matches your Nixpkgs channel and review upstream notes before bumping. See follows and overrides and lockfile.
Differences from the NixOS + HM example¶
| NixOS + HM | nix-darwin + HM (this page) | |
|---|---|---|
| Flake output | nixosConfigurations.<host> |
darwinConfigurations.<name> |
| Builder | nixpkgs.lib.nixosSystem |
nix-darwin.lib.darwinSystem |
| HM module | home-manager.nixosModules.home-manager |
home-manager.darwinModules.home-manager |
| Activate | sudo nixos-rebuild switch --flake .#<host> |
sudo darwin-rebuild switch --flake .#<name> |
| Services | systemd | launchd (Darwin activation scripts) |
| Platform | system = "x86_64-linux" (typical) |
nixpkgs.hostPlatform = "aarch64-darwin" or "x86_64-darwin" |
| Accounts | Declared in users.users |
Existing macOS login user; HM configures the home directory |
Do not copy NixOS-only options (systemd.services.*, kernel modules, etc.) into Darwin configs—look up Darwin names in the nix-darwin manual.
Apple Silicon vs Intel¶
Set nixpkgs.hostPlatform in the system module to the machine you activate on (from the nix-darwin getting-started checklist):
| Hardware | nixpkgs.hostPlatform |
|---|---|
| Apple Silicon | aarch64-darwin |
| Intel Mac | x86_64-darwin |
Wrong platform produces wrong-arch packages and build failures. Build and switch on the Mac itself unless you have a deliberate cross setup.
Repository layout¶
A minimal mono-repo keeps the host entry thin and colocates the user module next to the machine (alternatives in config repo layout):
.
├── flake.nix
├── flake.lock
└── hosts/
└── macbook/
├── default.nix # Darwin entry: imports + HM wiring
└── home.nix # Home Manager module for one macOS user
There is no NixOS-style hardware-configuration.nix on macOS; machine-specific facts (hostname, platform) live in the host module.
flake.nix (annotated)¶
{
description = "nix-darwin host with embedded Home Manager";
inputs = {
# Pin Nixpkgs (unstable track — illustrative).
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
# Match nix-darwin branch to the same track (see nix-darwin README).
nix-darwin.url = "github:nix-darwin/nix-darwin/master";
nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
# Home Manager on the same Nixpkgs revision via follows.
home-manager = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs@{ self, nix-darwin, nixpkgs, home-manager, ... }: {
# Name commonly matches `scutil --get LocalHostName` (see Activate).
darwinConfigurations."Johns-MacBook" = nix-darwin.lib.darwinSystem {
modules = [
./hosts/macbook/default.nix
];
};
};
}
Stable-track alternative (pair branches, do not mix tracks):
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-26.05-darwin";
nix-darwin.url = "github:nix-darwin/nix-darwin/nix-darwin-26.05";
home-manager.url = "github:nix-community/home-manager/release-26.05";
# … both nix-darwin and home-manager should follow "nixpkgs"
There is no homeConfigurations key for the embedded user — that output is for standalone Home Manager only. The same ./home.nix can be reused in a standalone config later; only the import and activation path change.
hosts/macbook/default.nix (system + Home Manager wiring)¶
{ inputs, ... }:
{
imports = [
inputs.home-manager.darwinModules.home-manager
];
# Required: match the Mac you rebuild on.
nixpkgs.hostPlatform = "aarch64-darwin"; # or "x86_64-darwin"
# Share the system pkgs with Home Manager modules.
home-manager.useGlobalPkgs = true;
# Install user packages into the usual user profile layout.
home-manager.useUserPackages = true;
# Pass flake inputs into home.nix (optional but common).
home-manager.extraSpecialArgs = { inherit inputs; };
# macOS user must already exist; HM configures /Users/<name>.
home-manager.users.alice = import ./home.nix;
# Illustrative system-level options — expand per role.
environment.systemPackages = with pkgs; [ git ];
services.nix-daemon.enable = true;
}
home-manager.users.<name> must match an existing macOS account. Unlike NixOS, nix-darwin does not create Unix users—you log in with the account Apple (or your org) already provisioned.
hosts/macbook/home.nix (user environment)¶
{ pkgs, ... }:
{
home.username = "alice";
home.homeDirectory = "/Users/alice";
home.stateVersion = "26.05"; # Set once; do not change casually.
home.packages = with pkgs; [
ripgrep
jq
];
programs.git = {
enable = true;
userName = "Alice Example";
userEmail = "alice@example.org";
};
# programs.* / xdg.configFile patterns: see dotfiles guidance.
}
With useGlobalPkgs = true, pkgs in this module is the system package set. Program modules and file options follow normal Home Manager semantics; see dotfiles patterns and writing HM modules.
Activate¶
Enable experimental flakes and nix-command in your Nix config before using flake rebuilds.
First install (before darwin-rebuild is on PATH): run darwin-rebuild via nix run against the nix-darwin input, with elevation—upstream install flow in the nix-darwin README. Illustrative:
Routine switch (from the flake directory, after darwin-rebuild is installed):
Replace Johns-MacBook with the key under darwinConfigurations. Upstream getting-started flow expects that name to match scutil --get LocalHostName (not always the same as the friendly ComputerName shown in System Settings).
That one command builds the Darwin closure and activates Home Manager profiles for every home-manager.users.* entry. Do not run home-manager switch for this integration path—it maintains a separate generation line and can fight module-mode activation.
Optional checks before switching:
Failure modes¶
| Symptom | Likely cause | Fix |
|---|---|---|
| Permission denied / privilege errors | darwin-rebuild switch run without sudo |
Use sudo as in upstream examples |
Attribute missing on --flake .#name |
Flake key ≠ darwinConfigurations entry or hostname mismatch |
Align with scutil --get LocalHostName; fix typo |
| Wrong-arch or build failures | nixpkgs.hostPlatform does not match hardware |
Set aarch64-darwin vs x86_64-darwin on the target Mac |
| HM option unknown / eval skew | home-manager, nix-darwin, or nixpkgs on mismatched tracks |
Pin all three to the same release line; use follows |
| Two Nixpkgs checkouts / slow builds | Inputs not following root nixpkgs |
Set inputs.nixpkgs.follows = "nixpkgs" on HM and nix-darwin |
home-manager.users has no effect |
Forgot home-manager.darwinModules.home-manager import |
Add the module to imports or modules |
| Copied NixOS options fail | systemd / Linux-only modules on Darwin | Use nix-darwin manual options; launchd, not systemd |
| Duplicate or stale user packages | Ran home-manager switch alongside module mode |
Use only darwin-rebuild for this setup |
| Collision on activation | Unmanaged file in ~ blocks symlinks |
Migrate into config or use backup/force sparingly — dotfiles patterns |
For user configs on a different cadence than system changes—or on a Mac without nix-darwin—use homeConfigurations and home-manager switch --flake .#<name> instead; see standalone vs NixOS module.
Examples¶
Inline user module instead of import ./home.nix:
home-manager.users.alice = { pkgs, ... }: {
home.stateVersion = "26.05";
programs.git.enable = true;
};
Shared user module across hosts (person follows the laptop, not the hardware):
Passing flake inputs into home.nix when modules need custom flakes or sources:
# home.nix — inputs available because default.nix set home-manager.extraSpecialArgs
{ inputs, pkgs, ... }:
{
# …
}
Template from Home Manager upstream (same wiring, different input names):
References¶
- nix-darwin/nix-darwin — source, README, install/uninstall, branch pairing
- nix-darwin site — project landing page
- nix-darwin reference manual — options reference (
nixpkgs.hostPlatform,homebrew.*, …) - Home Manager — nix-darwin flake module —
darwinModules.home-managerintegration (experimental) - Home Manager manual — Nix Flakes — standalone, NixOS, and nix-darwin flake setups
See also¶
- nix-darwin — activation, pins, platform, HM module overview
- Standalone vs NixOS module — when to embed vs use
homeConfigurations - homeConfigurations — standalone flake output and
home-manager switch - NixOS with Home Manager — Linux system + user in one
nixos-rebuild - nixosConfigurations —
nixosSystemwiring (flake cousin) - Config repo layout —
hosts/,modules/,users/conventions - Module ecosystems: nix-darwin — ecosystem placement
- Module system — how imported modules merge
- Dotfiles patterns —
programs.*, collisions, secrets - Writing HM modules — composing user modules
- Flake (concept) — inputs, outputs, reproducibility
- Generation (concept) — what
switchregisters - Flakes (experimental feature) — enabling flake commands
- nh / nixos-rebuild adjacent tools —
nh darwin switchas an optional frontend