nixos/users/default.nix

157 lines
4.8 KiB
Nix

# 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)
- `sshKeys`: User's authorized SSH keys (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,
...
}:
lib.foldl' (acc: obj: lib.recursiveUpdate acc obj) { } (
lib.lists.flatten [
# Import required modules
{
imports = [
inputs.home-manager.nixosModules.default
];
}
# Configure users' passwords as sops secret.
(map (user: {
sops.secrets."${user}/userPassword" = {
sopsFile = ./${user}/password.yaml;
neededForUsers = true;
};
}) cfg.usersList)
# Configure users
(map (user: {
users.users.${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 [ ];
openssh.authorizedKeys.keys = cfg.sshKeys or [ ];
};
}) cfg.usersList)
# Configurure home-manager
{
home-manager = {
backupFileExtension = "backup-${toString inputs.self.lastModified}";
extraSpecialArgs = {
inherit inputs;
};
};
}
(map (user: {
home-manager.users.${user} = {
nixpkgs.config.allowUnfree = true;
imports = [
./${user}/modules
inputs.stylix.homeModules.stylix
];
stylix = lib.mkIf (!cfg.headless) {
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
(lib.optionalAttrs (!cfg.headless) {
services.displayManager.gdm.enable = true;
})
(map (
user:
lib.optionalAttrs (!cfg.headless) {
systemd.tmpfiles.settings."20-gdm-default-session" = {
"/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)
(map (
user:
lib.optionalAttrs (!cfg.headless) (
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)
]
)