Flake-defined hosts
Flake-defined hosts
Goal: Manage the lab host with a flake (nixosConfigurations) from first ownership—nixos-rebuild switch --flake .#<host> is the source of truth.
Do not invest weeks in non-flake /etc/nixos only to rewrite. Migrate now while the config is small.
Why this chapter matters
A NixOS system without a flake pin drifts like a channel laptop. Flakes give you:
- Locked nixpkgs (and later inputs)
- Named hosts in one repo
- A rebuild command you can document and automate
Ops motivation: the host becomes a git review unit. Incident response is “what changed in the flake?” not “what did someone type on the box?”
Theory 1 — nixosConfigurations output
outputs = { self, nixpkgs, ... }: {
nixosConfigurations.lab = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./hosts/lab/configuration.nix
./hosts/lab/hardware-configuration.nix
];
};
};| Piece | Role |
|---|---|
nixosSystem |
Module system entry for a host |
system |
CPU-OS triple for packages |
modules |
List of NixOS modules (files/functions) |
attr name lab |
Host id in .#lab |
Rebuild:
sudo nixos-rebuild switch --flake /path/to/repo#lab
# or from repo:
sudo nixos-rebuild switch --flake .#labEvaluation sketch
flake inputs (locked nixpkgs)
│
▼
nixosSystem { modules }
│
▼
merged config → system derivation (toplevel)
│
▼
realize + activate → new generation
Theory 2 — Where the flake lives
| Location | Pros | Cons |
|---|---|---|
/etc/nixos/flake.nix |
Simple path | Mixed with generated hardware; git harder |
/home/you/nixos-config git repo |
Proper history | Need path on rebuild |
| Separate git + copy | Flexible | Sync discipline |
Recommended for this book: git repo in your home (or shared path), rebuild with explicit flake path. Optionally symlink strategy later.
Sudo and paths
Under sudo, . may not be where you think. Prefer:
sudo nixos-rebuild switch --flake /home/alice/nixos-config#labor always cd to the repo with a documented absolute path.
Theory 3 — Module list composition
modules = [
./hardware-configuration.nix
./configuration.nix
./modules/ssh.nix # later
];Each module is typically:
{ config, lib, pkgs, ... }: {
# options / config
}Or a plain attrset in simple files. Modules-as-consumer and custom-modules chapters deepen this; here: imports work.
imports inside configuration.nix
{
imports = [
./hardware-configuration.nix
../../modules/common.nix
];
}Either list modules in flake.nix or nest via imports—pick a convention and stick to it.
Theory 4 — Minimal flake host contents
flake.nix
{
description = "lab flake host";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
outputs = { self, nixpkgs }: {
nixosConfigurations.lab = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; # match your VM
modules = [
./hosts/lab/configuration.nix
./hosts/lab/hardware-configuration.nix
];
};
};
}hosts/lab/configuration.nix
{ config, lib, pkgs, ... }: {
networking.hostName = "lab";
nix.settings.experimental-features = [ "nix-command" "flakes" ];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
time.timeZone = "UTC";
users.users.alice = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
environment.systemPackages = with pkgs; [ vim git ];
services.openssh.enable = true;
system.stateVersion = "26.05";
}hardware-configuration.nix
Copy from the machine’s generated file—do not invent UUIDs.
Theory 5 — First rebuild flow
edit flake modules
↓
nixos-rebuild switch --flake .#lab
↓
eval modules → system derivation → realize → activate
↓
new system generation
| Outcome | Meaning |
|---|---|
| Success | New generation is current |
| Eval error | Fix Nix before build |
| Build error | Package/build failure |
| Activation error | System may be partially switched—read output carefully |
Safe preview builds
nixos-rebuild build --flake .#lab
nix build .#nixosConfigurations.lab.config.system.build.toplevelBuild without activating when you want a cheap check.
Theory 6 — specialArgs / extraSpecialArgs (preview)
nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ … ];
}Used later to pass flake inputs into modules. Not required for the minimal host.
Theory 7 — Hostname vs flake attribute
| Name | Where |
|---|---|
networking.hostName |
OS hostname |
nixosConfigurations.lab |
Flake attribute |
They may match but are not required to. Document both in README.
Theory 8 — Git discipline for hosts
| Commit | Why |
|---|---|
flake.nix + modules |
Policy history |
flake.lock |
Pin truth |
hardware-configuration.nix |
Machine facts (lab OK to commit) |
Do not commit secrets. Public SSH keys are fine; private keys are not.
Flake purity reminder
Untracked module files may not appear in evaluation—git add them.
Theory 9 — Multiple hosts (preview)
nixosConfigurations = {
lab = nixpkgs.lib.nixosSystem { … };
# laptop = nixpkgs.lib.nixosSystem { … };
};Share modules via modules/common.nix. Fleet tooling comes in Ops part; structure starts now.
Theory 10 — Leaving installer /etc/nixos behind
| Approach | Notes |
|---|---|
Ignore /etc/nixos after migration |
Flake repo is SoT |
| README warning | Prevent future-you editing wrong tree |
| Optional pointer file | Comment-only reminder |
Avoid maintaining two competing configs.
Worked examples bank
Example A — Build without switching (safe)
nixos-rebuild build --flake .#lab
# or
nix build .#nixosConfigurations.lab.config.system.build.toplevelExample B — Switch
sudo nixos-rebuild switch --flake .#labExample C — Show config value
nix eval .#nixosConfigurations.lab.config.networking.hostNameExample D — Show system path
nix eval --raw .#nixosConfigurations.lab.config.system.build.toplevelExample E — Trace eval errors
nixos-rebuild build --flake .#lab --show-traceLab 1 — Repository layout on the lab host
mkdir -p ~/nixos-config/hosts/lab
cd ~/nixos-config
git initsudo cp /etc/nixos/hardware-configuration.nix ~/nixos-config/hosts/lab/
sudo chown "$USER":"$USER" ~/nixos-config/hosts/lab/hardware-configuration.nixWrite flake.nix + hosts/lab/configuration.nix (adapt user, system, boot).
git add .
nix flake lock
git add flake.lock
git commit -m "initial nixosConfigurations.lab"Lab 2 — First flake rebuild
cd ~/nixos-config
sudo nixos-rebuild switch --flake .#labVerify:
nixos-version
hostname
nix eval .#nixosConfigurations.lab.config.networking.hostNameLab 4 — README for future you
README.md:
# nixos-config
## Rebuild
sudo nixos-rebuild switch --flake .#lab
## Host
- flake attr: lab
- hostname: lab
- nixpkgs: 26.05 (see flake.lock)Lab 5 — Optional: match /etc/nixos to flake
Some prefer keeping only a stub under /etc/nixos. Simplest reliable approach:
cd ~/nixos-config && sudo nixos-rebuild switch --flake .#labDo not create circular confusion between two live configs.
Exercises
- Eval three config values with
nix eval(hostname, stateVersion, openssh enable).
- Break a module path on purpose; fix via
--show-trace.
- Add a second module file for packages only; import it.
- Record locked nixpkgs rev in README from
nix flake metadata.
- Rebuild with absolute flake path under sudo.
- Compare installer config vs flake config—list deltas.
- Sketch multi-host layout for lab + future laptop.
- Measure toplevel path size with
nix path-info -Shafter build.
- Ensure
flake.lockis never gitignored.
- Write a one-line alias
nrsfor rebuild (shell config later via HM).
- Deliberately leave a file untracked; observe flake missing-file behavior.
- Document
systemtriple and why it must match the VM.
Common pitfalls
| Symptom | Theory |
|---|---|
| Absolute import paths broken | Prefer relative module paths in repo |
Wrong system |
Eval/build target mismatch |
| hardware config not updated after disk change | Regenerate carefully |
experimental-features missing |
Rebuild cannot use flakes cleanly |
| Dirty git / missing files | Flake file inclusion |
stateVersion folklore |
Set to install release; read release notes before changing |
| Sudo cwd confusion | Absolute flake URI |
Editing /etc/nixos by habit |
Flake is SoT |
Checkpoint
nixosConfigurations.<host>exists
hardware-configuration.niximported from flake repo
switch --flake .#hostsucceeded
- Lock committed
- README documents rebuild
- Small declarative change proven
Further depth (this book)
| Topic | Chapter |
|---|---|
| Rebuild modes / rollback | Rebuild modes and generations |
| Users/SSH | Users and access |
| Module literacy | Modules as a consumer |
| Custom modules | Writing custom modules |
| Advanced flake layout | Home and flake layout part |