skip to content

den, a Framework Built on gen

den is a configuration framework for NixOS, nix-darwin and home-manager. It is the first framework built on gen’s libraries. This page shows where each den concept sits on a gen construct, as an example of how a framework is layered on gen. gen itself has no hosts, users or homes. Those are den’s names for kinds it declares.

den declares its entity kinds through gen-schema. den.schema is a gen-schema option, so den.schema.host and den.schema.user are gen kinds, and gen-schema merges them with gen-merge. den reaches gen-schema through the hub, inputs.gen.lib.mkGenLibs { }, so every gen library it uses comes from one revision.

den conceptthe gen construct it sits onread more
den.schema.<kind>a kind, declared with gen-schema’s evalSchema or mkSchemaOptionKinds, Registries and Identity
den.hosts, den.homesinstances in a registry (mkInstanceRegistry), each with a content-derived id_hashStable Identity for Everything
den.aspectsgen-aspects aspects, with includes and one key per classAspects
a Nix class: nixos, darwin, homeManageran aspect key declared category = "class" and built by a terminalDelivery
a parametric aspect, { host, user }: { … }argument injection: gen-bind binds node and other named arguments into a module functionAutomatic Argument Injection
the host → users → homes pipelineedges in one graph, walked by queriesYour Configuration as a Graph
den.policiesrules in a logic program (gen-program), whose results the framework turns into edgesRules That Add Relationships
quirks and pipesa channel key on an aspect (category = "channel"), moved between nodes by a viewDelivery
den’s diagrams and debugginggen-inspect: SQL and selector queries over the graph, “why does this edge exist”, mermaid renderingInspection
batteriesframework content, which den provides itself

In den, a host and an aspect look like this:

den.hosts.x86_64-linux.web-1.users.deploy = { };
den.aspects.web-1 = {
includes = [ den.aspects.ssh ];
nixos = { host, ... }: { networking.hostName = host.name; };
};

The gen layer underneath holds the same facts in gen’s terms. The host is an instance of a host kind, and the aspect’s nixos module takes the host as node:

hosts.web-1.aspects = [ "base" "ssh" ];
aspects.base.nixos = { node, ... }: { networking.hostName = node.name; };
aspects.ssh.includes = [ "base" ];

den supplies the kinds, the registry names, the context argument names and the pipeline. gen supplies the merge, the identity, the graph and delivery. From an Aspect to a NixOS System builds the gen layer in full.

A den configuration can call any gen library directly. The hub’s mkGenLibs { } returns the whole set:

let
gen = inputs.gen.lib.mkGenLibs { };
deps = { web = [ "api" ]; api = [ "db" ]; db = [ ]; };
in
gen.graph.reachableFrom { edges = id: deps.${id} or [ ]; } "web" # [ "api" "db" ]
palette
dark
light
↑↓ select↵ apply esc close

Palettes adapted from Catppuccin (Macchiato) (MIT), Tokyo Night (Apache-2.0), gruvbox (MIT), Catppuccin (Latte) (MIT), Rosé Pine (Dawn) (MIT).