Day 83 — Capstone 1/5 implement

Updated

July 30, 2026

Day 83 — Capstone 1/5 implement

Stage VIII · ~4h (implementation)
Goal: Close the highest P0 gaps from Day 82 so the Capstone A skeleton is real: flake host role, module layout, HM or service users, and a live checklist that tracks proof—not vibes.

Important

Capstone A (required): flake host · HM or service users · sops/agenix · reverse proxy · deploy-rs/colmena · nixosTest · CI + cache.
Days 83–87 implement; 88 wipe/rebuild; 89 rollback+tests; 90 retro.

Why this day exists

Architecture review without commits is stationery. Day 83 turns GAPS.md P0s into code on a branch, with rebuilds you can demonstrate.


Theory — Working agreements for Stage VIII

Rule Why
One change → build → commit Bisectable; safer switch
Lab VM first Protect daily driver
Checklist is law CAPSTONE-A.md updated same day
No drive-by rewrites Freeze is Day 87
Secrets never in git plaintext Even “temporary”

Suggested repo shape (adapt, don’t dogma)

flake.nix
flake.lock
hosts/<name>/configuration.nix
modules/{proxy,common,users,…}.nix
homes/<user>.nix          # if HM
secrets/secrets.yaml      # sops-encrypted
tests/*.nix
deploy.nix or colmena hive
.github/workflows/ci.yml
docs/{ARCHITECTURE,CAPSTONE-A,RUNBOOK}.md

Capstone A checklist (live)

Copy into repo root if missing; tick as you go this week:

# CAPSTONE-A.md
- [ ] Host role rebuilds from flake
- [ ] HM user OR service user story
- [ ] sops-nix OR agenix wired; service reads secret
- [ ] Reverse proxy edge with TLS or lab HTTP mode documented
- [ ] deploy-rs OR colmena path works from admin machine
- [ ] nixosTest/check catches a real regression
- [ ] CI builds toplevel (and checks)
- [ ] CI pushes to binary cache (preferred)
- [ ] ARCHITECTURE.md current
- [ ] RUNBOOK.md for deploy/rollback
- [ ] Day 88: wipe + rebuild timed
- [ ] Day 89: rollback drill + suite green

Day 83 target scope

From GAPS.md, implement P0s that unblock structure, typically:

  1. nixosConfigurations.<lab> evaluates and builds
  2. Host modules split (common + role)
  3. Users: interactive HM or system service user + data dir
  4. Firewall baseline + SSH
  5. Placeholder modules for proxy/secrets if not ready (interfaces only)—prefer real stubs that mkEnableOption cleanly

Defer full proxy TLS and CI cache to 84–85 if needed—but leave option shapes ready.


Worked example — Minimal host flake skeleton

# flake.nix (sketch)
{
  description = "capstone lab";
  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";
    # sops-nix.url = "github:Mic92/sops-nix";
    # sops-nix.inputs.nixpkgs.follows = "nixpkgs";
  };
  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.lab = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      specialArgs = { inherit inputs; };
      modules = [
        ./hosts/lab/configuration.nix
        ./modules/common.nix
        # inputs.sops-nix.nixosModules.sops
        # inputs.home-manager.nixosModules.home-manager
      ];
    };
  };
}
# modules/common.nix
{ lib, pkgs, ... }:
{
  time.timeZone = "UTC";
  networking.firewall.enable = true;
  services.openssh.enable = true;
  environment.systemPackages = with pkgs; [ vim git curl ];
}
# hosts/lab/configuration.nix
{ config, pkgs, ... }:
{
  imports = [ ./hardware.nix ];
  networking.hostName = "lab";
  # users / HM / roles
  system.stateVersion = "26.05"; # your real value
}

Lab 0 — Branch & checklist

cd /path/to/capstone-flake
git checkout -b capstone/day83
cp ~/lab/90daysofx/02-nixos/day82/CAPSTONE-A.md ./docs/CAPSTONE-A.md  # or merge
mkdir -p ~/lab/90daysofx/02-nixos/day83

Lab 1 — Build green host

nix flake show
nix build .#nixosConfigurations.lab.config.system.build.toplevel -L \
  2>&1 | tee ~/lab/90daysofx/02-nixos/day83/build.log

Fix until green. Prefer build over switch until config is sane; then:

sudo nixos-rebuild switch --flake .#lab
# or deploy path if already wired

Lab 2 — Users story

Track HM (workstation-ish)

  • Enable HM as NixOS module
  • Manage shell + one dotfile
  • Prove with home-manager generations or files in place

Track service users (server-ish)

users.users.myapp = {
  isSystemUser = true;
  group = "myapp";
  home = "/var/lib/myapp";
  createHome = true;
};
users.groups.myapp = { };

Document which track in docs/CAPSTONE-A.md.


Lab 3 — Module hygiene from Day 72

Ensure at least one custom module uses:

  • typed options
  • mkEnableOption
  • mkIf
  • one assertion

Even if proxy is stubbed:

options.my.capstone.proxy.enable = lib.mkEnableOption "edge proxy";

Lab 4 — Update architecture & gaps

# edit docs/ARCHITECTURE.md paths if moved
# mark GAPS.md items closed with PR/commit refs

Write ~/lab/90daysofx/02-nixos/day83/NOTES.md: what shipped, what slipped to 84.


Lab 5 — Smoke

systemctl --failed
hostname
# ssh localhost or from client


Theory — Capstone A success definition

Day 83 is not “finish the whole series project.” It is:

Done Not done
Green host from flake Perfect theming
Users + SSH story Every optional Stage IV service
Module hygiene applied Multi-region fleet
Architecture doc updated Final polish (later capstone days)

Scope control is part of the grade.


Theory — Branch discipline

git checkout -b capstone-a
# work
# merge only when smoke passes

Avoid committing broken main mid-capstone if you use the same repo for the lab host.


Worked example — smoke script

#!/usr/bin/env bash
set -euo pipefail
hostname
systemctl is-active sshd
curl -sf -o /dev/null -w '%{http_code}\n' http://127.0.0.1:… || true
nix flake metadata

Keep it boring; run after every significant rebuild.


Lab 6 — Gap register freeze for Day 83

Write docs/capstone-gaps.md with only items that remain for Days 84–87. Anything critical for a bootable admin host must be closed today.


Lab 7 — Teach-back outline (5 bullets)

  1. How to rebuild
  2. How to roll back
  3. Where secrets live
  4. What state to back up
  5. What the next capstone day will add

Common gotchas

Symptom What to do
Hardware config missing in flake Import hardware-configuration.nix or disko
Infinite recursion after module split Day 71 dependency cycles
HM + system package duplication Pick layers deliberately
Switching daily driver Stop; use VM
Checklist not updated Same commit as code

Checkpoint

  • nix build toplevel green for lab host
  • HM or service user story demoable
  • Modules structured; ≥1 typed custom module
  • CAPSTONE-A.md updated honestly
  • GAPS.md P0s reduced or re-dated
  • Commits on capstone branch

Commit

git add .
git commit -m "day83: capstone host skeleton and user story"

Write three personal gotchas before continuing.

Tomorrow

Day 84 — Capstone 2/5: secrets + reverse proxy end-to-end; tests updated for the edge path.