Day 32 — Stage III gate
Day 32 — Stage III gate
Stage III · ~4h
Goal: Prove the Stage III exit criteria: a workstation/server skeleton where host + Home Manager + project/devShell workflow + flake checks live in one coherent flake layout—and a new machine of the same role is “clone + hardware + rebuild.”
Gates are not content cram days. They are proof. If something is missing, fix it here before Stage IV secrets and services multiply the mess.
Why this day exists
Stage III introduced structure without which Stage IV becomes dangerous:
| Stage III skill | Stage IV needs it because… |
|---|---|
| hosts/modules/homes | Secrets modules attach cleanly |
| Lock discipline | New inputs (sops-nix) must pin sanely |
| HM as NixOS module | User + system activate together |
| direnv/devShell | Service dev doesn’t bloat system |
| checks | Catch eval breakage before deploy |
| light overlays | Occasional pin without chaos |
Today you demonstrate, not skim blog posts.
Theory 1 — Official exit criteria (from syllabus)
New machine of same role = clone flake + hardware config + rebuild.
Operationalization:
- Flake is the source of truth (no critical imperative snowflakes)
- Layout is navigable by someone else (or future you)
- User environment is HM-managed for shell/git basics
- Project tools are not only global profiles
nix flake check(your subset) passes
- Rebuild from cold boot still works; rollback still works
Theory 2 — Evidence pack (what “done” looks like)
Prepare a short evidence directory (journal or docs/stage-iii-evidence.md):
# Stage III evidence
## Tree
(paste tree -L 3)
## Commands
- nix flake show
- nix flake check
- nixos-rebuild switch --flake .#lab
- direnv / nix develop proof
- home-manager user programs proof
## Pins
- nixpkgs rev: …
- home-manager rev: …
## Known debt
- …Theory 3 — Role skeleton checklist
Host (hosts/lab)
- Hostname set
- Hardware imported
- Common modules imported
- SSH keys-only access still true
- Firewall stance known (even if simple)
system.stateVersionset
Modules
- Common policy split (users/ssh/nix/…)
- At least one custom module still present from Stage II
- Overlay wiring intentional
Homes
- HM NixOS module wired
- User programs: shell + git
- At least one managed file or XDG config
- Optional user service still present
Flake outputs
nixosConfigurations.<host>
devShellsor project-flake workflow documented
checksnonempty and passing
formatteroptional but nice
- Style doc (flake-parts vs hand-rolled)
Theory 4 — Clone drill (mental or real)
Ideal proof on a second VM:
git clone <your-flake-url> lab && cd lab
# generate or copy hardware-configuration for THIS machine
sudo nixos-rebuild switch --flake .#labIf you lack a second VM today: walk the steps dry and list what would differ (disk UUIDs, hostname, network).
Theory 5 — Debt register
Unfinished work is allowed only if listed:
| Debt | Stage to pay |
|---|---|
| Secrets still plaintext | IV (33–35) urgently |
| No format check | Fix today if <1h |
| Theming rabbit hole | Never required |
| Multi-host | Later stages |
Do not enter Stage IV with “I will structure the flake later.”
Lab 1 — Tree and show
cd /path/to/your-flake
find . -type f \( -name '*.nix' -o -name '*.md' -o -name '.envrc' \) | sort
nix flake metadata
nix flake showPaste into evidence doc.
Lab 2 — Full rebuild proof
sudo nixos-rebuild switch --flake .#labVerify:
hostname
systemctl is-active sshd
git config --global --get user.name || true
command -v direnvLab 3 — Checks pass
nix flake check -LFix failures before continuing. If toplevel check is too heavy, ensure documented lighter checks still pass.
Lab 4 — DevShell / direnv proof
cd ~/lab/90daysofx/02-nixos/day28/demo-app # or your project
# show tools available via direnv or nix develop
nix develop -c trueLab 5 — Rollback still works (confidence)
# list generations
sudo nix-env -p /nix/var/nix/profiles/system --list-generations | tailYou do not need to break the system today if already proven in Stage II—but confirm you still know the boot menu / switch --rollback path. Write the commands in evidence.
Lab 6 — Peer-style review of your own flake
Answer in writing:
- Where do I add a second host?
- Where do I add a system service module?
- Where do I add a user package?
- How do I update only nixpkgs?
- What is still imperative on this machine?
If any answer is “I don’t know,” fix docs or layout now.
Lab 7 — Gate commit and tag (optional)
git add .
git commit -m "day32: stage III gate — host+HM+shell+checks"
git tag -a stage-iii-gate -m "Stage III exit"Tags help Stage VIII capstone archaeology.
Theory 6 — Stage III → IV interface contract
Stage IV will attach:
| Concern | Expected hook in your flake |
|---|---|
| sops-nix / agenix | module import + secrets files outside store plaintext |
| reverse proxy | modules/services/ style |
| data service | state dirs + secrets paths |
| firewall matrix | docs/ports.md living doc |
If your layout has nowhere obvious to put those, redesign today.
Theory 7 — Pin coherence check
nix flake metadata
# home-manager should follow nixpkgs when you set followsMismatched HM release vs nixpkgs (e.g. HM 25.11 on nixpkgs 26.05) is a classic eval footgun. Align release-26.05 tracks.
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
home-manager.url = "github:nix-community/home-manager/release-26.05";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};Worked example — Minimal checks still count
checks.${system}.hostname = pkgs.runCommand "check-hostname" { } ''
# example pattern only — prefer real eval checks you already have
echo ok > $out
'';Better: evaluate that nixosConfigurations.lab exists and maybe that config.networking.hostName matches expectation (as you did in Day 30). Gate requires passing checks, not toy checks that ignore the host.
Lab 8 — HM vs system package boundary audit
List five tools and where they live:
| Tool | systemPackages | HM home.packages | devShell |
|---|---|---|---|
| git | ? | ? | ? |
Prefer: system or HM for daily drivers; devShell for language toolchains.
Lab 9 — flake.lock age honesty
git log -1 --format=%ci -- flake.lockIf the lock is months stale on a public-facing host, schedule an update session—not a blind full update on this gate day unless you have time to smoke-test.
Common gotchas
| Symptom / mistake | What to do |
|---|---|
| Gate day used to learn HM from zero | Return to Day 25; don’t fake the gate |
| Checks failing “but switch works” | Fix checks—CI will not care about switch on your laptop |
| Evidence only in head | Write the evidence file |
| Second host impossible today | Dry-run clone steps still required |
| Secret debt ignored | Escalate to Day 33 first thing next stage |
| Layout relapsed into monolith | Re-split before Stage IV |
Checkpoint — Stage III exit
- Layout: hosts / modules / homes
- Lock policy exists; lock committed
- HM as NixOS module; shell + git managed
- Files/XDG or programs configs real
- direnv/devShell workflow works
- Flake style chosen and documented
nix flake checkpasses
- Light overlay optional but understood
- Evidence doc written
- Clone + hardware + rebuild story clear
Commit
git add .
git commit -m "day32: stage III gate"Write three personal gotchas before continuing.
Tomorrow
Day 33 — Secret problem: why strings in Nix are dangerous, how the store leaks “secrets,” and what patterns Stage IV will replace.