❄️ Try it now! Launch our template VM: nix run github:vic/denOr clone it and run the VM as you edit nix flake init -t github:vic/den
nix flake update den
nix run .#vmNeed more batteries? see vic/denful |
🏠 Concise hosts+users and standalone-homes definition. # modules/den.nix -- reuse home in nixos & standalone.
{
# $ nixos-rebuild switch --flake .#work-laptop
den.hosts.x86-64-linux.work-laptop.users.vic = {};
# $ home-manager switch --flake .#vic
den.homes.aarch64-darwin.vic = { };
# That's it! The rest is adding den.aspects.
}🧩 Aspect-oriented dendritic modules (example) # modules/work-laptop.nix
{ den, ... }:
{
den.aspects.work-laptop = {
darwin = ...; # (see nix-darwin options)
nixos = ...; # (see nixos options)
includes = with den.aspects; [ vpn office ];
};
}
# modules/vic.nix
{ den, ... }:
{
den.aspects.vic = {
homeManager = ...;
nixos = ...;
includes = with den.aspects; [ tiling-wm ];
provides.work-laptop = { host, user }: {
darwin.system.primaryUser = user.userName;
nixos.users.users.vic.isNormalUser = true;
};
};
} |
den separates the definition of systems from their configuration. You declare your machines and users using a concise syntax, and then attach features to them using an aspect-oriented approach.
-
Hosts & Homes: You define what systems exist (e.g.,
den.hosts.my-laptoporden.homes.my-user). This part is focused only on the system's identity and its users. See the schema inmodules/_types.nix. -
Aspects: You define how systems are configured using
den.aspects. An aspect is a tree of configuration modules. Aspects can provide modules to other aspects forming a graph of configurations. Aspect dependency graphs are applied to hosts and homes to build the final system configuration.
This separation keeps your system definitions clean and makes your configurations reusable and composable.
The syntax for defining hosts and standalone homes is minimal, focusing on identity, not features. All available options are defined in the modules/_types.nix schema.
Define NixOS/Nix-Darwin hosts in den.hosts and standalone home-manager configurations in den.homes.
# modules/systems.nix
{
# Defines host 'rockhopper' with user 'alice'.
# Builds with: $ nixos-rebuild switch --flake .#rockhopper
den.hosts.x86_64-linux.rockhopper.users.alice = { };
# Defines standalone home 'cam'.
# Builds with: $ home-manager switch --flake .#cam
den.homes.x86_64-linux.cam = { };
}For a working example, see templates/default/modules/_example/hosts.nix and homes.nix.
den automatically creates an aspect for each host and user. A host rockhopper gets a den.aspects.rockhopper aspect, and a user alice gets den.aspects.alice. You can add configuration to these aspects from any module.
# modules/features.nix
{
# Add configuration to the 'rockhopper' aspect
den.aspects.rockhopper.nixos.networking.hostName = "rockhopper";
# Add configuration to the 'alice' aspect
den.aspects.alice.homeManager.programs.helix.enable = true;
}Dependencies between host/user aspects is defined by modules/aspects/dependencies.nix. For a full example, see templates/default/modules/_example/aspects.nix.
Apply global settings using default aspects, defined in modules/aspects/defaults.nix.
den.default.host: Applied to all hosts.den.default.user: Applied to all users within hosts.den.default.home: Applied to all standalone homes.
You can set static values per class or use parametric includes for dynamic, context-aware configurations.
# modules/defaults.nix
{
# Static default: set state version for all NixOS hosts
den.default.host.nixos.system.stateVersion = "25.05";
# Parametric default: define a user account on every host
den.default.user._.user.includes = [
({ user, host }: {
${host.class}.users.users.${user.name}.isNormalUser = true;
})
];
}See this in action in templates/default/modules/_example/defaults.nix and aspects.nix.
den provides ready-to-use aspects for common patterns.
den.home-manager: Integrateshome-managerinto NixOS/Darwin hosts. Seemodules/aspects/batteries/home-manager.nix.den.import-tree: Recursively imports non-dendritic.nixfiles, ideal for migrating existing setups. Seemodules/aspects/batteries/import-tree.nix.
Enable them by adding them to an aspect's includes list, for example, to enable home-manager for all hosts:
# modules/home-managed.nix
{ den, ... }:
{
den.default.host._.host.includes = [ den.home-manager ];
}Aspects can include other aspects (includes) or provide configuration to them (provides), creating a powerful dependency graph. A user aspect, for example, can provide host-level settings to the host it's running on.
# modules/aspects.nix
{
den.aspects.alice._.user.includes = [
({ host, user }:
# Provide tmux config to the host if the user is 'alice' on a non-darwin system
if user.userName == "alice" && host.class != "darwin"
then { nixos.programs.tmux.enable = true; }
else { })
];
}For more patterns, see flake-aspects and the examples in templates/default/modules/_example/aspects.nix.
You can override the default system builders (nixosSystem, homeManagerConfiguration) by providing a custom instantiate function. This is useful for supporting new system types or using different nixpkgs channels.
# modules/wsl.nix
{ inputs, ... }:
{
den.hosts.x86_64-linux.my-wsl = {
# Use a different builder for this host
instantiate = inputs.nixpkgs-stable.lib.nixosSystem;
};
}The template includes a comprehensive set of CI checks in templates/default/modules/_example/ci.nix. These checks serve as live documentation, demonstrating and verifying all core features and aspect patterns. Refer to this file for concrete usage examples.
