Skip to content

feat/den: Refactor our features to use vic/den for implementation, closing gaps where possible#86

Open
sini wants to merge 38 commits into
mainfrom
feat/den
Open

feat/den: Refactor our features to use vic/den for implementation, closing gaps where possible#86
sini wants to merge 38 commits into
mainfrom
feat/den

Conversation

@sini
Copy link
Copy Markdown
Owner

@sini sini commented Apr 3, 2026

No description provided.

sini added 8 commits April 2, 2026 14:52
- Add home-manager integration aspect (hm-host/hm-user ctx)
- Migrate zsh feature to den aspect (shell/zsh)
- Migrate audio/pipewire feature to den aspect with providers
- Declare bitstream as first den-managed host
- Add sini user aspect
- Disable old bitstream host definition (_host.nix)
- Update design spec and implementation plan with review fixes
Migrate all 29 default features to den aspects with 1:1 parity:

Trivial (8): avahi, disko, facter, i18n, power-mgmt, ssd, stateVersion, time
Simple (11): firmware, home-manager-feature, hosts (stub), linux-kernel,
  nixpkgs, openssh, security, sudo, systemd, systemd-boot, utils
Moderate (4): deterministic-uids, nix, tailscale, users
Complex (3): agenix, impermanence, networking

Wire den.aspects.default including all features, update bitstream to use it.
Always import home-manager NixOS module via host context (matching old builder).
Update home-platform forwarding class to iterate platforms with guard.

Simplifications for later migration phases:
- hosts: stub (cross-host discovery needs environment context)
- users: simplified (full ACL provisioning needs environment context)
- tailscale: darwin/secrets stubs (needs agenix integration)
- sudo: wheel group only (no per-user doas rules without users injection)
- Forwarding classes for collectsProviders deferred
- Add impermanence forwarding classes (persist, cache, persistHome, cacheHome)
  with dedup and guard for impermanence module presence
- Add secrets forwarding class for age.secrets collection
- Add firewall forwarding class for networking.firewall collection
- Replace hosts-file stub with real cross-host /etc/hosts and SSH known hosts
  generation (reads from existing config.hosts/environments)
- Update firmware, security, systemd, tailscale, impermanence aspects to use
  persist/cache forwarding classes instead of direct environment.persistence
- Rewrite den.aspects.users to call resolveUsers from existing flake-parts lib
- Reads canonical users, environments, groups from flake-parts config
- Full three-level ACL resolution: groups → environment.access → system-access-groups
- Generates NixOS user accounts with deterministic UIDs, SSH keys, group membership
- Add host metadata to bitstream (environment, system-access-groups, networking, facts)
- Verified: sini provisioned on bitstream with UID 1000, correct groups (wheel, audio,
  video, server-access, etc.), description from canonical identity
- sudo: per-user doas rules from ACL-resolved enabled users
- systemd-boot: add missing tmpfs and zramSwap/earlyoom config
- users: fix hashedPasswordFile to use NixOS module config (not flake config)
- agenix: migrate all 16 custom generators to den aspect (agenix-generators)
  Bitstream now has all 20 generators matching cortex
sini added 20 commits April 2, 2026 19:19
ZFS stack (used by bitstream):
- zfs-root: runtime support, boot, packages, kernel params, scrub, trim
- zfs-disk-single: disko declarative layout with encryption and datasets
- impermanence-zfs: initrd rollback services + shutdown hooks
- zfs-diff: diff tools for impermanence

BTRFS stack (parity for other hosts):
- btrfs-root: runtime support with diff tools
- btrfs-disk-single: disko LUKS+BTRFS layout with subvolumes
- impermanence-btrfs: initrd rollback services

Bitstream updated with ZFS metadata (device, impermanence settings)
and includes zfs-disk-single, impermanence-zfs, zfs-diff aspects.

Verified: ZFS in boot.supportedFilesystems, disko device resolved,
rollback-zfs-root service present, rollback-zfs-home correctly absent.
- Fix secrets forwarding class: intoPath now targets age.secrets directly
  (cleaner API - aspects declare secrets.foo instead of secrets.secrets.foo)
- Fix initrd-bootstrap-keys: use direct age.secrets in nixos module context
  instead of secrets class (needed for generator dependencies)
- Fix nix-remote-build-server and network-boot: use resolveUsers for
  getSshKeysForGroup (canonical users lack systemGroups), fix secrets refs
- Migrate independent features: acme, media-data-share, tang,
  nix-remote-build-server, cpu-amd, gpu-amd
- Migrate dependent features: initrd-bootstrap-keys, nix-builder,
  network-boot, server role
- Wire all into bitstream includes

