Day 22 — Stage II gate
Day 22 — Stage II gate
Stage II · ~4h (review + proof)
Goal: Prove a minimal production-shaped flake-managed NixOS lab: users, SSH keys, firewall, one service, one custom module—cold boot and rollback work; the flake is the only source of truth.
Why this day exists
Stage III multiplies structure (layouts, Home Manager). Entering it with a snowflake host guarantees pain. Today is an honesty gate: the machine is rebuildable, operable, and documented.
Theory 1 — Syllabus exit criteria
You may leave Stage II when:
- From cold boot you can roll back a bad generation
- The flake is the only source of truth for the lab host
- Host includes: declarative users, SSH key access, firewall policy, at least one service/timer, one custom module
- Notes cover boot path + network + recovery
Theory 2 — Minimal production-shaped host (definition for this gate)
| Capability | Evidence |
|---|---|
| Flake host | nixosConfigurations.<name> rebuilds |
| Pin | flake.lock committed; nixpkgs 26.05 |
| User | Non-root admin in wheel |
| Remote access | SSH key login; password SSH off (or justified) |
| Firewall | Enabled; SSH allowed; extras documented |
| Packages | Daily tools declarative |
| Service | Custom or high-level service active |
| Module | Local options+config module imported |
| Docs | rebuild, rollback, boot, network |
| Recovery | Rollback card tested |
Not required yet: secrets machinery, Home Manager, Disko redesign, multi-host, reverse proxy zoo.
Theory 3 — Cold boot proof
running system (gen N)
→ reboot
→ firmware → loader → kernel → multi-user
→ SSH/console login works
→ systemctl is-system-running (or degraded explained)
Cold boot catches “worked in this session only” activation myths.
Theory 4 — Source of truth test
| Signal flake is SoT | Smell of drift |
|---|---|
| Rebuild from git repo only | Hand edits in /etc that vanish/surprise |
| README rebuild command works | “Also run these shell fixes” |
| hardware-config in git | Hardware only on machine, never backed up |
Theory 5 — Gate knowledge verbalization
Prepare short answers:
switchvstestvsboot
- What rollback does not restore
- Why SSH public keys in git are OK but passwords are not
- Store vs state paths
- Why custom modules use
mkIf cfg.enable
- How you open the boot generation menu
Worked examples bank
Example A — Gate rebuild
cd ~/nixos-config
sudo nixos-rebuild switch --flake .#labExample B — Eval sanity
nix flake show
nix eval .#nixosConfigurations.lab.config.networking.hostName
nix eval .#nixosConfigurations.lab.config.networking.firewall.allowedTCPPortsExample C — Service proof
systemctl is-enabled sshd || systemctl status sshd
systemctl list-timers --all | headLab 1 — Gate repository hygiene
cd ~/nixos-config
git status
git log --oneline | head
test -f flake.lock && echo lock-okEnsure structure roughly:
flake.nix
flake.lock
hosts/lab/configuration.nix
hosts/lab/hardware-configuration.nix
modules/*.nix
docs/{boot,network,rollback,filesystems,modules-study}.md
README.md
Missing docs → write them now (brief is fine).
Lab 2 — Checklist (tick only if true)
Stage II gate checklist
- NixOS 26.05 lab boots (VM preferred)
nix --version/nixos-versionrecorded
- Flake
nixosConfigurationsrebuild switch works
flake.lockcommitted
- Hostname + flake attr documented
- Admin user declarative +
wheel
- SSH key login works
- PasswordAuthentication disabled or exception documented
- Firewall enabled; SSH port allowed
- Port audit exists
environment.systemPackages/programs.*used intentionally
- ≥1 custom systemd service or timer or meaningful
services.*
- ≥1 custom module with
enableoption
- Assertion or deliberate option validation somewhere
- Generations listed; rollback performed at least once in Stage II
- Boot loader + generation menu documented
- Mount inventory + persist list written
- README rebuild instructions accurate
- No private keys or live passwords in git
- Cold boot → login succeeds
Any empty box is a stop for Stage III.
Lab 3 — Cold boot ceremony
- VM snapshot labeled
day22-pre-coldboot(optional safety)
- Reboot lab
- Login console and/or SSH
systemctl is-system-running || true
hostname;curllocalhost service if any
- Record timestamp + generation
Lab 4 — Rollback proof (again)
- Make a tiny visible change (motd package,
environment.etc."day22".text, …)
switch
- Confirm change
sudo nixos-rebuild switch --rollback
- Confirm reversion
- Re-apply good config if needed
Lab 5 — Architecture one-pager
docs/host-diagram.md:
# lab host
- flake: ~/nixos-config #lab
- users: …
- ssh: keys only …
- firewall: …
- services/timers: …
- modules: …
- boot: …
- disks: …
- what is state: …Lab 6 — Teach-back (10–15 min)
Explain aloud or written:
“Here is how I rebuild this host from git; here is how I recover from a bad generation; here is what I must back up because Nix will not.”
If rough, revisit Days 13–15 and 21.
Theory 6 — Generation evidence commands
sudo nix-env -p /nix/var/nix/profiles/system --list-generations | tail -5
readlink -f /run/current-system
nixos-versionGate notes should include current generation number and flake shortrev if you embed git info (optional).
Theory 7 — What “flake is SoT” excludes
Still allowed outside the flake (state):
- Home directory contents (until HM owns them)
- SSH host keys
- Service databases (when you add them)
- Hypervisor snapshots
Not allowed as required ops procedure:
- “Also apt install…”
- “Then manually systemctl edit…”
- “Copy this binary into /usr/local”
Worked example D — Eval probes for gate
cd ~/nixos-config
nix eval .#nixosConfigurations.lab.config.users.users.alice.isNormalUser
nix eval .#nixosConfigurations.lab.config.services.openssh.enable
nix eval .#nixosConfigurations.lab.config.networking.firewall.enableBoolean/string outputs are quick CI-less checks that config intent is present.
Lab 7 — Secret smell re-scan
cd ~/nixos-config
rg -n "initialPassword|password\s*=\s*\"" || true
rg -n "PRIVATE KEY|AKIA" || trueStage IV will add secret machinery; Stage II must not already leak.
Lab 8 — Offline notes pack
Bundle in docs/ or a gate/ folder:
- Rebuild one-liner
- Rollback one-liner
- Boot menu steps
- Console lockout recovery
- Network identity (IP/interface)
Print or keep on the host that is not the VM (so a broken VM does not eat the runbook).
Common gotchas
| Symptom | Theory |
|---|---|
| Gate “passes” but docs missing | Future you fails |
| Secrets in history | Stage IV will not save past leaks |
| Service only started manually | Not declarative |
| Hardware file not in git | Disk loss → pain |
| Still using channels for system | Diverges from flake story |
Checkpoint
- All Stage II checklist boxes ticked
- Cold boot verified
- Rollback re-verified
- Host diagram written
- Teach-back completed
- Ready for Stage III layout + Home Manager
Commit
cd ~/nixos-config
git add .
git commit -m "day22: stage II gate production-shaped host"Tag optional:
git tag stage-ii-gateTomorrow
Day 23 — Flake layout. Split hosts/ / modules/ / homes/ cleanly; stop growing a single tangled config as Stage III begins (Home Manager arrives soon after).