users.nix (3317B)
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, 15 pkgs, 16 config, 17 ... 18 }: 19 let 20 inherit (lib) 21 concatStrings 22 concatStringsSep 23 mapAttrsToList 24 mkOption 25 types 26 ; 27 inherit (builtins) toString; 28 inherit (pkgs.pseudofile) dir; 29 passwd-file = 30 let 31 lines = mapAttrsToList ( 32 name: u: 33 "${name}:${ 34 if u ? passwd then u.passwd else "!!" 35 }:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n" 36 ) config.users; 37 in 38 concatStrings lines; 39 group-file = 40 let 41 lines = mapAttrsToList ( 42 name: 43 { 44 gid, 45 usernames ? [ ], 46 }: 47 "${name}:x:${toString gid}:${concatStringsSep "," usernames}\n" 48 ) config.groups; 49 in 50 concatStrings lines; 51 in 52 { 53 options = { 54 users = mkOption { 55 type = types.attrsOf ( 56 types.submodule { 57 options = { 58 passwd = mkOption { 59 type = types.str; 60 description = "encrypted password, as generated by mkpasswd -m sha512crypt"; 61 example = "$6$RIYL.EgWOrtoJ0/7$Z53a8sc0o6AU/kuFOGiLJKhwVavTG/deoM7JTs6luNczYSUsh4UYmhvT8sVzm.l8F/LZXhhhkC7IHQs5UGAIM/"; 62 default = "!!"; 63 }; 64 uid = mkOption { 65 type = types.int; 66 }; 67 gid = mkOption { 68 type = types.int; 69 }; 70 gecos = mkOption { 71 type = types.str; 72 default = ""; 73 example = "Jo Q User"; 74 }; 75 dir = mkOption { 76 type = types.str; 77 default = "/run"; 78 }; 79 shell = mkOption { 80 type = types.str; 81 default = "/bin/sh"; 82 }; 83 openssh.authorizedKeys.keys = mkOption { 84 type = types.listOf types.str; 85 default = [ ]; 86 }; 87 }; 88 } 89 ); 90 }; 91 groups = mkOption { 92 type = types.attrsOf ( 93 types.submodule { 94 options = { 95 gid = mkOption { 96 type = types.int; 97 }; 98 usernames = mkOption { 99 type = types.listOf types.str; 100 default = [ ]; 101 }; 102 }; 103 } 104 ); 105 }; 106 }; 107 config = 108 let 109 authorized_key_files = lib.attrsets.mapAttrs ( 110 name: val: 111 dir { 112 ".ssh" = dir { 113 authorized_keys = { 114 inherit (val) uid gid; 115 type = "f"; 116 mode = "0400"; 117 file = lib.concatStringsSep "\n" val.openssh.authorizedKeys.keys; 118 }; 119 }; 120 } 121 ) config.users; 122 in 123 { 124 filesystem = dir { 125 etc = dir { 126 passwd = { 127 file = passwd-file; 128 }; 129 group = { 130 file = group-file; 131 }; 132 }; 133 home = dir authorized_key_files; 134 }; 135 }; 136 }