Files
lux/SESSION_LOG.md
2026-04-17 00:27:22 +02:00

7.6 KiB

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.