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
at 2034ed6fe991b58aa3c23bfc6501dff33566aa88 205 lines 6.3 kB view raw
1{ 2 inputs, 3 lib, 4 config, 5 ... 6}: 7let 8 inherit (config) den; 9 10 hostsOption = lib.mkOption { 11 description = "den hosts definition"; 12 default = { }; 13 type = lib.types.attrsOf systemType; 14 }; 15 16 systemType = lib.types.submodule ( 17 { name, ... }: 18 { 19 freeformType = lib.types.attrsOf (hostType name); 20 } 21 ); 22 23 hostType = 24 system: 25 lib.types.submodule ( 26 { name, config, ... }: 27 { 28 freeformType = lib.types.attrsOf lib.types.anything; 29 options = { 30 name = strOpt "host configuration name" name; 31 hostName = strOpt "Network hostname" config.name; 32 system = strOpt "platform system" system; 33 class = strOpt "os-configuration nix class for host" ( 34 if lib.hasSuffix "darwin" config.system then "darwin" else "nixos" 35 ); 36 aspect = strOpt "main aspect name of <class>" config.name; 37 description = strOpt "host description" "${config.class}.${config.hostName}@${config.system}"; 38 users = lib.mkOption { 39 description = "user accounts"; 40 default = { }; 41 type = lib.types.attrsOf userType; 42 }; 43 instantiate = lib.mkOption { 44 description = '' 45 Function used to instantiate the OS configuration. 46 47 Depending on class, defaults to: 48 `darwin`: inputs.darwin.lib.darwinSystem 49 `nixos`: inputs.nixpkgs.lib.nixosSystem 50 `systemManager`: inputs.system-manager.lib.makeSystemConfig 51 52 Set explicitly if you need: 53 54 - a custom input name, eg, nixos-unstable. 55 - adding specialArgs when absolutely required. 56 ''; 57 example = lib.literalExpression "inputs.nixpkgs.lib.nixosSystem"; 58 type = lib.types.unspecified; 59 default = 60 { 61 nixos = inputs.nixpkgs.lib.nixosSystem; 62 darwin = inputs.darwin.lib.darwinSystem; 63 systemManager = inputs.system-manager.lib.makeSystemConfig; 64 } 65 .${config.class}; 66 }; 67 intoAttr = lib.mkOption { 68 description = '' 69 Flake attr where to add the named result of this configuration. 70 flake.<intoAttr>.<name> 71 72 Depending on class, defaults to: 73 `darwin`: darwinConfigurations 74 `nixos`: nixosConfigurations 75 `systemManager`: systemConfigs 76 ''; 77 example = lib.literalExpression ''"nixosConfigurations"''; 78 type = lib.types.str; 79 default = 80 { 81 nixos = "nixosConfigurations"; 82 darwin = "darwinConfigurations"; 83 systemManager = "systemConfigs"; 84 } 85 .${config.class}; 86 }; 87 mainModule = lib.mkOption { 88 internal = true; 89 visible = false; 90 readOnly = true; 91 type = lib.types.deferredModule; 92 default = mainModule config "OS" "host"; 93 }; 94 }; 95 } 96 ); 97 98 userType = lib.types.submodule ( 99 { name, config, ... }: 100 { 101 freeformType = lib.types.attrsOf lib.types.anything; 102 options = { 103 name = strOpt "user configuration name" name; 104 userName = strOpt "user account name" config.name; 105 class = strOpt "home management nix class" "homeManager"; 106 aspect = strOpt "main aspect name" config.name; 107 }; 108 } 109 ); 110 111 strOpt = 112 description: default: 113 lib.mkOption { 114 type = lib.types.str; 115 inherit description default; 116 }; 117 118 homesOption = lib.mkOption { 119 description = "den standalone home-manager configurations"; 120 default = { }; 121 type = lib.types.attrsOf homeSystemType; 122 }; 123 124 homeSystemType = lib.types.submodule ( 125 { name, ... }: 126 { 127 freeformType = lib.types.attrsOf (homeType name); 128 } 129 ); 130 131 homeType = 132 system: 133 lib.types.submodule ( 134 { name, config, ... }: 135 { 136 freeformType = lib.types.attrsOf lib.types.anything; 137 options = { 138 name = strOpt "home configuration name" name; 139 userName = strOpt "user account name" config.name; 140 system = strOpt "platform system" system; 141 class = strOpt "home management nix class" "homeManager"; 142 aspect = strOpt "main aspect name" config.name; 143 description = strOpt "home description" "home.${config.userName}@${config.system}"; 144 instantiate = lib.mkOption { 145 description = '' 146 Function used to instantiate the home configuration. 147 148 Depending on class, defaults to: 149 `homeManager`: inputs.home-manager.lib.homeManagerConfiguration 150 151 Set explicitly if you need: 152 153 - a custom input name, eg, home-manager-unstable. 154 - adding extraSpecialArgs when absolutely required. 155 ''; 156 example = lib.literalExpression "inputs.home-manager.lib.homeManagerConfiguration"; 157 type = lib.types.unspecified; 158 default = 159 { 160 homeManager = inputs.home-manager.lib.homeManagerConfiguration; 161 } 162 .${config.class}; 163 }; 164 intoAttr = lib.mkOption { 165 description = '' 166 Flake attr where to add the named result of this configuration. 167 flake.<intoAttr>.<name> 168 169 Depending on class, defaults to: 170 `homeManager`: homeConfigurations 171 ''; 172 example = lib.literalExpression ''"homeConfigurations"''; 173 type = lib.types.str; 174 default = 175 { 176 homeManager = "homeConfigurations"; 177 } 178 .${config.class}; 179 }; 180 mainModule = lib.mkOption { 181 internal = true; 182 visible = false; 183 readOnly = true; 184 type = lib.types.deferredModule; 185 default = mainModule config "HM" "home"; 186 }; 187 }; 188 } 189 ); 190 191 mainModule = 192 from: intent: name: 193 let 194 asp = den.aspects.${from.aspect}; 195 ctx = { 196 ${intent} = asp; 197 ${name} = from; 198 }; 199 mod = (asp ctx).resolve { inherit (from) class; }; 200 in 201 mod; 202in 203{ 204 inherit hostsOption homesOption; 205}