Day 10 — Stage I gate

Updated

July 30, 2026

Day 10 — Stage I gate

Stage I · ~4h (review + proof)
Goal: Close Stage I by demonstrating (not just claiming) that you understand store/closures, can pin a flake, enter a devShell on a clean context, and do not depend on channels for the project.

Why this day exists

Gates prevent “I watched myself type commands” from becoming “I own the material.” Stage II installs an OS; weak foundations make every rebuild mystical. Today is deliberate proof.


Theory 1 — What Stage I claimed

Day You should still own
1 Three faces of Nix; eval vs realize; flakes enabled
2 Store path anatomy; closure; GC roots; result trap
3 Attrsets, let, inherit, shallow merge
4 Function patterns, defaults, @, ellipsis
5 Laziness vs import; multi-file; lib taste
6 Derivation idea; trivial build; logs
7 Modern CLI intents
8 Project flake + lock + devShell
9 Classic ↔︎ modern map; channels as history

Theory 2 — Exit criteria (syllabus contract)

You may leave Stage I when:

  1. You can explain a store path and a lock file plainly
  2. nix develop works for your project after store is populated, without channel ceremony
  3. The project does not require nix-channel / <nixpkgs> for normal use
  4. You can rebuild understanding from notes under mild pressure (gate checklist)

Theory 3 — Clean-context testing

“Works on my polluted laptop” is not a gate.

Clean context options Notes
New Unix user on same machine Fast
Fresh VM with Nix installed Better isolation
Container with Nix (advanced) Optional
Friend’s machine Social reproducibility

Goal: clone/copy project → nix develop → tools appear.


Theory 4 — Offline after populate (honest version)

Claim Reality
Fully offline forever Only if all inputs/substitutes already in store
Offline nix develop after one online populate Often true for pinned shells
Eval may still want network Unlocked floating inputs / registry

Gate standard: document what you achieved offline, not aspirational purity.


Theory 5 — Knowledge you must verbalize

Prepare short answers (2–4 sentences each):

  1. Language vs package manager vs NixOS
  2. Why two versions of a library can coexist
  3. Definition of closure
  4. What a GC root is; name three kinds
  5. Eval failure vs build failure
  6. What flake.lock pins
  7. Why // is not module merge
  8. When to use nix run vs nix develop

Worked examples bank

Example A — Gate project shape

stage1-gate/
  flake.nix
  flake.lock
  README.md
  notes/
    answers.md
    classic-modern.md   # from day09 or link

Example B — Prove pin

nix flake metadata
# record: nixpkgs locked rev

Example C — Prove shell

nix develop -c bash -c 'command -v git; command -v hello || true; echo OK'

Lab 1 — Assemble the gate repository

mkdir -p ~/lab/90daysofx/02-nixos/day10/stage1-gate/notes
cd ~/lab/90daysofx/02-nixos/day10/stage1-gate

Copy or recreate a polished flake from day08:

  • inputs.nixpkgs.urlnixos-26.05
  • devShells with at least: git, one language or ops tool, jq or hello
  • README with exact enter instructions
nix flake lock
nix develop -c git --version
git init
git add .
git commit -m "day10: stage I gate flake"

Lab 2 — Written exam (open notes first, then closed)

In notes/answers.md, answer Theory 5 prompts. Then collapse notes and re-answer on paper/blank buffer. Diff gaps; restudy weak days.


Lab 3 — Clean context run

Pick one:

Option A — second user

# as admin, create labuser if policy allows; or use a VM

Option B — fresh directory + new shell env hygiene

# unset NIX_PATH to ensure you are not leaning on it
env -u NIX_PATH nix develop -c true

Document exact steps that succeeded on the clean context.


Lab 4 — Store drill (observation)

