den.aspects
den.aspects
Section titled “den.aspects”An attribute set of aspects. Each aspect key names an aspect; its value is
an aspect set containing per-class deferred modules and optional includes and provides:
den.aspects = { dns = { nixos.services.resolved.enable = true; darwin.networking.dns = [ "1.1.1.1" ]; includes = [ ./dns ]; };};Auto-generation
Section titled “Auto-generation”Den auto-generates den.aspects entries from den.hosts, den.homes,
and den.users. For every declared host/home/user, an aspect is created
with the appropriate class configurations. You do not need to declare
den.aspects manually unless adding shared aspects.
den.ful
Section titled “den.ful”Type: attrsOf aspectsType
Namespaced aspect collections. Each key is a namespace name, each value
is a full aspectsType. Populated by den.namespace or by merging
upstream denful flake outputs.
den.ful.myns = { some-aspect = { nixos.services.foo.enable = true; };};flake.denful
Section titled “flake.denful”Type: attrsOf raw
Raw flake output for publishing namespaces. Set automatically by
den.namespace; consumed by downstream flakes that import your aspects.
Aspect structure
Section titled “Aspect structure”An aspect is an attribute set with:
| Key | Purpose |
|---|---|
<class> | Config merged into hosts/homes of that class |
includes | List of modules or functions dispatched by context |
__functor | Auto-generated by parametric; drives dispatch |
Static vs parametric includes
Section titled “Static vs parametric includes”Functions in includes receiving { class, aspect-chain } are static —
evaluated once during aspect resolution. Functions receiving context
arguments ({ host }, { user }, etc.) are parametric — evaluated
per context during ctxApply.
meta.adapter
Section titled “meta.adapter”An aspect can declare a subtree adapter that controls how its includes are resolved. The adapter composes with the inherited adapter from parent aspects or context nodes.
den.aspects.monitoring = { meta.adapter = inherited: den.lib.aspects.adapters.filter (a: a.name != "noisy-exporter") inherited;
includes = [ den.aspects.prometheus den.aspects.noisy-exporter # filtered out den.aspects.grafana ];};The adapter receives the inherited adapter and returns a new one. This enables composition — a parent’s filter cannot be overridden by children.
Adapters set on context nodes (den.ctx.host.meta.adapter) apply
transitively to all aspects resolved within that context:
# Exclude "debug-tools" from all host resolutionden.ctx.host.meta.adapter = inherited: den.lib.aspects.adapters.filter (a: a.name != "debug-tools") inherited;meta.provider
Section titled “meta.provider”Tracks the structural origin of an aspect as a path. Top-level aspects
have meta.provider = []. An aspect provided by foo (via
foo.provides.bar or foo._.bar) has meta.provider = ["foo"].
Deeply nested providers accumulate: foo._.bar._.baz has
meta.provider = ["foo" "bar"].
Adapters can use this to distinguish aspects by origin:
# Only include aspects provided by "monitoring"meta.adapter = inherited: den.lib.aspects.adapters.filter (a: lib.take 1 (a.meta.provider or []) == ["monitoring"]) inherited;den.provides (aliased as den._)
Section titled “den.provides (aliased as den._)”This is the place for Den built-in batteries, reusable aspects that serve as basic utilities and examples.
See Batteries Reference.
Cross-context forwarding
Section titled “Cross-context forwarding”Entities (hosts, users, homes) expose .resolved — the aspect produced
by their context pipeline. Forwards can use this to pull configuration
from one entity into another without manually wiring context calls.
When den._.forward is called without fromAspect, it defaults to
item.resolved, resolving the source entity through its own context
pipeline:
# Collect SSH host keys from all other hostsden.aspects.iceberg.includes = [ ({ host }: den._.forward { each = lib.filter (h: h != host) (lib.attrValues den.hosts.${host.system}); fromClass = _: "ssh-host-key"; intoClass = _: host.class; # "nixos" or "darwin" intoPath = _: [ ]; } )];Each host in each is resolved via its .resolved attribute, and the
ssh-host-key class content is forwarded into the target’s OS config.
host.class is the OS class name ("nixos", "darwin"), not the
context type.
Class resolution
Section titled “Class resolution”When aspects are resolved for a host, Den:
- Collects all aspects referenced by the host
- Extracts the class-specific config (e.g.,
nixosfor NixOS hosts) - Evaluates static includes with
{ class, aspect-chain } - Builds context pairs from
den.ctx - Applies parametric includes via
ctxApply - Merges everything into the host’s
evalModulescall