liminix/modules/users.nix
2023-08-09 22:27:37 +01:00

103 lines
2.8 KiB
Nix

## Users
## =====
##
## User- and group-related configuration.
##
## Changes made here are reflected in files such as :file:/etc/shadow,
## :file:/etc/passwd, :file:/etc/group etc. If you are familiar with
## user configuration in NixOS, please note that Liminix does not have
## the concept of "mutable users" - files in /etc/ are symlinks to
## the immutable store, so you can't e.g change a password with
## :command:`passwd`
{ lib, pkgs, config, ...}:
let
inherit (lib)
concatStrings concatStringsSep mapAttrsToList mkOption types;
inherit (builtins) toString;
inherit (pkgs.pseudofile) dir symlink;
passwd-file =
let lines = mapAttrsToList (name: u: "${name}:${if u ? passwd then u.passwd else "!!"}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n" )
config.users;
in concatStrings lines;
group-file =
let lines = mapAttrsToList
(name: {gid, usernames ? []}:
"${name}:x:${toString gid}:${concatStringsSep "," usernames}\n" )
config.groups;
in concatStrings lines;
in {
options = {
users = mkOption {
type = types.attrsOf (types.submodule {
options = {
passwd = mkOption {
type = types.str;
default = "!!";
};
uid = mkOption {
type = types.int;
};
gid = mkOption {
type = types.int;
};
gecos = mkOption {
type = types.str;
default = "";
example = "Jo Q User";
};
dir = mkOption {
type = types.str;
default = "/run";
};
shell = mkOption {
type = types.str;
default = "/bin/sh";
};
openssh.authorizedKeys.keys = mkOption {
type = types.listOf types.str;
default = [];
};
};
});
};
groups = mkOption {
type = types.attrsOf (types.submodule {
options = {
gid = mkOption {
type = types.int;
};
usernames = mkOption {
type = types.listOf types.str;
default = [];
};
};
});
};
};
config =
let authorized_key_files =
lib.attrsets.mapAttrs
(name: val: dir {
".ssh" = dir {
authorized_keys = {
inherit (val) uid gid;
type = "f";
mode = "0400";
file = lib.concatStringsSep
"\n" val.openssh.authorizedKeys.keys;
};
};
})
config.users;
in {
filesystem = dir {
etc = dir {
passwd = { file = passwd-file; };
group = { file = group-file; };
};
home = dir authorized_key_files;
};
};
}