# from within project after develop once
nix flake metadata --json | head -c 500
# build something tiny if you expose packages.default
nix build nixpkgs#hello --print-out-paths --no-link
P=$(nix build nixpkgs#hello --print-out-paths --no-link)
nix path-info -rS "$P" | tail -5

Write:

  1. Full path of hello
  2. Rough requisites count
  3. Whether a result symlink currently roots anything in the gate dir

Lab 5 — Gate checklist ceremony

Print and tick honestly:

Foundations checklist

  • Three faces of Nix explained
  • Store path anatomy explained
  • Closure defined correctly
  • GC roots: ≥3 kinds named
  • Attrset + let + inherit demo exists in notes
  • Function with defaults + ellipsis written once
  • Multi-file import demo exists
  • Derivation vs output path explained
  • Modern CLI cheat-sheet exists
  • Classic↔︎modern table exists
  • Project flake with committed lock
  • nix develop on clean context documented
  • No required channel for project workflow
  • Installer / Nix version recorded (nix --version)

Any empty box → fix before Stage II.


Lab 6 — Capstone teach-back (10 minutes)

Record yourself or write a monologue:

“Here is how Nix keeps two library versions; here is what my lock file guarantees; here is how I enter my project shell on a new machine.”

If you cannot do it smoothly, restudy Days 1–2 and 8.



Theory 6 — What “flake owns the project” means in practice

Stage I does not require a NixOS host. It requires that your project is reproducible from:

git clone → cd project → nix develop
Owned by flake Not owned (yet)
inputs + flake.lock Machine-wide channels
devShells.default tools Random nix profile installs for this project
Documented enter path Tribal “source this bashrc first”

Minimal gate flake (26.05)

{
  description = "Stage I gate — 90DaysOfX";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";

  outputs = { self, nixpkgs }:
  let
    system = "x86_64-linux"; # or aarch64-linux / darwin
    pkgs = import nixpkgs { inherit system; };
  in {
    devShells.${system}.default = pkgs.mkShell {
      packages = with pkgs; [ git jq hello ];
    };
  };
}

Commit both flake.nix and flake.lock.


Theory 7 — Registry vs project inputs (trap)

nix registry list may show a global nixpkgs → floating ref. That is fine for ad-hoc nix run nixpkgs#…, but the gate must not require it:

# Prefer flake-relative evaluation
nix develop .
# not: hope that <nixpkgs> matches your mental pin

If nix develop fails without ambient registry entries, your inputs are incomplete.


Theory 8 — Eval vs build failures (gate discrimination)

Failure class Example Gate response
Eval syntax, missing attr, infinite recursion Fix expressions; nothing in store
Build compile error, hash mismatch Fix derivation / fetch
Runtime binary missing from PATH in shell Fix packages / nativeBuildInputs

Verbalize which class you hit during the gate—vague “Nix is broken” is a fail.


Worked example D — Offline populate script (notes)

# online once
nix develop -c true
nix build nixpkgs#hello --no-link

# later offline (airplane mode): should still work if store+lock complete
# nix develop -c git --version

Document exactly what still needs network on your machine (flake tarball fetches if not cached, substituters, etc.).


Lab 7 — Metadata and lock archaeology

cd ~/lab/90daysofx/02-nixos/day10/stage1-gate
nix flake metadata
nix flake metadata --json | jq -r '.locks.nodes.nixpkgs.locked.rev // .locks.nodes.nixpkgs.locked.narHash'

Paste locked rev into notes/answers.md. That string is evidence you understand pins.


Lab 8 — Negative proof: channel independence

# If channels exist, show they are optional for the project
nix-channel --list 2>/dev/null || true
env -u NIX_PATH nix develop -c true

If this fails, fix the flake until it passes. Stage II installs NixOS; do not carry channel dependency into it.

Common gotchas

Symptom Theory
Gate flake uses <nixpkgs> Fails purity/channel independence
Lock not in git Teammate gets different revs
Shell only works with ambient registry Inputs not declared
“I understand” but blank answers Theory not integrated
Aggressive GC mid-gate Lost realizations; re-populate

Checkpoint

  • All Stage I checklist boxes ticked
  • Gate repo committed with lock
  • Clean-context nix develop documented
  • Written answers for Theory 5
  • Ready to risk a disposable VM for NixOS

Commit

cd ~/lab/90daysofx/02-nixos/day10/stage1-gate
git add .
git commit -m "day10: stage I gate passed"

Tomorrow

Day 11 — Install NixOS lab. Disposable VM (preferred), UEFI, first boot of NixOS 26.05 “Yarara”—the machine Stage II will own with flakes.