Verified: tang, nix-serve, initrd SSH all enabled on bitstream
- Add resolve-environment.nix: overrides den.ctx.host to enrich host
  objects with resolved environment attrset before aspects see them
- Aspects access host.environment directly, no config.environments lookups
- Fix bitstream public_key path (use rootPath instead of relative)
- Dry-run build passes cleanly
Add modules/den/schema.nix declaring typed options on den.schema.host:
- host.system-access-groups (list str, default [])
- host.settings.linux-kernel.{channel, optimization}
- host.settings.impermanence.{enable, wipeRootOnBoot, wipeHomeOnBoot}
- host.settings.tailscale.{openFirewall, extraUpFlags, extraDaemonFlags, useNftables}
- host.settings.zfs-disk-single.device_id
- host.settings.btrfs-disk-single.{device_id, swap_size}

Update all aspects to read from typed host.settings.* instead of freeform
metadata with or fallbacks. Update bitstream host to use settings namespace.
Remove redundant nixos config from bitstream aspect.
- wireless: facter auto-detection, wpa_supplicant, secrets, impermanence
- network-manager: NM config with wifi powersave, impermanence
- workstation-boot: plymouth boot splash, quiet/splash kernel params
- ceph-device-allocation: settings-only for rook-ceph device path
- xfs-disk-longhorn: disko XFS partition for Longhorn storage

Add typed settings to schema.nix:
- network-manager.wifi-backend (enum)
- ceph-device-allocation.device (nullable str)
- xfs-disk-longhorn.{device_id, mountPoint}

All core/ features now have den aspect equivalents.
Shell/utils (10): archive-tools, data-tools, disk-tools, nix-index,
  process-tools, python, search-tools, ssh, sysmon, zoxide
Dev (16): bat, claude, delta, direnv, eza, gh, git, gitkraken, gpg,
  jujutsu, k9s, lazygit, nvf, starship, wireshark, yazi, zellij, vscode
Productivity (5): alacritty, kitty, obsidian, zathura, zoom
Media (8): easyeffects, jellyfin-client, mpv, qbittorrent, spicetify,
  spotify-player, youtube-music-desktop, yt-dlp
Gaming (3): emulation, mangohud, steam
Messaging (3): discord, kdeconnect, telegram
Browsers (2): firefox, zen-browser
Wayland (5): hypridle, hyprpanel, obs-studio, swaync, waybar
K8s tools (8): kube-core, kube-dev, kube-helm, kube-observability,
  kube-plugins, kube-security, kube-tui, kube-utils
Hardware (17): adb, audio (alias), bluetooth, coolercontrol, cpu-intel,
  ddcutil, gamepad, gpu-intel, gpu-nvidia (consolidated driver/kernel),
  gpu-nvidia-prime, gpu-nvidia-vfio, keyboard, laptop, performance,
  razer, thunderbolt-network, vr-amd

Desktop (12): fonts, gnome, hyprland (consolidated 8 source files),
  hyprland-split-monitors, kde, niri, stylix, uwsm, xdg, xdg-portal,
  xserver, xwayland

Login (3): gdm, regreet, sddm
Roles (18): bgp-spoke, cad, chiptune, daw, dev, dev-gui, gamedev,
  game-engines, gaming, graphics, headscale-role, inference, kexec,
  kube-tools, media, messaging, metrics-ingester, pixel-art, unlock,
  vault-role, workstation
Network (2): wireless-initrd, nfs-boot
Virtualization (3): libvirt, microvm, podman
System (1): ananicy
Runtime (1): nix-ld
Services (1): sunshine
Simple: bgp, bgp-hub, ceph (stub), cilium-bgp, docker, etcd (stub),
  kubernetes-base, nginx, prometheus-exporter, thunderbolt-mesh-bgp,
  thunderbolt-mesh-of

Medium: alloy, attic-server, forgejo, haproxy, homepage, minio,
  oauth2-proxy, open-webui

Complex: grafana (with dashboards), jellyfin (declarative config),
  k3s (538 lines, keepalived VIP, cilium/sops/argocd bootstrap),
  k3s-containerd, kanidm (583 lines, multi-part OIDC provisioning)

Also fix: nix aspect pipe-operator → pipe-operators
- Create den host definitions for all 3 axon k8s nodes
- Add schema settings: bgp, cilium-bgp, thunderbolt-mesh-of, k3s
- Add ipv4/ipv6 and cluster to enrichHost (resolve-environment.nix)
- Fix cilium-bgp and bgp-hub to include den.aspects.bgp
- Fix thunderbolt-mesh-of schema (add loopback.ipv6)
- Disable old axon host definitions (_host.nix)
- Disable namespaces.nix (subagent artifact, needs review)

