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 microvm: MicroVM runnable-pkg and guests. custom ctx-pipeline. example: cross-platform ci: Each feature tested as code examples bogus: Isolated test for bug reproduction
❄️ Try it: # Run virtio MicroVM from templates/microvm
nix run github:vic/den?dir=templates/microvm#runnable-microvm# Run qemu VM from templates/example
nix run github:vic/den |
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- Author of Unify dendritic-framework, 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-lib:matrix.orgchannel.
Den is a playground for some very advanced concepts. I’m convinced that some of its ideas will play a role in future Nix areas. In my opinion there are some raw diamonds in Den.
—@Doc-Steve- Author of Dendritic Design Guide
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.schema.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. Den batteries and yours.
includes = [ den.provides.hostname 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 ]; };
# Custom Nix classes. `os` applies to both nixos and darwin. contributed by @Risa-G.
# See https://den.oeiuwq.com/guides/custom-classes/#user-contributed-examples
os = { pkgs, ... }: {
environment.systemPackages = [ pkgs.direnv ];
};
# host can contribute default home environments to all its users.
homeManager.programs.vim.enable = true;
};
}# modules/vic.nix
{ den, ... }: {
den.aspects.vic = {
# supports multiple home environments, eg: for migrating from homeManager.
homeManager = { pkgs, ... }: { };
hjem.files.".envrc".text = "use flake ~/hk/home";
maid.kconfig.settings.kwinrc.Desktops.Number = 3;
# user can contribute OS-configurations to any host 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 classes is how Den implements homeManager, hjem, wsl, microvm support. You can use the very same mechanism to create your own 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 both support gaming role
gaming = { pkgs, ... }: { programs.steam.enable = true; };
};
den.aspects.bob = {
# enabled when both support devops role
devops = { pkgs, ... }: { virtualisation.podman.enable = true; };
# not enabled at igloo host (bob missing gaming role on that host)
gaming = {};
};Forward guards allow feature-detection without mkIf/mkMerge cluttering.
Aspects can simply assign configurations into a class (here persys)
from any file, without any mkIf/mkMerge cluttering. The logic for
determining if the class takes effect is defined at a single place.
Example inspired by @Doc-Steve
# 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;See example template/microvm for an example
of custom den.ctx and den.schema extensions for supporting
Declarative MicroVM guests with automatic host-shared /nix/store.
den.hosts.x86_64-linux.guest = {};
den.hosts.x86_64-linux.host = {
microvm.guests = [ den.hosts.x86_64-linux.guest ];
};
den.aspects.guest = {
# propagated into host.nixos.microvm.vms.<name>;
microvm.autostart = true;
# guest supports all Den features.
includes = [ den.provides.hostname ];
# As MicroVM guest propagated into host.nixos.microvm.vms.<name>.config;
nixos = { pkgs, ... }: { environment.systemPackages = [ pkgs.hello ]; };
};