NixOS with Home Manager¶
Overview¶
This walkthrough wires Home Manager into a flake as a NixOS module: one nixosConfigurations.<host> output evaluates system modules and per-user home modules together, and a single nixos-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 OS.
The pattern fits a single-machine or mono-repo setup where dotfiles should stay aligned with the system declaration, share one pkgs via home-manager.useGlobalPkgs, and ride the same generation cadence as NixOS. Pins below use release-26.05 / nixos-26.05 as illustrative stable branches (mid-2026).
Details¶
Domains composed¶
| Domain | Role in this example |
|---|---|
| Flake (concept) | Inputs, lock, and nixosConfigurations output |
| nixosConfigurations | nixpkgs.lib.nixosSystem host wiring |
| homeConfigurations | Contrast only — not used when HM is embedded |
| Experimental flakes / nix-command | Required for nix flake and --flake rebuilds |
| Users and groups | Login accounts declared under users.users |
| Standalone vs NixOS module | Integration mode and trade-offs |
| nixos-rebuild | Activation entry point for this path |
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.
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/
└── laptop/
├── default.nix # NixOS entry: imports + HM wiring
├── hardware-configuration.nix
└── home.nix # Home Manager module for one user
hardware-configuration.nix is normally generated by nixos-generate-config; treat it as machine-specific facts, not shared dotfiles.
flake.nix (annotated)¶
{
description = "NixOS host with embedded Home Manager";
inputs = {
# Pin Nixpkgs to a release branch (illustrative).
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
# Match Home Manager’s release branch to the same NixOS release.
home-manager = {
url = "github:nix-community/home-manager/release-26.05";
# Reuse the root nixpkgs checkout in the lock graph.
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { nixpkgs, home-manager, ... }@inputs: {
nixosConfigurations.laptop = nixpkgs.lib.nixosSystem {
# Pass flake inputs into every NixOS/HM module (optional but common).
specialArgs = { inherit inputs; };
modules = [
./hosts/laptop/default.nix
];
};
};
}
There is no homeConfigurations key for the embedded user — that output is for standalone Home Manager only. The same ./home.nix file can still be reused in a standalone config if you later split modes; only the import path changes.
hosts/laptop/default.nix (system + Home Manager wiring)¶
{ inputs, ... }:
{
imports = [
./hardware-configuration.nix
inputs.home-manager.nixosModules.home-manager
];
networking.hostName = "laptop";
# Account identity is NixOS’s job — Home Manager configures the home dir.
users.users.alice = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" ];
};
# Share the system pkgs with Home Manager modules (overlays / nixpkgs.* live here).
home-manager.useGlobalPkgs = true;
# Install user packages into the usual NixOS user profile layout.
home-manager.useUserPackages = true;
# Attach the user’s Home Manager module (path or inline attrset).
home-manager.users.alice = import ./home.nix;
# Minimal system services — expand per role modules as needed.
services.openssh.enable = true;
system.stateVersion = "26.05";
}
home-manager.users.<name> must match a users.users.<name> entry. Home Manager does not create Unix accounts.
hosts/laptop/home.nix (user environment)¶
{ pkgs, ... }:
{
home.username = "alice";
home.homeDirectory = "/home/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¶
On the target machine (flakes and nix-command enabled):
That one command builds the system closure and activates Home Manager profiles for every home-manager.users.* entry. Do not run home-manager switch for this integration path — it would maintain a separate generation line and can fight module-mode activation.
Optional checks before switching:
nix flake check # evaluates nixosConfigurations.*.config.system.build.toplevel
nix build .#nixosConfigurations.laptop.config.system.build.toplevel
Use test or boot instead of switch when you want non-persistent or reboot-deferred activation; see rebuild: switch, boot, test.
Failure modes¶
| Symptom | Likely cause | Fix |
|---|---|---|
| HM option unknown / version skew | home-manager input branch does not match nixpkgs |
Align release branches; run nix flake update intentionally |
| User does not exist / cannot log in | Missing or mismatched users.users.<name> |
Declare the account in NixOS; match home.username |
| Duplicate or stale packages | Ran home-manager switch alongside module mode |
Use only nixos-rebuild for this setup |
home-manager.users has no effect |
Forgot home-manager.nixosModules.home-manager import |
Add the module to imports or modules |
| Collision on activation | Unmanaged file in ~ blocks symlinks |
Migrate into config or use backup/force sparingly — dotfiles patterns |
| Two Nixpkgs checkouts / slow builds | HM input not following root nixpkgs |
Set inputs.nixpkgs.follows = "nixpkgs" on the HM input |
| Flake eval errors in modules | Modules need inputs but lack specialArgs |
Pass specialArgs = { inherit inputs; }; on nixosSystem |
For standalone user configs on non-NixOS hosts, or when dotfiles should move independently of the system, use homeConfigurations and home-manager switch --flake .#<name> instead — details in standalone vs NixOS module, not duplicated here.
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):
Keep host-specific packages in the host entry or a small wrapper import; shared shell/editor config belongs under users/ or modules/ as in config repo layout.
Passing flake inputs into home.nix when modules need custom flakes or sources:
# home.nix
{ inputs, pkgs, ... }:
{
# inputs available because flake.nix set specialArgs on nixosSystem
}
References¶
- Home Manager manual — options, activation, NixOS module install
- Home Manager — Nix Flakes — standalone, NixOS, and nix-darwin flake setups (experimental)
- NixOS manual — system configuration, users, and
nixos-rebuild
See also¶
- Standalone vs NixOS module — when to embed vs use
homeConfigurations - homeConfigurations — standalone flake output and
home-manager switch - nixosConfigurations —
nixosSystemwiring and flake checks - Config repo layout —
hosts/,modules/,users/conventions - Users and groups — account declarations required before HM
- configuration.nix — primary NixOS module shape
- Module system — how NixOS merges imported modules
- Dotfiles patterns —
programs.*, collisions, secrets - Writing HM modules — composing user modules
- Rebuild: switch, boot, test — activation modes
- nixos-rebuild (frontend) — CLI flags and flake hostname lookup
- Flake (concept) — inputs, outputs, reproducibility
- Generation (concept) — what
switchregisters - Flakes (experimental feature) — enabling flake commands