Day 12 — Flake host skeleton
Day 12 — Flake host skeleton
Stage II · ~4h
Goal: Manage the lab host with a flake (nixosConfigurations) from day one of ownership—nixos-rebuild switch --flake .#<host> is the source of truth.
Syllabus expert default: do not invest weeks in non-flake /etc/nixos only to rewrite. Migrate now while the config is small.
Why this day exists
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
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 .#labTheory 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 volume: git repo in your home (or shared path), rebuild with explicit flake path. Optionally symlink strategy later.
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. Day 18–19 deepen modules; today: imports work.
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 |
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.
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.hostNameLab 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 "day12: 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:
# conceptual — only if you understand implications
# keep hardware in repo; rebuild always with --flakeDo not create circular confusion. Simplest: always cd ~/nixos-config && sudo nixos-rebuild switch --flake .#lab.
Common gotchas
| 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 |
Checkpoint
nixosConfigurations.<host>exists
hardware-configuration.niximported from flake repo
switch --flake .#hostsucceeded
- Lock committed
- README documents rebuild
- Small declarative change proven
Commit
cd ~/nixos-config
git add .
git commit -m "day12: flake host skeleton rebuild switch"Tomorrow
Day 13 — Rebuild modes & generations. switch / test / boot / build, generation listing, and a deliberate break → rollback.