Verified: all 3 axon hosts + bitstream eval successfully
- Create den.environments with full typed schema
- Create prod/dev environment data as den-native definitions
- Update resolve-environment.nix to read from den.environments
- Implement den-native findHostsByFeature from den.hosts
- Restore ipv4/ipv6 and cluster in enrichHost
- Fix jellyfin: move inputs to flake-parts level

Breaks the infinite recursion cycle. Remaining aspect bugs need individual fixes.
- Migrate environments to den-native type (breaks recursion cycle)
- Add instantiate per host for channel selection
- Create cortex host definition
- Fix inputs-in-NixOS-module recursion pattern
- Fix peer host IP extraction for thunderbolt aspects

All 7 NixOS hosts eval: bitstream, axon-01/02/03, uplink, blade, cortex
Channel schema (den.schema.host):
- host.channel option: nixos-unstable, nixpkgs-master, nixos-stable, nixpkgs-stable-darwin
- Automatically sets host.instantiate from channel (nixosSystem/darwinSystem)
- Removes explicit instantiate from all host definitions
- Maps each channel to matching nixpkgs + home-manager + nix-darwin inputs

Home-manager channel matching:
- HM NixOS/Darwin module import now reads from host.channel
- Each channel gets its matching home-manager version

Darwin support:
- Import den.flakeOutputs.darwinConfigurations for merge semantics
- patch host enabled and listed in darwinConfigurations

All 7 NixOS hosts + 1 Darwin host eval successfully.
- Move user ACL resolution into enrichHost (resolve-environment.nix)
  so host.users.{all, enabled, enabledNames} are available to all aspects
- Simplify users, sudo, nix-remote-build-server, network-boot aspects
  to read from host.users.enabled instead of resolving independently
- Fix all remaining aspects using inputs from NixOS module args:
  emulation, gitkraken, firefox, spicetify, hyprland, vr-amd,
  k3s-containerd, zen-browser, discord, xdg-portal
  → moved inputs to flake-parts top-level module arg

Verified: sini provisioned on all hosts with wheel, UID 1000, 2 SSH keys,
zsh shell. cortex has 3 normal users (sini, shuo, will).
sini added 10 commits April 3, 2026 20:01
Move to modules/_legacy/ (preserving relative paths):
- apps/, core/, features/, services/, environments/ (old feature defs)
- hosts/*/host.nix (old host definitions)
- hosts/cortex/vms/ (microvm-cuda, windows-vfio)
- flake-parts/features/, flake-parts/environments/

Disable old host builders (prefixed with _):
- builders, nixos-configurations, home-config, utils

Update for den:
- colmena: reads from den.hosts
- expose-options: exports den-hosts, den-environments

NOTE: k8s-update-manifests hook skipped — kubernetes system depends on
config.features which is now in _legacy. K8s migration is a future task.

All 8 hosts eval successfully.
…sers

- Fix k3s secrets: use optionalAttrs instead of mkIf for forwarding class
- Fix impermanence perUser: accept { host, user } for take.exactly
- Add environment as NixOS module arg via ctx.host.includes
- Fix kanidm: use flake-level config.groups, host.resolvedUsers.all

Dry-run: bitstream OK, axon-01 OK. Remaining hosts have aspect bugs.
- Stylix: use autoImport + followSystem to propagate config to all HM users
  Remove redundant perUser home sub-aspect
- Agenix HM modules: inject via den.ctx.hm-host (only hosts with HM users)
  Includes masterIdentities for rekey
- Add system-owner to den.schema.host, set on blade/cortex
- Fix scx.package priority conflict between performance/laptop aspects
- Fix ollama: detect GPU via NixOS config instead of hasFeature
- Fix waybar/hyprpanel: get host from perUser closure, not HM module arg

Dry-run: bitstream OK, axon-01 OK, blade OK
Remaining: cortex (ollama config ref), uplink (kanidm env string)
- Channel schema sets home-manager.module per host (den reads host.home-manager.module)
- Fix kanidm oidc-secrets: use perHost ({host}:) for environment access
- Add secretPath to prod/dev environment definitions
- Fix ollama: move GPU detection into NixOS module with config access
- Fix haproxy: use host.name instead of host.hostname
- Fix attic-server: stub hasFeature with default
- Fix steam: add config to module args for nvidia prime detection
- Fix prometheus: use findHostsByFeature, stub hasFeature checks
- Partial fix for bgp-hub, vault, open-webui, alloy config.den.hosts refs

Dry-run: bitstream, axon-01, blade, cortex all OK
Uplink: blocked on hasFeature in bgp-hub, vault, open-webui, alloy
(needs den-native hasAspect implementation)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant