From cc2f42fbdfab6d87dd4432ce19f9661178db825d Mon Sep 17 00:00:00 2001 From: Archit Gupta Date: Sun, 14 Jan 2024 01:29:16 -0800 Subject: [PATCH] Enable simpler config of nixos/home configurations Instead of having to call the configuration generation functions, the params can just be set, and the functions will be called automatically with additional useful settings automatically set. --- API_GUIDE.md | 79 ++++++++++++++------------ builtinModules/homeConfigurations.nix | 54 +++++++++++++----- builtinModules/nixosConfigurations.nix | 56 ++++++++++++------ tests/default.nix | 15 ++++- 4 files changed, 134 insertions(+), 70 deletions(-) diff --git a/API_GUIDE.md b/API_GUIDE.md index ff7ba13..2694e07 100644 --- a/API_GUIDE.md +++ b/API_GUIDE.md @@ -710,24 +710,23 @@ To write the above using autoloads, can use the following: { hello, ... }: x: hello; ``` -### nixosConfigurations and homeConfigurations +### nixosConfigurations -The `nixosConfigurations` and `homeConfigurations` attributes let you set -outputs for NixOS systems and home-manager users. +The `nixosConfigurations` attribute lets you set outputs for NixOS systems and +home-manager users. -They should be set to an attribute set of respective configurations. +It should be set to an attribute set. Each value should be a set of +`nixpkgs.lib.nixosSystem` args, the result of calling `nixpkgs.lib.nixosSystem`, +or a function that takes `moduleArgs` and returns one of the prior. -Alternatively, the configurations can be functions, in which case those -functions will be passed `moduleArgs` and must return a standard -configuration (this is useful when using autoloads with the `nixDir` feature). +When using a set of `nixpkgs.lib.nixosSystem` args, NixOS modules will have +access to a `flake` module arg equivalent to `moduleArgs` plus `inputs'` and +`outputs'`. Flakelight's pkgs attributes, `withOverlays`, and `packages` will +also be available in the NixOS instance's pkgs. -The `propagationModule` config provides a module to apply flakelight -configuration to other module systems such as NixOS and home-manager. Applying -this module will give modules in the nested modules system access to a `flake` -module arg that contains the flakelight module args as well as `inputs'` and -`outputs'`. Flakelight's packages configuration will also be applied to the pkgs -of the nested module system (This includes flakelight's additional pkgs values, -`withOverlays` overlays, and the flake's packages. +When using the result of calling `nixpkgs.lib.nixosSystem`, the +`config.propogationModule` value can be used as a NixOS module to gain the above +benefits. For example: @@ -736,44 +735,54 @@ For example: inputs.flakelight.url = "github:nix-community/flakelight"; outputs = { flakelight, ... }: flakelight ./. ({ lib, config, ... }: { - nixosConfigurations.system = lib.nixosSystem { - # nixosSystem arguments - modules = [ config.propagationModule ]; + nixosConfigurations.test-system = { + system = "x86_64-linux"; + modules = [{ system.stateVersion = "24.05"; }]; }; }); } ``` +### homeConfigurations + +The `homeConfigurations` attribute lets you set outputs for NixOS systems and +home-manager users. + +It should be set to an attribute set. Each value should be a set of +`home-manager.lib.homeManagerConfiguration` args, the result of calling +`home-manager.lib.homeManagerConfiguration`, or a function that takes +`moduleArgs` and returns one of the prior. + +When using a set of `homeManagerConfiguration` args, it is required to include +`system` (`pkgs` does not need to be included), and `inputs.home-manager` must +be set. home-manager modules will have access to a `flake` module arg equivalent +to `moduleArgs` plus `inputs'` and `outputs'`. Flakelight's pkgs attributes, +`withOverlays`, and `packages` will also be available in the home-manager +instance's pkgs. + +When using the result of calling `homeManagerConfiguration`, the +`config.propogationModule` value can be used as a home-manager module to gain +the above benefits. + +For example: + ```nix { inputs = { flakelight.url = "github:nix-community/flakelight"; home-manger.url = "github:nix-community/home-manager"; }; - outputs = { flakelight, home-manager, ... }: + outputs = { flakelight, home-manager, ... }@inputs: flakelight ./. ({ config, ... }: { - homeConfigurations.user = home-manager.lib.homeManagerConfiguration { - # homeManagerConfiguration arguments - modules = [ config.propagationModule ]; + inherit inputs; + homeConfigurations.username = { + system = "x86_64-linux"; + modules = [{ home.stateVersion = "24.05"; }]; }; }); } ``` -Optionally, defining as a function: - -```nix -{ - inputs.flakelight.url = "github:nix-community/flakelight"; - outputs = { flakelight, ... }: - flakelight ./. { - nixosConfigurations.system = { lib, ... }: lib.nixosSystem { - # nixosSystem arguments - }; - }; -} -``` - ### nixosModules, homeModules, and flakelightModules The `nixosModules`, `homeModules`, and `flakelightModules` options allow you to diff --git a/builtinModules/homeConfigurations.nix b/builtinModules/homeConfigurations.nix index 54265a9..5008279 100644 --- a/builtinModules/homeConfigurations.nix +++ b/builtinModules/homeConfigurations.nix @@ -2,27 +2,53 @@ # Copyright (C) 2023 Archit Gupta # SPDX-License-Identifier: MIT -{ config, lib, flakelight, moduleArgs, ... }: +{ config, lib, inputs, flakelight, moduleArgs, ... }: let - inherit (builtins) isAttrs mapAttrs; - inherit (lib) foldl mapAttrsToList mergeOneOption mkOption mkOptionType mkIf - recursiveUpdate; - inherit (lib.types) lazyAttrsOf; + inherit (builtins) concatLists head mapAttrs match; + inherit (lib) foldl last mapAttrsToList mkOption mkIf recursiveUpdate + zipAttrsWith; + inherit (lib.types) attrs lazyAttrsOf; inherit (flakelight.types) optFunctionTo; - homeConfiguration = mkOptionType { - name = "homeConfiguration"; - description = "homeConfiguration"; - descriptionClass = "noun"; - check = x: isAttrs x && x ? activationPackage; - merge = mergeOneOption; - }; + isHome = x: x ? activationPackage; - configs = mapAttrs (_: f: f moduleArgs) config.homeConfigurations; + mergeCfg = zipAttrsWith (n: vs: + if n == "extraSpecialArgs" then + foldl (a: b: a // b) { } vs + else if n == "modules" then + concatLists vs + else last vs); + + mkHome = name: cfg: + let + inherit (cfg) system; + in + inputs.home-manager.lib.homeManagerConfiguration (mergeCfg [ + { + extraSpecialArgs = { + inherit inputs; + inputs' = mapAttrs (_: mapAttrs (_: v: v.${system} or { })) inputs; + }; + modules = [ + ({ lib, ... }: { + home.username = lib.mkDefault (head (match "([^@]*)(@.*)?" name)); + }) + config.propagationModule + ]; + pkgs = inputs.nixpkgs.legacyPackages.${system}; + } + (removeAttrs cfg [ "system" ]) + ]); + + configs = mapAttrs + (name: f: + let val = f moduleArgs; in + if isHome val then val else mkHome name val) + config.homeConfigurations; in { options.homeConfigurations = mkOption { - type = lazyAttrsOf (optFunctionTo homeConfiguration); + type = lazyAttrsOf (optFunctionTo attrs); default = { }; }; diff --git a/builtinModules/nixosConfigurations.nix b/builtinModules/nixosConfigurations.nix index 0b65aae..1bd6024 100644 --- a/builtinModules/nixosConfigurations.nix +++ b/builtinModules/nixosConfigurations.nix @@ -2,40 +2,60 @@ # Copyright (C) 2023 Archit Gupta # SPDX-License-Identifier: MIT -{ config, lib, flakelight, moduleArgs, ... }: +{ config, lib, inputs, flakelight, moduleArgs, ... }: let - inherit (builtins) isAttrs mapAttrs; - inherit (lib) foldl mapAttrsToList mergeOneOption mkIf mkOption mkOptionType - recursiveUpdate; - inherit (lib.types) lazyAttrsOf; + inherit (builtins) concatLists mapAttrs; + inherit (lib) foldl last mapAttrsToList mkIf mkOption recursiveUpdate + zipAttrsWith; + inherit (lib.types) attrs lazyAttrsOf; inherit (flakelight.types) optFunctionTo; - nixosConfiguration = mkOptionType { - name = "nixosConfiguration"; - description = "nixosConfiguration"; - descriptionClass = "noun"; - check = x: isAttrs x - && x ? config.nixpkgs.system - && x ? config.system.build.toplevel; - merge = mergeOneOption; - }; + # Avoid checking if toplevel is a derivation as it causes the nixos modules + # to be evaluated. + isNixos = x: x ? config.system.build.toplevel; - configs = mapAttrs (_: f: f moduleArgs) config.nixosConfigurations; + mergeCfg = zipAttrsWith (n: vs: + if n == "specialArgs" then + foldl (a: b: a // b) { } vs + else if n == "modules" then + concatLists vs + else last vs); + + mkSystem = hostname: cfg: + let + inherit (cfg) system; + in + inputs.nixpkgs.lib.nixosSystem (mergeCfg [ + { + specialArgs = { + inherit inputs hostname; + inputs' = mapAttrs (_: mapAttrs (_: v: v.${system} or { })) inputs; + }; + modules = [ config.propagationModule ]; + } + cfg + ]); + + systems = mapAttrs + (hostname: f: + let val = f moduleArgs; in + if isNixos val then val else mkSystem hostname val) + config.nixosConfigurations; in { options.nixosConfigurations = mkOption { - type = lazyAttrsOf (optFunctionTo nixosConfiguration); + type = lazyAttrsOf (optFunctionTo attrs); default = { }; }; config.outputs = mkIf (config.nixosConfigurations != { }) { - nixosConfigurations = configs; + nixosConfigurations = systems; checks = foldl recursiveUpdate { } (mapAttrsToList (n: v: { ${v.config.nixpkgs.system}."nixos-${n}" = v.pkgs.runCommand "check-nixos-${n}" { } "echo ${v.config.system.build.toplevel} > $out"; }) - configs); + systems); }; } diff --git a/tests/default.nix b/tests/default.nix index ee1c85a..0eeb21b 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -589,14 +589,23 @@ in nixosConfigurations = test (flakelight ./empty ({ lib, ... }: { - nixosConfigurations.test = nixpkgs.lib.nixosSystem { + nixosConfigurations.test = { system = "x86_64-linux"; - modules = [ ]; + modules = [{ system.stateVersion = "24.05"; }]; }; })) (f: f ? nixosConfigurations.test.config.system.build.toplevel); - nixosConfigurationsWithProp = test + nixosConfigurationsManual = test + (flakelight ./empty ({ lib, ... }: { + nixosConfigurations.test = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [{ system.stateVersion = "24.05"; }]; + }; + })) + (f: f ? nixosConfigurations.test.config.system.build.toplevel); + + nixosConfigurationsManualWithProp = test (flakelight ./empty ({ lib, config, ... }: { nixosConfigurations.test = nixpkgs.lib.nixosSystem { system = "x86_64-linux";