# Users /** This module contains users' configuration which is declared on system level. It includes user's password, shell, etc. Parameters is imported from `about.json` in user's folder. File can have these keys (may be expanded in future): - `realName`: User's real name (optionally) - `extraGroups`: groups (optionally) - `shell`: User's shell - `session`: User's default graphical session (optionally) Session must have format of "{type}:{session}" where type is one of `co` (short for "compositor") and `de` (short for "desktop environment"). This `type` is actually important, because it depends where nix will search corresponding option for enabling your session. If `co`, it will search it in `programs.*`, and if `de`, in `services.desktopManager.*` User's face (optionally) - if any, should be located at users/{user}/face.png - i prefer store this encrypted, but you can keep it in clear text User's password must be stored at users/{user}/password.yaml and encrypted with sops. Format of unencrypted file: ```yaml # {your password} {username}: userPassword: {hash} ``` where `{hash}` is result of `echo {your password} | mkpasswd -s` Wallpapers can be `png` or `jpg` format, and must be stored at `users/{user}/wallpaper.{ext}` */ { lib, pkgs, cfg, config, inputs, ... }: { imports = [ inputs.home-manager.nixosModules.default ]; # Configure users' passwords as sops secret. sops.secrets = lib.mkMerge ( map (user: { "${user}/userPassword" = { sopsFile = ./${user}/password.yaml; neededForUsers = true; }; }) cfg.usersList ); # Configure users users.users = lib.mkMerge ( map (user: { ${user} = let cfg = builtins.fromJSON (builtins.readFile ./${user}/about.json); in { description = cfg.realName or user; hashedPasswordFile = config.sops.secrets."${user}/userPassword".path; isNormalUser = true; shell = pkgs."${cfg.shell}"; extraGroups = cfg.extraGroups or [ ]; }; }) cfg.usersList ); # Configurure home-manager home-manager = { backupFileExtension = "backup-${toString inputs.self.lastModified}"; users = lib.mkMerge ( map (user: { ${user} = { imports = [ ./${user}/modules inputs.stylix.homeModules.stylix ]; stylix = { enable = true; image = if builtins.pathExists ./${user}/wallpaper.png then ./${user}/wallpaper.png else ./${user}/wallpaper.jpg; }; home.stateVersion = config.system.stateVersion; }; }) cfg.usersList ); }; # Configure DM and users' default sessions services.displayManager.gdm.enable = true; systemd.tmpfiles.settings."20-gdm-default-session" = lib.mkMerge ( map (user: { "/run/tmpfiles/var/lib/AccountsService/users/${user}".f = { argument = "${lib.generators.toINI { } { User = { Session = toString ( builtins.tail ( lib.splitString ":" (builtins.fromJSON (builtins.readFile ./${user}/about.json)).session ) ); SystemAccount = false; } // ( let pic = ./${user}/face.png; in if builtins.pathExists pic then { Icon = "${pic}"; } else { } ); }}"; }; "/var/lib/AccountsService/users/${user}"."L+" = { argument = "/run/tmpfiles/var/lib/AccountsService/users/${user}"; }; }) cfg.usersList ); } // (lib.foldl (acc: elem: acc // elem) { } ( map ( user: let __session = lib.splitString ":" (builtins.fromJSON (builtins.readFile ./${user}/about.json)) .session; sessionType = (builtins.head __session); session = toString (builtins.tail __session); in assert sessionType == "co" || sessionType == "de"; if sessionType == "co" then { programs.${session}.enable = true; } else if sessionType == "de" then { services.desktopManager.${session}.enable = true; } else { } ) cfg.usersList ))