Skip to content

Batteries

Den ships reusable aspect providers under den.batteries (also accessible via the aliases den.provides and den._). Each battery contributes NixOS/Darwin/home-manager modules to hosts and users that include them.

Batteries fall into two categories:

  • Opt-in — you include them explicitly in den.default.includes, den.aspects.<name>.includes, or den.schema.<kind>.includes.
  • Auto-activated — Den activates them via built-in policies. They define new classes or integration layers that work without explicit inclusion. These are not values under den.batteries — there is nothing to include; their headings below name the class they add.

Creates OS-level user accounts (users.users.<name>) with a home directory (/Users/<name> on Darwin, /home/<name> elsewhere), plus isNormalUser on NixOS. Also sets home.username and home.homeDirectory for Home Manager. Works on NixOS, Darwin, and standalone Home Manager homes.

Opt-in.

den.default.includes = [ den.batteries.define-user ];

Sets the system hostname from den.hosts.<name>.hostName. Works on NixOS and Darwin.

Opt-in.

den.default.includes = [ den.batteries.hostname ];

Provides an os convenience class whose contents land in the host’s own OS class — nixos on NixOS hosts, darwin on Darwin hosts. This lets you write platform-agnostic host configuration without duplicating it across classes.

Auto-activated. The os-to-host policy is in den.default, so it fires in every scope that binds a host — os content on a user aspect reaches that user’s host too. Hosts of any other class (and standalone homes) ignore os content.

den.aspects.my-host = {
os.networking.hostName = "foo";
};

Provides a user class that forwards settings into the host’s users.users.<userName> at OS level. Instead of writing the full nixos.users.users.alice path, you write directly into the user class. Inside a user module, config is the host’s OS config, also available as osConfig.

Auto-activated through the user-to-host policy in den.default. user is the default of users.<name>.classes, so a user gets it unless you replace that list.

den.aspects.alice.user = { pkgs, ... }: {
packages = [ pkgs.hello ];
extraGroups = [ "wheel" ];
};

Marks a user as the primary (admin-level) user. On NixOS, adds wheel and networkmanager groups. On Darwin, sets system.primaryUser. On WSL, sets defaultUser.

Opt-in.

den.aspects.alice.includes = [ den.batteries.primary-user ];

Sets the user’s login shell at both OS and Home Manager levels. Enables programs.<shell>.enable and sets users.users.<name>.shell.

Opt-in. Takes a shell name as argument.

den.aspects.alice.includes = [
(den.batteries.user-shell "fish")
];

Projects user-relevant classes (like homeManager) from the host’s aspect tree onto users who opt in. Any homeManager key defined in the host aspect is forwarded to the user’s home-manager evaluation.

Opt-in.

den.aspects.tux.includes = [ den.batteries.host-aspects ];

Configures automatic TTY1 login on NixOS via a systemd getty override. NixOS only.

Opt-in. Takes a username as argument.

den.aspects.laptop.includes = [
(den.batteries.tty-autologin "alice")
];

Configures automatic TTY1 login on NixOS VMs via a systemd getty override. NixOS VMs only.

Opt-in. Takes a username as argument.

den.aspects.laptop.includes = [
(den.batteries.vm-autologin "alice")
];

Enables WSL support on NixOS using the NixOS-WSL project. For an enabled host it imports the NixOS-WSL module, sets wsl.enable = true, resolves a wsl-host entity, and routes the wsl class into the host’s wsl.* options.

Auto-activated when host.wsl.enable = true on a nixos host. Requires inputs.nixos-wsl, or set host.wsl.module to the NixOS-WSL module yourself.

den.hosts.x86_64-linux.igloo.wsl.enable = true;
# or on every host (only nixos hosts are affected)
den.schema.host.wsl.enable = true;
# `wsl` class content becomes the host's `wsl.*` NixOS options
den.aspects.igloo.wsl.startMenuLaunchers = true;

den.batteries.primary-user sets wsl.defaultUser through this class.

A generic forwarding primitive that creates custom Nix classes by routing module contents from one class into a target submodule path. The homeManager, hjem, and maid integrations use it internally. (The os, user, and wsl classes use the lighter den.lib.policy.route instead — see Policies.)

Opt-in. Used when building custom classes. See the Custom Classes guide.

den.batteries.forward {
each = lib.singleton user;
fromClass = _: "myClass";
intoClass = _: host.class;
intoPath = _: [ "some" "path" ];
fromAspect = _: user.aspect;
};

Recursively imports plain .nix files, taking the class from the directory name: every _<class>/ directory under the given root (_nixos/, _darwin/, _homeManager/, or any other class) is imported into <class>. Useful for migrating existing configurations.

Opt-in. Requires inputs.import-tree. The provides.host/user/home forms look in <root>/<entity name>/, so ./hosts above reads ./hosts/<host>/_nixos/ and so on.

