From 0ded132804541286e827dfda599c7a5ff898e07b Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 1 Jan 2021 22:16:57 +0100 Subject: implement user profiles --- .gitignore | 3 +- flake.nix | 77 ++++++++++++++++++++++++++++++++++++------------ system-profiles/core.nix | 8 ++--- user-profiles/core.nix | 26 ++++++++++++++++ 4 files changed, 90 insertions(+), 24 deletions(-) create mode 100644 user-profiles/core.nix diff --git a/.gitignore b/.gitignore index bc527922..2c9847e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/result **/result-* -**/#*# \ No newline at end of file +**/#*# +**/.#* \ No newline at end of file diff --git a/flake.nix b/flake.nix index 302a322c..7a3b61bc 100644 --- a/flake.nix +++ b/flake.nix @@ -26,17 +26,26 @@ outputs = { self, nixpkgs, home-manager, sops-nix }@inputs: let - inherit (builtins) attrNames attrValues elemAt; + inherit (builtins) attrNames attrValues elemAt toJSON; inherit (nixpkgs) lib; utils = import ./utils { inherit lib; }; inherit (utils) recImport overrideModule; - inherit (lib) nixosSystem mkIf splitString filterAttrs listToAttrs mapAttrsToList nameValuePair concatMap composeManyExtensions mapAttrs mapAttrs' recursiveUpdate; + inherit (lib) nixosSystem mkIf splitString filterAttrs listToAttrs mapAttrsToList nameValuePair concatMap composeManyExtensions mapAttrs mapAttrs' recursiveUpdate genAttrs unique; + + accountUserName = accountName: + let + accountName' = splitString "@" accountName; + in elemAt accountName' 0; + accountHostName = accountName: + let + accountName' = splitString "@" accountName; + in elemAt accountName' 1; mkNixosConfiguration = dir: path: hostName: nixosSystem rec { specialArgs = { flake = self; flakeInputs = inputs; - path = toString ./.; + path = ./.; }; modules = let @@ -44,54 +53,84 @@ [ core ]; - local = "${toString dir}/${path}"; + local = dir + "/${path}"; argsModule._module.args = { customUtils = utils; inherit hostName; }; accountModules = attrValues (filterAttrs accountMatchesHost self.nixosModules.accounts); - accountMatchesHost = n: _v: - let - accountName' = splitString "@" n; - hostName' = elemAt accountName' 1; - in hostName' == hostName; + accountMatchesHost = n: _v: accountHostName n == hostName; in [ argsModule ] ++ defaultProfiles ++ [ local ] ++ accountModules; }; mkSystemProfile = dir: path: profileName: { - imports = [ "${toString dir}/${path}" ]; + imports = [ (dir + "/${path}") ]; config = { system.profiles = [profileName]; }; }; - mkUserModule = dir: path: userName: overrideModule (import "${toString dir}/${path}") (inputs: inputs // { inherit userName; }) (outputs: { _file = "${toString dir}/${path}"; } // outputs); + defaultUserProfiles = userName: with self.nixosModules.userProfiles.${userName}; + [ core + ]; + + mkUserModule = dir: path: userName: + overrideModule (import (dir + "/${path}")) + (inputs: inputs // { inherit userName; }) + (outputs: { _file = dir + "/${path}"; } + // outputs + // { imports = [self.nixosModules.userProfiles.${userName}.core] ++ (outputs.imports or []); }); + + mkUserProfile = userName: dir: path: profileName: + let + profileModule = overrideModule (import (dir + "/${path}")) + (inputs: inputs // { inherit userName; }) + (outputs: { _file = dir + "/${path}"; } + // outputs); + in { + imports = [profileModule]; + config = { + users.users.${userName}.profiles = [profileName]; + }; + }; mkAccountModule = dir: path: accountName: let - accountName' = splitString "@" accountName; - userName = elemAt accountName' 0; - in overrideModule (import "${toString dir}/${path}") (inputs: inputs // { inherit userName; }) (outputs: { _file = "${toString dir}/${path}"; } // outputs // { imports = [self.nixosModules.users.${userName}] ++ (outputs.imports or []); }); + userName = accountUserName accountName; + in overrideModule + (import (dir + "/${path}")) + (inputs: inputs // { inherit userName; }) + (outputs: { _file = dir + "/${path}"; } + // outputs + // { imports = defaultUserProfiles userName ++ (outputs.imports or []); }); forAllSystems = f: mapAttrs f nixpkgs.legacyPackages; + forAllUsers = genAttrs (unique (map accountUserName (attrNames self.nixosModules.accounts))); activateHomeManagerConfigurations = forAllSystems (system: _pkgs: mapAttrs' (configName: hmConfig: nameValuePair "${configName}-activate" { type = "app"; program = "${hmConfig.activationPackage}/bin/activate"; }) self.homeManagerConfigurations); activateNixosConfigurations = forAllSystems (system: _pkgs: mapAttrs' (hostName: nixosConfig: nameValuePair "${hostName}-activate" { type = "app"; program = "${nixosConfig.config.system.build.toplevel}/bin/switch-to-configuration"; }) self.nixosConfigurations); + + overlayPaths = recImport rec { dir = ./overlays; _import = (path: _name: dir + "/${path}"); } // { pkgs = ./pkgs; }; in { nixosModules = let modulesAttrs = recImport { dir = ./modules; }; systemProfiles = recImport rec { dir = ./system-profiles; _import = mkSystemProfile dir; }; - userProfiles = recImport rec { dir = ./user-profiles; }; users = recImport rec { dir = ./users; _import = mkUserModule dir; }; - accounts = recImport rec { dir = ./accounts; _import = mkAccountModule dir; }; - in modulesAttrs // { inherit systemProfiles userProfiles users accounts; }; + userProfiles = forAllUsers (userName: recImport rec { dir = ./user-profiles; _import = mkUserProfile userName dir; }); + accounts = recursiveUpdate rootAccounts (recImport rec { dir = ./accounts; _import = mkAccountModule dir; }); + rootAccounts = mapAttrs' (hostName: _value: nameValuePair "root@${hostName}" ({...}: { imports = [ self.nixosModules.users.root or ({...}: { imports = defaultUserProfiles "root"; }) ]; })) self.nixosConfigurations; + in modulesAttrs // { inherit systemProfiles users userProfiles accounts; }; nixosConfigurations = recImport rec { dir = ./hosts; _import = mkNixosConfiguration dir; }; + homeManagerModules = recImport rec { dir = ./user-profiles; }; homeManagerConfigurations = listToAttrs (concatMap ({hostName, users}: mapAttrsToList (userName: homeConfig: nameValuePair "${userName}@${hostName}" homeConfig) users) (mapAttrsToList (hostName: nixosConfig: { inherit hostName; users = nixosConfig.config.home-manager.users; }) (self.nixosConfigurations))); - overlay = import ./pkgs; - overlays = recImport { dir = ./overlays; } // { pkgs = self.overlay; }; + overlay = import overlayPaths.pkgs; + overlays = mapAttrs (_name: path: import path) overlayPaths; + overlays-path = forAllSystems (system: _: self.legacyPackages.${system}.writeText "overlays.nix" '' + map import (builtins.attrValues (builtins.fromJSON ${self.legacyPackages.${system}.writeText "overlays.json" (toJSON overlayPaths)})); + ''); packages = forAllSystems (system: systemPkgs: composeManyExtensions (attrValues self.overlays) (self.legacyPackages.${system}) systemPkgs); diff --git a/system-profiles/core.nix b/system-profiles/core.nix index f009c178..bd2004df 100644 --- a/system-profiles/core.nix +++ b/system-profiles/core.nix @@ -22,8 +22,7 @@ in { networking.hostName = hostName; system.configurationRevision = lib.mkIf (flake ? rev) flake.rev; - nixpkgs.pkgs = flakeInputs.nixpkgs.legacyPackages.${config.nixpkgs.system}; - nixpkgs.overlays = lib.attrValues flake.overlays; + nixpkgs.pkgs = flake.legacyPackages.${config.nixpkgs.system}; nix = { package = pkgs.nixUnstable; @@ -34,12 +33,13 @@ in { experimental-features = nix-command flakes ca-references ''; nixPath = [ - "nixpkgs=${path}" + "nixpkgs=${flakeInputs.nixpkgs.legacyPackages.${config.nixpkgs.system}.path}" + "nixpkgs-overlays=${flake.overlays-path.${config.nixpkgs.system}}" ]; registry = { nixpkgs.flake = flakeInputs.nixpkgs; home-manager.flake = flakeInputs.home-manager; - machines.flake = flake; + nixos.flake = flake; }; }; diff --git a/user-profiles/core.nix b/user-profiles/core.nix new file mode 100644 index 00000000..6f473b1a --- /dev/null +++ b/user-profiles/core.nix @@ -0,0 +1,26 @@ +{ flake, userName, lib, customUtils, ... }: +let + userProfileSet = customUtils.types.attrNameSet (lib.zipAttrs (lib.attrValues flake.nixosModules.userProfiles)); +in { + options = { + users.users = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { + options.profiles = lib.mkOption { + type = userProfileSet; + default = []; + description = '' + Set (list without duplicates) of ‘userProfiles’ enabled for this user + ''; + }; + }); + }; + }; + + config = { + users.users.${userName} = {}; # Just make sure the user is created + + home-manager.users.${userName} = { + manual.manpages.enable = true; + }; + }; +} -- cgit v1.2.3