Den's Fundamental Idea
This section is about how and why Den came to be. You can safely skip this unless you are interested in how Den was shaped.
However you might need to already be familiar with what Dendritic means you might also want to read the FAQ
Den is basically about a single idea:
Being able to share re-usable (parametric) cross-class Nix configurations.
Den was born not to be yet-another zillionth way to wire-up configurations.
The purpose of Den is social more than purely technical.
Den can be used with/without flakes, with/without flake-parts, because it is an exploration on how to take nix module sharing to a higher-level, literaly, since dendritic modules contain one or more of other classic non-dendritic modules.
The history of Den
Before creating Den, my vic/vix infra was made with flake-parts (previously I had used blueprint, snowfall, and before that a couple of my own in-flake tailor-made libs) and I was really happy with dendritic flake-parts.
You can still browse the noden branch as an example of a flake-parts based Dendritic setup.
So I dreamed about having a place akin to the Nix User Repository but for finding Dendritic aspects made by others. That is still an on-going effort named dendrix. At that time there were just a handful of people using Dendritic publicly, and every module even when they followed a dendritic-style were clearly not made with re-usability in mind, user-specifics and host-specifics where always there somehow, or even worse, trying to evaluate a single module demanded to also download all of the owner's particular inputs.
At that time unify - the first dendritic framework I know of- entered my radar, and I really loved it! It was missing a couple of features that I needed in my existing infra, but I loved the <aspect>.<class> transposition that its author invented, and the cleaness of the code at the author's infra was a testament to how good-looking and organized a Dendritic setup could look. I certainly wanted that for mine.
However, before adopting unify for a more terse dendritic syntax than mere flake.modules. I realized that my re-usability problem was not about syntax, not about how things are loaded from filesystem nor how they are wired.
The problem was more about feature composability.
Being an fan of functional programming, the most composable things I know are functions. So I asked myself: What if we had the following:
# Just like any nixos module can be a function:
{ pkgs, ... }: { <nixos-settings> }`
# A dendritic aspect in Den is a function:
{ <context> }: {
nixos = { pkgs, ... }: { <nixos-settings> };
darwin = { pkgs, ... }: { <darwin-settings> };
# any other nix-configuration class
}
This would turn our flake.modules basically into functions.
The result of that exploration was flake-aspects. Which is a dependency free library (usable with/without flakes) that focuses on composability not on wiring/building configurations.
flake-aspects allows for aspects to be parametric by using the Nix __functor pattern, it also allows aspects to be nested unlike the flat-structure we had in flake.modules which caused people to use weird-named modules flake.modules."host/desktop".nixos or similar for string-based-semantics. It also allows declaring dependencies between aspects themselves, not using stringly-typed references like .requires = [ "base" "gaming" ] which was one of the shortcomings early-days unify had.
Some people have found
flake-aspectsenough to implement their own Dendritic setups, or even for mixing with other non-dendritic infra.
Den emerged naturally as framework upon flake-aspects. Den focuses more on structure and on social aspects.
Den, being a framework, tries to answer some specific issues:
-
How to define entities on your infra:
den.hosts.<arch>.<hostName>.users.<userName> -
How to define common schemas (options) for these entities.
den.base.host.options.vpn.port = lib.mkOption -
How to include features that affect all entities
den.default.includes = [ den.provides.home-manager ] -
How a
Hostcan affect itsUsers configurations, and viceversa. -
How to mixin aspects from remote sources and enhance locally defined ones.
den.namespace "omfnix" [ inputs.remote ] -
How to provide features to the community using a common namespace.
{ omfnix, ... }: { omfnix.niri.nixos = ...; }
Based on Den sharable aspects (which depend on a minimal surface syntax for namespaces), I'm planning to create denful. A lazyvim-like configurations distribution that people can include from, just like they do with editor distributions.
And this exploration is all part of the dendrix initiative. Trying to come up with better ways to share configurations even between flakes/no-flakes users. dendrix indexes using import-tree collections instead of flakes, because flakes demand all its inputs to be downloaded, a collection of modules in an import-tree can define the inputs they need by using flake-file and these inputs can be propagated to the final user's flake or npins/unflake.
So, dendrix became something like an index of browsable aspects found in GitHub, my intention was that showing the different aspects each people produces would motivate re-usability, because a major problem I see in the Nix community is most people just copy and paste and/or re-invent the wheel in so many infinite ways.
Den is more about giving to others (creating useful Nix software/configurations), not just about make things work locally.
I've been working over a year on these dendritic libs, but time is our most scarce resource. If you like my work, consider sponsoring