Modular, context-aware and aspect-oriented dendritic Nix configurations. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ den.oeiuwq.com
configurations den dendritic nix aspect oriented

Make intoAttr a path of flake output (#211)

Fixes #210

authored by oeiuwq.com and committed by

GitHub 26b263bc 3d9be07e

+53 -37
+18 -1
docs/src/content/docs/guides/declare-hosts.mdx
··· 34 34 hostName = "yavanna"; # default: my-laptop 35 35 class = "nixos"; # default: guessed from platform 36 36 aspect = "workstation"; # default: my-laptop 37 + intoAttr = [ "nixosConfigurations" "yavanna" ]; # default: [ "nixosConfigurations" "my-laptop" ] 37 38 users.vic = { 38 39 userName = "vborja"; # default: vic 39 40 aspect = "oeiuwq"; # default: vic ··· 54 55 55 56 ```console 56 57 home-manager switch --flake .#vic 58 + ``` 59 + 60 + The following standalone Home-Manager example showcases 61 + custom input channels and output attribute. 62 + 63 + ```nix 64 + den.homes.x86_64-linux.tux-at-igloo = { 65 + intoAttr = [ "homeConfigurations" "tux@igloo" ]; 66 + userName = "tux"; 67 + instantiate = { pkgs, modules }: 68 + inputs.home-manager-stable.lib.homeManagerConfiguration { 69 + inherit modules; 70 + pkgs = inputs.self.nixpkgs-stable.legacyPackages.x86_64-linux; 71 + extraSpecialArgs.osConfig = inputs.self.nixosConfigurations.igloo.config; 72 + }; 73 + }; 57 74 ``` 58 75 59 76 ## Multiple Hosts, Shared Users ··· 118 135 119 136 ```nix 120 137 den.hosts.x86_64-linux.wsl-box = { 121 - intoAttr = "wslConfigurations"; 138 + intoAttr = [ "wslConfigurations" "my-wsl" ]; 122 139 users.wsl = { }; 123 140 }; 124 141 ```
+10 -11
docs/src/content/docs/reference/output.mdx
··· 27 27 1. **Resolves the main module** — applies the context pipeline to produce a 28 28 single Nix module containing all class-specific configurations 29 29 2. **Calls the instantiate function** — passes the module to the platform builder 30 - 3. **Places the result** — puts it at `flake.<intoAttr>.<name>` 30 + 3. **Places the result** — puts it at `flake.<intoAttr>` 31 31 32 32 ## OS Configurations 33 33 ··· 64 64 65 65 | Class | Default `intoAttr` | 66 66 |-------|-------------------| 67 - | `nixos` | `nixosConfigurations` | 68 - | `darwin` | `darwinConfigurations` | 69 - | `systemManager` | `systemConfigs` | 70 - | `homeManager` | `homeConfigurations` | 67 + | `nixos` | `nixosConfigurations.<name>` | 68 + | `darwin` | `darwinConfigurations.<name>` | 69 + | `systemManager` | `systemConfigs.<name>` | 70 + | `homeManager` | `homeConfigurations.<name>` | 71 71 72 72 Override `intoAttr` to place configs elsewhere: 73 73 74 74 ```nix 75 - den.hosts.x86_64-linux.my-wsl = { 76 - intoAttr = "wslConfigurations"; 77 - users.vic = { }; 75 + den.homes.x86_64-linux.tux = { 76 + intoAttr = [ "homeConfigurations" "tux@igloo" ]; 78 77 }; 79 78 ``` 80 79 ··· 87 86 graph TD 88 87 Entity["host / home definition"] 89 88 Entity -->|"ctx.host / ctx.home"| Intent["Apply context pipeline"] 90 - Intent -->|"aspect.resolve { class }"| Module["Single Nix module"] 91 - Module --> Instantiate["instantiate function"] 92 - Instantiate --> Output["flake.<intoAttr>.<name>"] 89 + Intent -->|"aspect.resolve { class }"| Module["Obtain Nix module"] 90 + Module --> Instantiate["instantiate configuration"] 91 + Instantiate --> Output["set value into flake.<intoAttr>"] 93 92 ``` 94 93 95 94 The context pipeline collects contributions from:
+20 -8
modules/_types.nix
··· 76 76 `nixos`: nixosConfigurations 77 77 `systemManager`: systemConfigs 78 78 ''; 79 - example = lib.literalExpression ''"nixosConfigurations"''; 80 - type = lib.types.str; 79 + example = lib.literalExpression ''[ "nixosConfigurations" hostName ]''; 80 + type = lib.types.listOf lib.types.str; 81 81 default = 82 82 { 83 - nixos = "nixosConfigurations"; 84 - darwin = "darwinConfigurations"; 85 - systemManager = "systemConfigs"; 83 + nixos = [ 84 + "nixosConfigurations" 85 + config.name 86 + ]; 87 + darwin = [ 88 + "darwinConfigurations" 89 + config.name 90 + ]; 91 + systemManager = [ 92 + "systemConfigs" 93 + config.name 94 + ]; 86 95 } 87 96 .${config.class}; 88 97 }; ··· 187 196 Depending on class, defaults to: 188 197 `homeManager`: homeConfigurations 189 198 ''; 190 - example = lib.literalExpression ''"homeConfigurations"''; 191 - type = lib.types.str; 199 + example = lib.literalExpression ''[ "homeConfigurations" userName ]''; 200 + type = lib.types.listOf lib.types.str; 192 201 default = 193 202 { 194 - homeManager = "homeConfigurations"; 203 + homeManager = [ 204 + "homeConfigurations" 205 + config.name 206 + ]; 195 207 } 196 208 .${config.class}; 197 209 };
+5 -17
modules/config.nix
··· 9 9 builder: cfg: 10 10 let 11 11 items = map builtins.attrValues (builtins.attrValues cfg); 12 - buildItem = item: { 13 - inherit (item) name intoAttr; 14 - value = builder item; 15 - }; 12 + buildItem = item: lib.setAttrByPath item.intoAttr (builder item); 13 + built = map buildItem (lib.flatten items); 16 14 in 17 - map buildItem (lib.flatten items); 15 + built; 18 16 19 17 osConfiguration = 20 18 host: ··· 32 30 modules = [ home.mainModule ]; 33 31 }; 34 32 35 - cfgs = (build osConfiguration config.den.hosts) ++ (build homeConfiguration config.den.homes); 36 - 37 - outputs = 38 - acc: item: 39 - acc 40 - // { 41 - ${item.intoAttr} = (acc.${item.intoAttr} or { }) // { 42 - ${item.name} = item.value; 43 - }; 44 - }; 45 - 33 + configs = (build osConfiguration config.den.hosts) ++ (build homeConfiguration config.den.homes); 46 34 in 47 35 { 48 - flake = lib.foldl outputs { } cfgs; 36 + config.flake = lib.mkMerge configs; 49 37 }