A modern, pure-leaf dendritic NixOS and Home Manager configuration powered by Den, flake-file, devenv, and agenix-rekey.
- Awesome Nix
- Den Documentation
- NixOS Options Search
- Home Manager Options
- devenv Documentation
- flake-parts Documentation
- Dendritic Aspect Architecture: Pure leaf aspects powered by Den, composable roles, and zero-boilerplate automatic discovery.
- Root Impermanence & Rollback: Ephemeral Btrfs root subvolume rolled back to clean snapshot on boot with explicit persistence paths under
/persistand/cache. - Automated Garbage Collection (
nh): Background weekly system cleanup viaprograms.nh.cleanwith configurable retention (--keep-since 4d --keep 3). - Smart Rebuild Switch & Rollback Protection:
rebuild-switchlabels each generation with<branch>-<scope>-<rev>-<timestamp>and automatically rolls back if activation fails so broken configurations never persist. - Interactive Generation Management:
nix-generationsCLI and Television channel (tv nix-generations, aliasnhg) with real-time bootspec metadata, closure diffs, and pruning controls. - Television Cable Suite: Dedicated channels for git worktrees, branches, cliphist, zsh-histdb, systemd units, flake inputs, NixOS options, and packages.
- Standardized Local Packages: Custom package suite organized under standard Nix
pkgs/by-name/<pkgname>/package.nixhierarchy.
This repository includes custom tools and scripts in pkgs/by-name to streamline daily maintenance and development.
| Command | Description |
|---|---|
rebuild-switch (or rebuild) |
Build and activate NixOS with lazygit-style commit label (<branch>-<scope>-<rev>-<timestamp>). Automatically reverts and deletes generation on failure. |
nh os switch (or nho switch) |
Standard system switch using nh. |
nh os test (or nho test) |
Build and activate system in a transient generation without setting boot default. |
nh os build (or nho build) |
Build system toplevel derivation without activating. |
nix-flake-build [host] [--apply] |
Build system configurations with nix-output-monitor (nom) and optional deployment switch. |
| Command | Description |
|---|---|
tv nix-generations (or nhg, generations) |
Fuzzy search, inspect closure diffs, switch, and delete system generations via Television. |
nix-generations list |
Print tab-separated table of generations with active indicators and labels. |
nix-generations preview <num> |
Detailed bootspec inspection, kernel info, and package closure diff against active system. |
nix-generations switch <num> |
Activate and switch to specified generation number. |
nix-generations boot <num> |
Set specified generation as bootloader default without immediate activation. |
nix-generations delete <num> |
Delete single generation (prevents deleting active generation). |
nix-generations delete-older [count/num] |
Prune older generations keeping latest count or strictly older than generation number. |
| Command | Description |
|---|---|
nix-flake-update [-e <input>] |
Update flake inputs authenticated via GitHub token, with optional -e / --exclude flags. |
update-pkgs [pkg...] |
Automatically bump versions, hashes, and cargo/vendor dependencies in pkgs/by-name via nix-update. |
nh clean all --keep <count> |
Trigger manual garbage collection keeping the latest N generations. |
| Command | Description |
|---|---|
nix run .#write-flake |
Regenerate flake.nix inputs and outputs from modules/flake-parts/flake-file.nix. |
nix run .#write-files |
Synchronize generated files (README.md, AGENTS.md, BOOTSTRAP.md, .workmux.yaml, .nvim.lua). |
nix run .#diagrams.write-topology |
Regenerate system topology documentation in TOPOLOGY.md. |
nix fmt modules/ pkgs/ |
Format all Nix modules and packages according to project conventions. |
nix flake check --no-build |
Validate all host configurations, checks, packages, and apps. |
This repository configures nixConfig for strict, safe, and cached builds:
nixConfig = {
accept-flake-config = true;
allow-import-from-derivation = true;
auto-optimise-store = true;
lazy-trees = true;
show-trace = true;
};The following files in this repository are generated and managed using the files flake-parts module:
README.mdAGENTS.mdBOOTSTRAP.md.workmux.yaml.nvim.lua
Nix files (they're all flake-parts modules) are automatically imported via import-tree. Nix files prefixed with an underscore are ignored. No literal path imports are used. This means files can be moved around and nested in directories freely.
This configuration uses den for declarative multi-entity system management.
| Entity | Purpose |
|---|---|
host |
Channel, networking, system configuration, hardware facts |
user |
Identity, home directory, Home Manager aspects |
Every feature in modules/aspects/ is organized as an atomic leaf aspect under den.aspects.*. Leaf aspects encapsulate their own NixOS, Home Manager, nixpkgs overlay, and impermanence persistence configurations in a single file, and are selectively composed by roles (den.aspects.roles.*) consumed by hosts:
modules/
├── aspects/
│ ├── applications/
│ │ ├── browsers/ # zen, firefox, librewolf, chromium, tor-browser, _common/
│ │ ├── dev/
│ │ │ ├── ai/ # llm-agents, opencode, pi, antigravity, copilot
│ │ │ ├── editor/ # neovim, helix, vim, lazyvim, doom-emacs, vscode, zed, codium
│ │ │ ├── git/ # git, github, lazygit
│ │ │ ├── lang/ # go, rust, node, elixir, lua, nix, cc, grammars
│ │ │ ├── mux/ # tmux, zellij, sesh, workmux, herdr
│ │ │ ├── networking/ # winbox, wireguard, mtr, doggo
│ │ │ ├── security/ # bitwarden, gpg, ssh, sops
│ │ │ ├── shell/ # direnv, mise, television, starship, zoxide, fzf, bat, btop, vivid, fastfetch
│ │ │ └── tree-sitter/ # grammars
│ │ ├── gaming/ # steam, mangohud, gamescope, gamemode, lutris, heroic, bottles, nix-ld
│ │ ├── media/ # mpv, vlc, rmpd, cava, yt-dlp, imv, feh, mpvpaper
│ │ ├── messaging/ # vesktop
│ │ ├── productivity/ # tuxedo, evince, foliate, galculator, localsend, anydesk, scrcpy
│ │ ├── shell/ # zsh (with histdb), carapace, yazi, superfile, cli-utils
│ │ ├── terminals/ # ghostty, kitty, foot
│ │ └── wayland/ # wl-kbptr, fuzzel, cliphist, quickshell, fcitx5
│ ├── core/ # boot, documentation, locale, mounts, networking, nix, nixpkgs, security, users
│ ├── desktop/ # audio, fonts, greeter, gtk, hyprland, kdeconnect, nautilus, niri, stylix, thunar, udiskie, xdg, xserver
│ ├── hardware/ # bluetooth, graphics, input, laptop, nixos, power, steam-hardware
│ ├── roles/ # default, workstation, dev, gaming
│ ├── secrets/ # agenix
│ ├── services/ # avahi, openssh, printing, samba, smartd, tailscale
│ └── virtualization/ # libvirt, podman, waydroid, vm-variant, looking-glass, windows-vm
├── classes/ # devenv, files, nix-unit, formatter
├── core/ # impermanence, policies, quirks
├── flake-parts/ # devenv, diagrams, files, flake-file, flake-root, formatter, meta, pkgs, wrappers
├── hosts/ # nixos, super, sandbox
└── users/ # artifex
Cross-cutting concerns collected from aspects and aggregated at host/user scope:
autostart cache cacheHome codium-extensions codium-settings firewall homeManagerModules nixpkgs-overlays persist persistHome secrets secretsHome
System and user state persistence is managed declaratively in modules/core/impermanence.nix via four Den quirks (persist, cache, persistHome, cacheHome) aggregated by den.aspects.impermanence.collect.
On boot, den.aspects.impermanence.rollback-btrfs rolls the root subvolume (/) back to a read-only root-blank snapshot in initrd (controlled by settings.impermanence.wipeRootOnBoot = true, with optional /home rollback via settings.impermanence.wipeHomeOnBoot = false), while den.aspects.impermanence.tmpfs mounts /tmp on tmpfs.
| Quirk | Target Mount | Scope | Purpose |
|---|---|---|---|
persist |
/persist |
NixOS (environment.persistence."/persist") |
Critical, irreplaceable system state, identity keys, and service databases. |
cache |
/cache |
NixOS (environment.persistence."/cache") |
Regenerable system caches, temporary build artifacts, and container image layers. |
persistHome |
/persist |
Home Manager (home.persistence."/persist") |
Irreplaceable user data, credentials, app configs, shell/session history, and editor state. |
cacheHome |
/cache |
Home Manager (home.persistence."/cache") |
Re-downloadable or regenerable user caches, language toolchains, package registries, and game libraries. |
When auditing an application that writes to ~/.config, ~/.local/share, ~/.local/state, or /var/lib, classify each directory by whether losing it causes data/identity loss (persist / persistHome) or merely a re-download/rebuild (cache / cacheHome):
| Category | Quirk | Examples in Repository |
|---|---|---|
| Identity, Keys & Secrets | persist / persistHome |
/etc/machine-id, /etc/ssh/ssh_host_*_key, /var/lib/systemd/credential.secret, .ssh (0700), .gnupg, .config/agenix, .local/share/keyrings |
| System & Network State | persist |
/var/log, /var/lib/nixos, /etc/NetworkManager/system-connections, /var/lib/NetworkManager, /var/lib/tailscale, /var/lib/bluetooth, /var/lib/libvirt |
| Sessions, History & Databases | persistHome |
.local/state/tmux (resurrect), .local/share/zsh & .histdb, .local/share/zoxide, .local/share/television, .local/state/nvim & .local/share/nvim, .local/share/opencode & .local/state/opencode, .local/share/dankcal |
| Mutable App Configurations | persistHome |
Browser profiles (.config/zen, .mozilla, .config/chromium), .config/VSCodium, .config/vesktop, .config/obsidian, .config/fcitx5, .config/vlc, .config/torlink, .config/zennotes, .config/Thunar |
| Language & Package Caches | cacheHome |
.npm, .bun, .local/share/vite-plus, .cargo, .rustup, .config/go, .cache/uv, .local/share/uv, .local/share/mise, .cache/mise, .local/share/nix |
| Env & Tooling Caches | cacheHome |
.local/share/direnv, .local/share/devenv, .cache/nix-index, .local/share/qalculate, Downloads, .cache |
| Browser & Electron Caches | cacheHome |
.cache/zen, .cache/mozilla, .cache/librewolf, .cache/chromium, .config/ZenNotes (Electron GPU/code cache) |
| Containers & Game Bulk Data | cache / cacheHome |
/var/lib/containers, .local/share/containers, .local/share/Steam, .steam |
Each leaf aspect under modules/aspects/ declares its own persistence paths alongside its NixOS and Home Manager configuration:
{
den.aspects.applications.example = {
nixos = { ... };
homeManager = { ... };
# System-level state (/persist and /cache)
persist = {
directories = [ "/var/lib/example" ];
files = [ "/etc/example/host.key" ];
};
cache.directories = [ "/var/cache/example" ];
# User-level state (/persist/home/<user> and /cache/home/<user>)
persistHome = {
directories = [
".config/example"
".local/state/example"
{
directory = ".local/share/example-secrets";
mode = "0700";
}
];
files = [ ".example_history" ];
};
cacheHome.directories = [
".cache/example"
".local/share/example/toolchains"
];
};
}Hosts and user topologies are declared in modules/hosts/:
| Host | Architecture | User | Roles & Aspects |
|---|---|---|---|
nixos |
x86_64-linux |
artifex |
roles.default, roles.workstation, roles.dev, roles.gaming, hardware.nixos, impermanence, secrets.agenix |
super |
x86_64-linux |
artifex |
roles.default, roles.workstation, roles.dev, roles.gaming, impermanence, secrets.agenix |
sandbox |
x86_64-linux |
artifex |
roles.default, applications.gaming.nix-ld (Isolated testbed host for rapid VM testing) |
The repository includes a reproducible developer environment configured in modules/flake-parts/devenv.nix and integrated via .envrc.
- Ensure direnv and nix-direnv are installed.
- Allow the environment in the repo root:
direnv allow
- Alternatively, enter the shell manually:
nix develop
Deploy system configurations safely using nh:
# Build toplevel derivation
nh os build
# Test build in a transient generation
nh os test
# Switch system generation and activate (with git-labeled generation & rollback protection)
rebuild-switch # or: rebuild
# Standard switch via nh
nh os switch
# Manage, inspect, and prune generations interactively with Television
tv nix-generations # or: nhg, generationsGenerate fleet visualization diagrams and update TOPOLOGY.md:
nix run .#diagrams.write-topology