Initial commit

This commit is contained in:
2026-04-17 00:27:22 +02:00
commit 9af07bedff
80 changed files with 5389 additions and 0 deletions

152
SESSION_LOG.md Normal file
View File

@@ -0,0 +1,152 @@
# Session Log
## Current Repo State
- The git worktree is dirty. Many files were already modified before or during this session. Do not revert unrelated changes.
- New main host/user additions are already in place:
- hosts: `polaris`, `zenith`, `orion`
- users: `kiri`, `ergon`
- `zenith` is the Lenovo Yoga Slim 7 ProX 14ARH7 laptop.
- `ergon` is the work user and is present on `polaris` and `zenith`, not `orion`.
## Naming Decisions
- Host names chosen:
- `polaris` = main machine
- `zenith` = laptop
- `orion` = VPS
- Work user chosen:
- `ergon`
## Den / Architecture Decisions
- `kiri` stays on `den._.primary-user`.
- `ergon` is explicit and should not use `den._.primary-user`.
- Do not introduce a local `admin-user` battery yet. Keep repeated patterns explicit until they stabilize.
- Prefer host files thin and move reusable behavior into `modules/features/` or `modules/profiles/`.
## Den Helper Mental Model
- `perHost` / `perUser` are stage gates, not just readability helpers.
- `perUser` is not the same as `parametric.exactly`.
- Actual behavior:
- `perUser` gates entry at exact `{ host, user }`, then evaluates the wrapped aspect under fixed `{ host, user }` with normal `atLeast` matching inside.
- `parametric.exactly` is an inner include matcher based on exact context shape.
- Practical rule used in this repo:
- use `perHost` for host-owned NixOS config that must apply once per host
- use `perUser` for host-user-pair HM or NixOS config
- avoid `take.*` unless doing low-level Den plumbing
## Niri / Display Model
- `lux.niri` was intentionally collapsed back into one conceptual aspect in `modules/features/niri.nix`.
- It now uses:
- `den.lib.perHost` for NixOS-side Niri setup
- `den.lib.perUser` for HM-side Niri settings
- Host monitor layout is a host fact, not a user fact.
- `den.schema.host.displays` exists and is the source of truth for monitor facts.
- Current `polaris` display layout lives in `modules/infra.nix`.
- `programs.niri.settings.outputs` is derived from `host.displays`, so both `kiri` and `ergon` on `polaris` get the same output configuration.
- `displays` intentionally has no `enabled` flag; omission means absent.
## SOPS / SSH / GPG Decisions
- Repo-managed GPG was removed from `modules/features/ssh.nix`.
- If commit signing is added later, prefer SSH signing rather than restoring repo-managed GPG.
- Secret recipient policy currently is:
- one admin age recipient
- `orion` SSH host key recipient
- `.sops.yaml` and `modules/secrets/secrets.yaml` were rekeyed to that policy.
## Current SOPS Model
- SOPS is now host-owned conceptually.
- Current host schema fields:
- `sopsHostSshKeyPath`
- `sopsAdminKeyPath`
- `sopsAdminKeyUsers`
- Current policy:
- `orion` uses `sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]` for host-level NixOS decryption.
- local hosts (`polaris`, `zenith`) use `/var/lib/sops-nix/admin-key.txt` for host-level NixOS decryption.
- HM SOPS also uses the host-provisioned `/var/lib/sops-nix/admin-key.txt`, but only for users listed in `host.sopsAdminKeyUsers`.
- Shared reader group:
- `sops-users`
- Current host metadata in `modules/infra.nix`:
- `polaris.sopsAdminKeyPath = "/var/lib/sops-nix/admin-key.txt"`
- `polaris.sopsAdminKeyUsers = [ "kiri" "ergon" ]`
- `zenith.sopsAdminKeyPath = "/var/lib/sops-nix/admin-key.txt"`
- `zenith.sopsAdminKeyUsers = [ "kiri" "ergon" ]`
- `orion.sopsAdminKeyPath = "/var/lib/sops-nix/admin-key.txt"`
- `orion.sopsAdminKeyUsers = [ "kiri" ]`
- `orion.sopsHostSshKeyPath = "/etc/ssh/ssh_host_ed25519_key"`
- Important operational caveat:
- the admin key file is expected to be provisioned out-of-band on hosts
- config creates `/var/lib/sops-nix` via tmpfiles and adds listed users to `sops-users`, but does not create the private key itself
## SSH Recovery Policy
- `orion` is treated as the remote recovery-critical host.
- `modules/features/services/openssh.nix` now owns both:
- OpenSSH base config
- user `authorizedKeys`
- Recovery assertions now enforce for `requiresSshRecovery = true`:
- OpenSSH enabled
- password auth disabled
- root login disabled
- `sshRecoveryUsers` non-empty
- every recovery user exists
- every recovery user has plain `authorizedSshKeys`
- `sopsHostSshKeyPath` non-null
- SSH exposed through firewall
- `AllowUsers = lib.attrNames host.users` is still the intended model.
## Recent Validation Results
- Successfully built after the Niri / SOPS / SSH refactors:
- `nix build .#nixosConfigurations.polaris.config.system.build.toplevel --show-trace`
- `nix build .#nixosConfigurations.orion.config.system.build.toplevel --show-trace`
- `nix build .#nixosConfigurations.zenith.config.system.build.toplevel --show-trace`
- Verified by evaluation:
- `polaris` Niri outputs for `kiri` and `ergon` match
- local hosts resolve `config.sops.age.keyFile = "/var/lib/sops-nix/admin-key.txt"`
- `orion` resolves `config.sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]`
- HM SOPS for allowed users resolves `"/var/lib/sops-nix/admin-key.txt"`
- `ergon@polaris` has `["sops-users", "wheel", "networkmanager"]`
- tmpfiles includes `d /var/lib/sops-nix 0750 root sops-users -`
## Remaining Warnings / Caveats
- Builds still emit pre-existing Home Manager default-change warnings:
- `gtk.gtk4.theme`
- `xdg.userDirs.setSessionVariables`
- `programs.git.signing.format`
- These warnings were not addressed in this session.
- There is no deployment wrapper or automated bootstrap tooling yet.
- `nixos-anywhere --copy-host-keys` remains the intended `orion` install approach when preserving the SSH host key for first-boot SOPS decryption.
## Architecture Contract
- Added `ARCHITECTURE.md` as the single durable reference for the repo's intended 1.0 structure.
- The contract is grounded in the current codebase:
- `schema` and `infra` own facts
- `users` own cross-host user baselines
- `features` own reusable behavior
- `profiles` and `environments` own bundling
- `hosts` stay thin and compose the final machine shape
- Kept the existing Den helper convention explicit:
- `perHost` and `perUser` are stage gates
- `parametric.exactly` is only for exact inner matching
- avoid new local batteries until the pattern is stable
- No repo redesign was done; this was documentation only.
- Validation:
- doc-only change
- no `nix build` run in this session
- Small open question for later:
- whether `ARCHITECTURE.md` should stay standalone or also be linked from `AGENTS.md` / future README if a contributor-facing index is added
## Architecture Simplification
- Collapsed `environments` into `profiles`.
- Current rule is now simpler:
- `features` are the smallest reusable behavior units
- `profiles` are all named bundles larger than a single feature
- `hosts` still own final composition and explicit host-specific exceptions
- `modules/environments.nix` was removed.
- `graphical` and `development` now live under `lux.profiles._`.
- Kept the repeated `provides.kiri` / `provides.ergon` host wiring explicit for now. The duplication is intentional until a shared host-composition pattern is clearly stable enough to justify extraction.
- Validation:
- `nix build .#nixosConfigurations.polaris.config.system.build.toplevel --show-trace`
- `nix build .#nixosConfigurations.orion.config.system.build.toplevel --show-trace`
- `nix build .#nixosConfigurations.zenith.config.system.build.toplevel --show-trace`
## MANUAL INTERVENTION NOTE BY HUMAN USER, NOT AI AGENT
Removed `ARCHITECTURE.md`. Pinning down the architecture this explicitly feels too rigid and unnecessary.
Perhaps a more generally applicable Design Philsophy would be more helpful and allow for more flexibility.