den and vic's dendritic libs made for you with Love++ and AI--. If you like my work, consider sponsoring
|
At its core, Den is a library built on flake-aspects for activating configuration-aspects via context-transformation pipelines. On top of the library, Den provides a framework for the NixOS/nix-Darwin/Home-Manager Nix domains. Den embraces your Nix choices and does not impose itself. All parts of Den are optional and replaceable. Works with your current setup, with/without flakes, flake-parts or any other Nix module system. default: +flake-file +flake-parts +home-manager minimal: +flakes -flake-parts -home-manager noflake: -flakes +npins +lib.evalModules +nix-maid example: cross-platform ci: Each feature tested as code examples bogus: Isolated test for bug reproduction
❄️ Try it: nix run github:vic/den
nix flake init -t github:vic/den && nix run .#vm |
Den takes the Dendritic pattern to a whole new level, and I cannot imagine going back.
— @adda - Very early Den adopter after using Dendritic flake-parts and Unify.
I’m super impressed with den so far, I’m excited to try out some new patterns that Unify couldn’t easily do.
— @quasigod - Unify dendritic-framework author on adopting Den.
Massive work you did here!
— @drupol - Author of “Flipping the Configuration Matrix” Dendritic blog post.
Thanks for the awesome library and the support for non-flakes… it’s positively brilliant!. I really hope this gets wider adoption.
— @vczf - At den matrix channel.
# Define hosts, users & homes
den.hosts.x86_64-linux.lap.users.vic = {};
den.hosts.aarch64-darwin.mac.users.vic = {};
den.homes.aarch64-darwin.vic = {};$ nixos-rebuild switch --flake .#lap
$ darwin-rebuild switch --flake .#mac
$ home-manager switch --flake .#vic# extensible base modules for common, typed schemas
den.base.user = { user, lib, ... }: {
config.classes =
if user.userName == "vic" then [ "hjem" "maid" ]
else lib.mkDefault [ "homeManager" ];
options.mainGroup = lib.mkOption { default = user.userName; };
};# modules/my-laptop.nix
{ den, inputs, ... }: {
den.aspects.my-laptop = {
# re-usable configuration aspects
includes = [ den.aspects.work-vpn ];
# regular nixos/darwin modules or any other Nix class
nixos = { pkgs, ... }: { imports = [ inputs.disko.nixosModules.disko ]; };
darwin = { pkgs, ... }: { imports = [ inputs.nix-homebrew.darwinModules.nix-homebrew ]; };
# Den `os` Nix class forwards to both nixos and darwin
os = { pkgs, ... }: {
networking.hostName = "yavanna";
environment.packages = [ pkgs.direnv ];
};
# host can contribute to its users' environment
homeManager.programs.vim.enable = true;
};
}# modules/vic.nix
{ den, ... }: {
den.aspects.vic = {
# supports multiple home environments
homeManager = { pkgs, ... }: { };
hjem.files.".envrc".text = "use flake ~/hk/home";
maid.kconfig.settings.kwinrc.Desktops.Number = 3;
# user can contribute configurations to all hosts it lives on
darwin.services.karabiner-elements.enable = true;
# user class forwards into {nixos/darwin}.users.users.<userName>
user = { pkgs, ... }: {
packages = [ pkgs.helix ];
description = "oeiuwq";
};
includes = [
den.provides.primary-user # re-usable batteries
(den.provides.user-shell "fish") # parametric aspects
den.aspects.tiling-wm # your own aspects
den.aspects.gaming.provides.emulators
];
};
}# Custom Nix classes.
# Example: A class for role-based configuration between users and hosts
roleClass =
{ host, user }:
{ class, aspect-chain }:
den._.forward {
each = lib.intersectLists (host.roles or []) (user.roles or []);
fromClass = lib.id;
intoClass = _: host.class;
intoPath = _: [ ];
fromAspect = _: lib.head aspect-chain;
};
den.ctx.user.includes = [ roleClass ];
den.hosts.x86_64-linux.igloo = {
roles = [ "devops" "gaming" ];
users = {
alice.roles = [ "gaming" ];
bob.roles = [ "devops" ];
};
};
den.aspects.alice = {
# enabled when host supports gaming role
gaming = { pkgs, ... }: { programs.steam.enable = true; };
# enabled when host supports devops role
devops = { pkgs, ... }: { virtualisation.podman.enable = true; };
};# Forward guards allow feature-detection without mkIf/mkMerge cluttering.
# Aspects use the `persys` class without any conditional. And guard guarantees
# settings are applied **only** when impermanence module has been imported.
persys = { host }: den._.forward {
each = lib.singleton true;
fromClass = _: "persys";
intoClass = _: host.class;
intoPath = _: [ "environment" "persistance" "/nix/persist/system" ];
fromAspect = _: den.aspects.${host.aspect};
guard = { options, config, ... }: options ? environment.persistance;
};
# enable on all hosts
den.ctx.host.includes = [ persys ];
# aspects just attach config to custom class
den.aspects.my-laptop.persys.hideMounts = true;