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