a flake module to ease creating and managing multiple hosts in your nix flake.
at main 7.6 kB view raw
1{ 2 lib, 3 inputs, 4 config, 5 withSystem, 6 ... 7}: 8let 9 inherit (builtins) concatLists attrNames; 10 inherit (lib.options) mkOption mkEnableOption literalExpression; 11 inherit (lib) types; 12 13 inherit (import ./lib.nix { inherit lib inputs withSystem; }) 14 constructSystem 15 mkHosts 16 buildHosts 17 ; 18 19 cfg = config.easy-hosts; 20 21 mkBasicParams = name: { 22 modules = mkOption { 23 # we really expect a list of paths but i want to accept lists of lists of lists and so on 24 # since they will be flattened in the final function that applies the settings 25 type = types.listOf types.deferredModule; 26 default = [ ]; 27 description = "${name} modules to be included in the system"; 28 example = literalExpression '' 29 [ ./hardware-configuration.nix ./networking.nix ] 30 ''; 31 }; 32 33 specialArgs = mkOption { 34 type = types.lazyAttrsOf types.raw; 35 default = { }; 36 description = "${name} special arguments to be passed to the system"; 37 example = literalExpression '' 38 { foo = "bar"; } 39 ''; 40 }; 41 }; 42in 43{ 44 # module for flake-parts 45 _class = "flake"; 46 47 options = { 48 easy-hosts = { 49 autoConstruct = lib.mkEnableOption "Automatically construct hosts"; 50 51 path = mkOption { 52 type = types.nullOr types.path; 53 default = null; 54 example = literalExpression "./hosts"; 55 description = "Path to the directory containing the host files"; 56 }; 57 58 onlySystem = mkOption { 59 type = types.nullOr types.str; 60 default = null; 61 example = literalExpression "aarch64-darwin"; 62 description = "Only construct the hosts with for this platform"; 63 }; 64 65 shared = mkBasicParams "Shared"; 66 67 perClass = mkOption { 68 default = _: { 69 modules = [ ]; 70 specialArgs = { }; 71 }; 72 defaultText = '' 73 class: { 74 modules = [ ]; 75 specialArgs = { }; 76 }; 77 ''; 78 79 type = types.functionTo ( 80 types.submodule { 81 options = mkBasicParams "Per class"; 82 } 83 ); 84 85 example = literalExpression '' 86 class: { 87 modules = [ 88 { system.nixos.label = class; } 89 ]; 90 91 specialArgs = { }; 92 } 93 ''; 94 95 description = "Per class settings"; 96 }; 97 98 perArch = mkOption { 99 default = _: { 100 modules = [ ]; 101 specialArgs = { }; 102 }; 103 defaultText = '' 104 arch: { 105 modules = [ ]; 106 specialArgs = { }; 107 }; 108 ''; 109 110 type = types.functionTo ( 111 types.submodule { 112 options = mkBasicParams "Per arch"; 113 } 114 ); 115 116 example = literalExpression '' 117 arch: { 118 modules = [ 119 { system.nixos.label = arch; } 120 ]; 121 122 specialArgs = { }; 123 } 124 ''; 125 126 description = "Per arch settings"; 127 }; 128 129 perTag = mkOption { 130 default = _: { 131 modules = [ ]; 132 specialArgs = { }; 133 }; 134 defaultText = '' 135 tag: { 136 modules = [ ]; 137 specialArgs = { }; 138 }; 139 ''; 140 141 type = types.functionTo ( 142 types.submodule { 143 options = mkBasicParams "Per tag"; 144 } 145 ); 146 147 example = literalExpression '' 148 let 149 tagModule = { 150 laptop = ./modules/laptop; 151 gaming = ./modules/gaming; 152 }; 153 in 154 tag: { 155 modules = [ tagModule.''${tag} ]; 156 157 specialArgs = { }; 158 } 159 ''; 160 161 description = "Per tag settings"; 162 }; 163 164 additionalClasses = mkOption { 165 default = { }; 166 type = types.attrsOf types.str; 167 description = "Additional classes and their respective mappings to already existing classes"; 168 example = lib.literalExpression '' 169 { 170 wsl = "nixos"; 171 rpi = "nixos"; 172 macos = "darwin"; 173 } 174 ''; 175 }; 176 177 hosts = mkOption { 178 description = "Hosts to be defined by the flake"; 179 180 default = { }; 181 182 type = types.attrsOf ( 183 types.submodule ( 184 { name, config, ... }: 185 { 186 options = { 187 nixpkgs = mkOption { 188 type = types.anything; 189 default = inputs.nixpkgs or (throw "cannot find nixpkgs input"); 190 defaultText = literalExpression "inputs.nixpkgs"; 191 example = literalExpression "inputs.nixpkgs-unstable"; 192 description = "The nixpkgs flake to be used for the host"; 193 }; 194 195 nix-darwin = mkOption { 196 type = types.anything; 197 default = inputs.darwin or inputs.nix-darwin or null; 198 defaultText = literalExpression "inputs.darwin or inputs.nix-darwin"; 199 example = literalExpression "inputs.my-nix-darwin"; 200 description = "The nix-darwin flake to be used for the host"; 201 }; 202 203 # keep this up to date with 204 # https://github.com/NixOS/nixpkgs/blob/75a43236cfd40adbc6138029557583eb77920afd/lib/systems/flake-systems.nix#L1 205 arch = mkOption { 206 type = types.enum [ 207 "x86_64" 208 "aarch64" 209 "armv6l" 210 "armv7l" 211 "i686" 212 "powerpc64le" 213 "riscv64" 214 ]; 215 default = "x86_64"; 216 example = "aarch64"; 217 description = "The architecture of the host"; 218 }; 219 220 class = mkOption { 221 type = types.enum (concatLists [ 222 [ 223 "nixos" 224 "darwin" 225 "iso" 226 ] 227 228 (attrNames cfg.additionalClasses) 229 ]); 230 default = "nixos"; 231 example = "darwin"; 232 description = "The class of the host"; 233 }; 234 235 tags = mkOption { 236 type = types.listOf types.str; 237 default = [ ]; 238 example = [ "laptop" ]; 239 description = "Extra tags for the host"; 240 }; 241 242 system = mkOption { 243 type = types.str; 244 default = constructSystem cfg.additionalClasses config.arch config.class; 245 example = "aarch64-darwin"; 246 description = "The system to be used for the host"; 247 internal = true; # this should ideally be set by easy-hosts 248 }; 249 250 path = mkOption { 251 type = types.nullOr types.path; 252 default = null; 253 example = literalExpression "./hosts/myhost"; 254 description = "Path to the directory containing the host files"; 255 }; 256 257 deployable = mkEnableOption "Is this host deployable" // { 258 default = false; 259 }; 260 } 261 // (mkBasicParams name); 262 } 263 ) 264 ); 265 }; 266 }; 267 }; 268 269 config = { 270 # if the user has made it such that they want the hosts to be constructed automatically 271 # i.e. from the file paths then we will do that 272 easy-hosts.hosts = lib.mkIf cfg.autoConstruct (buildHosts cfg); 273 274 flake = mkHosts cfg; 275 }; 276}