Flake-defined hosts

Updated

July 30, 2026

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.

Tip

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 .#lab

Evaluation 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#lab

or 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.toplevel

Build 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.toplevel

Example B — Switch

sudo nixos-rebuild switch --flake .#lab

Example C — Show config value

nix eval .#nixosConfigurations.lab.config.networking.hostName

Example D — Show system path

nix eval --raw .#nixosConfigurations.lab.config.system.build.toplevel

Example E — Trace eval errors

nixos-rebuild build --flake .#lab --show-trace

Lab 1 — Repository layout on the lab host

mkdir -p ~/nixos-config/hosts/lab
cd ~/nixos-config
git init
sudo cp /etc/nixos/hardware-configuration.nix ~/nixos-config/hosts/lab/
sudo chown "$USER":"$USER" ~/nixos-config/hosts/lab/hardware-configuration.nix

Write 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 .#lab

Verify:

nixos-version
hostname
nix eval .#nixosConfigurations.lab.config.networking.hostName

Lab 3 — Prove flake is authority

  1. Change a harmless package in environment.systemPackages (add htop).
  2. Rebuild switch.
  3. Confirm htop available.
  4. Commit.

Avoid editing /etc/nixos/configuration.nix as the long-term path—if installer files remain, leave a comment in README: flake repo is SoT.


Lab 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 .#lab

Do not create circular confusion between two live configs.


Exercises

  1. Eval three config values with nix eval (hostname, stateVersion, openssh enable).
  2. Break a module path on purpose; fix via --show-trace.
  3. Add a second module file for packages only; import it.
  4. Record locked nixpkgs rev in README from nix flake metadata.
  5. Rebuild with absolute flake path under sudo.
  6. Compare installer config vs flake config—list deltas.
  7. Sketch multi-host layout for lab + future laptop.
  8. Measure toplevel path size with nix path-info -Sh after build.
  9. Ensure flake.lock is never gitignored.
  10. Write a one-line alias nrs for rebuild (shell config later via HM).
  11. Deliberately leave a file untracked; observe flake missing-file behavior.
  12. Document system triple 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.nix imported from flake repo
  • switch --flake .#host succeeded
  • 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