# Import per host
den.schema.host.includes = [
(den.batteries.import-tree.provides.host ./hosts)
];
# Import per user
den.schema.user.includes = [
(den.batteries.import-tree.provides.user ./users)
];
# Import per standalone home
den.schema.home.includes = [
(den.batteries.import-tree.provides.home ./homes)
];
# Import for a specific aspect
den.aspects.laptop.includes = [
(den.batteries.import-tree ./disko)
];

Exposes lib, inputs, and den to aspect pipeline functions and to class modules (nixos, homeManager, …) — the generic (non-flake-parts) counterpart of inputs'/self'. A parametric aspect or a class module can then destructure these alongside entity args:

den.default.includes = [ den.batteries.flake-scope ];
den.aspects.my-aspect = { host, inputs, lib, ... }: {
nixos = { pkgs, ... }: {
environment.etc."version".text = inputs.nixpkgs.lib.version;
};
};

Values are tagged pipelineOnly (class-wins collision policy), so class-module-native values (e.g. NixOS’s own lib from _module.args) win silently over the flake-scope ones.

Opt-in.


The three home environments share one activation rule: a host enables one when at least one of its users lists the class in users.<name>.classes. Writing a homeManager (or hjem, maid) key on an aspect is not enough — classes defaults to [ "user" ].

den.hosts.x86_64-linux.igloo.users.alice.classes = [ "homeManager" ];
# or for every user
den.schema.user.classes = lib.mkDefault [ "homeManager" ];

Each adds a pair of host options under its option path (home-manager, hjem, nix-maid): enable (defaults to “some user has the class”) and module (defaults to the module from the flake input). Set module to use a pinned or patched module, or to supply one without the flake input.

Integrates home-manager as a user environment class. Imports the appropriate home-manager NixOS or Darwin module and merges home-manager.users.<name> from each user’s homeManager class. Inside a homeManager module, osConfig is the host’s config.

Auto-activated on NixOS and Darwin hosts (see above). Requires inputs.home-manager unless host.home-manager.module is set. Aspects in den.schema.hm-host.includes are included on every host that enables home-manager.

den.aspects.alice.homeManager = {
programs.git.enable = true;
};

Integrates hjem as an alternative home environment. Imports hjem’s NixOS or Darwin module and merges hjem.users.<name> from each user’s hjem class.

Auto-activated on NixOS and Darwin hosts (see above). Requires inputs.hjem unless host.hjem.module is set.

den.aspects.alice.hjem = { pkgs, ... }: {
packages = [ pkgs.ripgrep ];
};

Integrates nix-maid as an alternative home environment. NixOS only. Merges configuration into users.users.<name>.maid for each user’s maid class.

Auto-activated on NixOS hosts (see above). Requires inputs.nix-maid unless host.nix-maid.module is set.

den.aspects.alice.maid = {
programs.helix.enable = true;
};

Allows specific unfree packages by name via nixpkgs.config.allowUnfreePredicate. Emits into nixos, darwin, and homeManager. When included on a user, the names are also allowed on the host’s OS config, so home-manager.useGlobalPkgs = true and users with only the user class work too. The predicate builder is automatically included in den.default.

Opt-in. Takes a list of package names as argument.

den.aspects.laptop.includes = [
(den.batteries.unfree [ "nvidia-x11" "steam" ])
];

Allows specific insecure packages by name and version via nixpkgs.config.permittedInsecurePackages. Works for any class (nixos, darwin, homeManager). The predicate builder is automatically included in den.default.

Opt-in. Takes a list of package name-version strings as argument.

den.aspects.laptop.includes = [
(den.batteries.insecure [ "openssl-1.1.1w" ])
];

These batteries require flake-parts as the module system.

Provides inputs' (the flake’s inputs with system pre-selected) as a top-level module argument. Contextual: configures the appropriate class depending on whether it is included in a host, user, or home aspect.

Opt-in.

den.default.includes = [ den.batteries.inputs' ];

Provides self' (the flake’s self outputs with system pre-selected) as a top-level module argument. Contextual: configures the appropriate class depending on whether it is included in a host, user, or home aspect.

Opt-in.

den.default.includes = [ den.batteries.self' ];

Apply batteries to all hosts, users, and homes:

den.default.includes = [
den.batteries.define-user
den.batteries.hostname
den.batteries.inputs'
];

Apply batteries to specific aspects:

den.aspects.alice.includes = [
den.batteries.primary-user
(den.batteries.user-shell "zsh")
(den.batteries.unfree [ "vscode" ])
];

Apply batteries to all entities of a kind:

den.schema.user.includes = [
den.batteries.define-user
];

Batteries compose freely with inline configuration:

den.aspects.my-admin = {
includes = [
den.batteries.primary-user
(den.batteries.user-shell "fish")
{ nixos.security.sudo.wheelNeedsPassword = false; }
];
};
ContributeCommunitySponsor