liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

users.nix (3095B)


      1 ## Users
      2 ## =====
      3 ##
      4 ## User- and group-related configuration.
      5 ##
      6 ## Changes made here are reflected in files such as :file:/etc/shadow,
      7 ## :file:/etc/passwd, :file:/etc/group etc. If you are familiar with
      8 ## user configuration in NixOS, please note that Liminix does not have
      9 ## the concept of "mutable users" - files in /etc/ are symlinks to
     10 ## the immutable store, so you can't e.g  change a password with
     11 ## :command:`passwd`
     12 
     13 
     14 { lib, pkgs, config, ...}:
     15 let
     16   inherit (lib)
     17     concatStrings concatStringsSep mapAttrsToList mkOption types;
     18   inherit (builtins) toString;
     19   inherit (pkgs.pseudofile) dir symlink;
     20   passwd-file  =
     21     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" )
     22       config.users;
     23     in concatStrings lines;
     24   group-file =
     25     let lines = mapAttrsToList
     26       (name: {gid, usernames ? []}:
     27         "${name}:x:${toString gid}:${concatStringsSep "," usernames}\n" )
     28       config.groups;
     29     in concatStrings lines;
     30 in {
     31   options = {
     32     users =  mkOption {
     33       type = types.attrsOf (types.submodule {
     34         options = {
     35           passwd = mkOption {
     36             type = types.str;
     37             description = "encrypted password, as generated by mkpasswd -m sha512crypt";
     38             example = "$6$RIYL.EgWOrtoJ0/7$Z53a8sc0o6AU/kuFOGiLJKhwVavTG/deoM7JTs6luNczYSUsh4UYmhvT8sVzm.l8F/LZXhhhkC7IHQs5UGAIM/";
     39             default = "!!";
     40           };
     41           uid = mkOption {
     42             type = types.int;
     43           };
     44           gid = mkOption {
     45             type = types.int;
     46           };
     47           gecos = mkOption {
     48             type = types.str;
     49             default = "";
     50             example = "Jo Q User";
     51           };
     52           dir = mkOption {
     53             type = types.str;
     54             default = "/run";
     55           };
     56           shell = mkOption {
     57             type = types.str;
     58             default = "/bin/sh";
     59           };
     60           openssh.authorizedKeys.keys = mkOption {
     61             type = types.listOf types.str;
     62             default = [];
     63           };
     64         };
     65       });
     66     };
     67     groups =  mkOption {
     68       type = types.attrsOf (types.submodule {
     69         options = {
     70           gid = mkOption {
     71             type = types.int;
     72           };
     73           usernames = mkOption {
     74             type = types.listOf types.str;
     75             default = [];
     76           };
     77         };
     78       });
     79     };
     80   };
     81   config =
     82     let authorized_key_files =
     83           lib.attrsets.mapAttrs
     84             (name: val: dir {
     85               ".ssh" = dir {
     86                 authorized_keys = {
     87                   inherit (val) uid gid;
     88                   type = "f";
     89                   mode = "0400";
     90                   file = lib.concatStringsSep
     91                     "\n" val.openssh.authorizedKeys.keys;
     92                 };
     93               };
     94             })
     95             config.users;
     96     in {
     97       filesystem = dir {
     98         etc = dir {
     99           passwd = { file = passwd-file; };
    100           group = { file = group-file; };
    101         };
    102         home = dir authorized_key_files;
    103       };
    104     };
    105 }