Configure Aspects
Den created aspects.
Section titled “Den created aspects.”Den automatically creates an aspect for each of your host/user/home defintions. For example, with the following definitions:
den.hosts.x86_64-linux.igloo.users = { tux = { classes = [ "homeManager" "hjem" ]; }; pingu = { classes = [ "maid" ]; };};Den will create the following parametric aspects for you:
den.aspects.igloo = parametric { nixos = {}; # `host.class` was derived from the host platform };
den.aspects.tux = parametric { homeManager = {}; hjem = {}; };
den.aspects.pingu = parametric { maid = {}; };Aspect Basics
Section titled “Aspect Basics”In addition to per-class modules, an aspect has an includes list referencing other aspects, and provides for sub-aspects in same category:
{ den, ... }: { den.aspects.laptop = { # Owned configs per class nixos = { pkgs, ... }: { environment.systemPackages = [ pkgs.git ]; }; darwin.nix-homebrew.enable = true; homeManager.programs.starship.enable = true;
# Dependencies includes = [ den.provides.primary-user den.aspects.gaming.provides.emulation ]; };
den.aspects.gaming = { darwin = ...; nixos = ...; provides.emulation = { darwin = ...; nixos = ...; }; }}Owned Configs
Section titled “Owned Configs”Attributes named after a Nix class (nixos, darwin, homeManager, or any
custom class) are referred by this documentation as owned configs.
They are just a regular Nix module:
- Attrset Module: plain and simple configuration.
- Function Module: taking module arguments (
{ config, pkgs, lib, ... }: { }).
# Attrset formden.aspects.laptop.nixos.networking.hostName = "laptop";
# Function formden.aspects.laptop.nixos = { pkgs, ... }: { environment.systemPackages = [ pkgs.git ];};Includes
Section titled “Includes”includes is a list of aspects used to declare dependencies between aspects.
Unlike other Nix libraries that use stringly-typed “tags” to define requirements, Den uses real aspect references, these can be type-checked by the Nix module system.
den.aspects.workstation.includes = [ # Reference another aspect (its full DAG is included) den.aspects.dev-tools];It is important to note the three kinds of values that Den distinguishes as part of an includes list:
- Static (plain attribute set):
{ nixos.foo = ...; } - Static (aspects leaf):
{class, aspect-chain}: { ${class}.foo = ...; } - Parametric (any other function):
{ host, user }: { ${host.class}.foo = ...; }
(1) and (2) are termed static aspects and are the terminal leafs of aspects DAG.
(1) provides configuration unconditionally, and (2) gets access to the class that is
being resolved and an aspect-chain that lead to the current aspect (most recent last).
(3) is a more interesting kind of aspect that is used by Den to pass host/user defitions
into these functions, so they can inspect the host features and provide
configuration accordingly.
Provides
Section titled “Provides”provides creates named sub-aspects accessible via den.aspects.<name>._.<sub>
or den.aspects.<name>.provides.<sub>:
den.aspects.tools.provides.editors = { homeManager.programs.helix.enable = true; homeManager.programs.vim.enable = true;};
# Used elsewhere:den.aspects.alice.includes = [ den.aspects.tools._.editors ];provides can also be parametric functions:
den.aspects.alice.provides.work-vpn = { host, user, ... }: lib.optionalAttrs host.hasVpn { nixos.services.openvpn.servers.work.config = "..."; };Global Defaults
Section titled “Global Defaults”den.default is a special aspect applied to every host, user, and home:
{ den.default = { nixos.system.stateVersion = "25.11"; homeManager.home.stateVersion = "25.11"; includes = [ den.provides.define-user den.provides.inputs' ]; };}Aspect Meta-Data
Section titled “Aspect Meta-Data”Aspects have a meta submodule that can be used to attach meta-data
at the aspect-level.
This is useful for introspection, for example, using some key to filter out aspects or communicate information about aspects to other tooling like graph generators.
Since .meta is a freeformType you can add any custom attribute or import a module on it.
The following are default meta.* attributes defined by Den:
aspect.name # "igloo", the submodule nameaspect.meta.loc # the location [ "den" "aspects" "igloo" ] from where name is derived.aspect.meta.name # "den.aspects.igloo" derived from locaspect.meta.file # the last file where this aspect was defined.aspect.meta.self # a reference to the aspect module `config`.You can access meta values by referencing an aspect:
den.aspects.igloo.meta.nameOr if an aspect needs to access its own meta data as part of its parametric functor, it can do something like:
den.aspects.foo = { config, lib, ... }: # module args to access `config.meta` { meta.foo = "bar"; __functor = self: ctx: if config.meta.foo == "bar" then { } # do nothing, skip. { includes = filter (i: someCondition i) self.includes; }; }Aspect Custom Submodule
Section titled “Aspect Custom Submodule”In case an aspect needs a custom submodule, it can be added this way:
# User aspect `tux`den.aspects.tux = { config, ... }: # The function-args style is required for `imports` not to be interpreted as an Aspect class. { imports = [ { options = { default-key = lib.mkOption { type = with lib.types; str; }; keygrip = lib.mkOption { type = with lib.types; str; }; }; } ];
default-key = "Hello World!"; keygrip = "Hello World!";}And then, you can refer to tux aspect from other aspects:
{ den, ... }:{ den.aspects.igloo = { homeManager = { config, ... }: { programs = { gpg = { enable = true; settings.default-key = den.aspects.tux.default-key; # Access the `tux` aspect statically }; };
services = { gpg-agent = { enable = true; enableSshSupport = true; sshKeys = [ den.aspects.${config.home.username}.keygrip # Access the current user aspect dynamically ]; }; }; }; };}Aspect Fixed-Point
Section titled “Aspect Fixed-Point”Aspects are fixed-point, meaning that they can reference themselves, as such:
{ den.aspects.igloo = {config,...}: # Here, `config` represents the aspect `igloo` itself. { meta = { default-key = "Hello World!"; };
homeManager = { programs = { gpg = { enable = true; settings.default-key = config.meta.default-key; };
git = { enable = true; settings.signing.key = config.meta.default-key; } }; }; };}