| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | {pkgs, config, ...}: | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  | with pkgs.lib; | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | let | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-29 14:25:56 +00:00
										 |  |  |   ids = config.ids; | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2007-11-16 13:26:34 +00:00
										 |  |  |   # User accounts to be created/updated by NixOS. | 
					
						
							|  |  |  |   users = | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  |     let | 
					
						
							|  |  |  |       defaultUsers = | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |         [ { name = "root"; | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  |             uid = ids.uids.root; | 
					
						
							|  |  |  |             description = "System administrator"; | 
					
						
							|  |  |  |             home = "/root"; | 
					
						
							| 
									
										
										
										
											2009-05-28 12:24:56 +00:00
										 |  |  |             shell = config.users.defaultUserShell; | 
					
						
							| 
									
										
										
										
											2007-11-12 14:59:23 +00:00
										 |  |  |             group = "root"; | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  |           } | 
					
						
							|  |  |  |           { name = "nobody"; | 
					
						
							|  |  |  |             uid = ids.uids.nobody; | 
					
						
							|  |  |  |             description = "Unprivileged account (don't use!)"; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ]; | 
					
						
							| 
									
										
										
										
											2009-12-13 15:29:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  |       addAttrs = | 
					
						
							|  |  |  |         { name | 
					
						
							|  |  |  |         , description | 
					
						
							|  |  |  |         , uid ? "" | 
					
						
							|  |  |  |         , group ? "nogroup" | 
					
						
							|  |  |  |         , extraGroups ? [] | 
					
						
							|  |  |  |         , home ? "/var/empty" | 
					
						
							| 
									
										
										
										
											2009-05-28 12:24:56 +00:00
										 |  |  |         , shell ? (if useDefaultShell then config.users.defaultUserShell else "/noshell") | 
					
						
							| 
									
										
										
										
											2007-11-16 13:26:34 +00:00
										 |  |  |         , createHome ? false | 
					
						
							|  |  |  |         , useDefaultShell ? false | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |         , password ? null | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  |         }: | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |         { inherit name description uid group extraGroups home shell createHome password; }; | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 16:50:08 +00:00
										 |  |  |     in map addAttrs (defaultUsers ++ config.users.extraUsers); | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-16 13:26:34 +00:00
										 |  |  |   # Groups to be created/updated by NixOS. | 
					
						
							|  |  |  |   groups = | 
					
						
							| 
									
										
										
										
											2007-06-10 20:13:12 +00:00
										 |  |  |     let | 
					
						
							|  |  |  |       defaultGroups =  | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |         [ { name = "root"; | 
					
						
							| 
									
										
										
										
											2007-06-10 20:13:12 +00:00
										 |  |  |             gid = ids.gids.root; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2007-08-16 15:09:06 +00:00
										 |  |  |           { name = "wheel"; | 
					
						
							|  |  |  |             gid = ids.gids.wheel; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2008-07-02 18:03:43 +00:00
										 |  |  |           { name = "disk"; | 
					
						
							|  |  |  |             gid = ids.gids.disk; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "kmem"; | 
					
						
							|  |  |  |             gid = ids.gids.kmem; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "tty"; | 
					
						
							|  |  |  |             gid = ids.gids.tty; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "floppy"; | 
					
						
							|  |  |  |             gid = ids.gids.floppy; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "uucp"; | 
					
						
							|  |  |  |             gid = ids.gids.uucp; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "lp"; | 
					
						
							|  |  |  |             gid = ids.gids.lp; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2009-08-11 09:17:30 +00:00
										 |  |  |           { name = "cdrom"; | 
					
						
							|  |  |  |             gid = ids.gids.cdrom; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "tape"; | 
					
						
							|  |  |  |             gid = ids.gids.tape; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "video"; | 
					
						
							|  |  |  |             gid = ids.gids.video; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "dialout"; | 
					
						
							|  |  |  |             gid = ids.gids.dialout; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2007-06-10 20:13:12 +00:00
										 |  |  |           { name = "nogroup"; | 
					
						
							|  |  |  |             gid = ids.gids.nogroup; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "users"; | 
					
						
							|  |  |  |             gid = ids.gids.users; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { name = "nixbld"; | 
					
						
							|  |  |  |             gid = ids.gids.nixbld; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2010-04-22 13:56:26 +00:00
										 |  |  |           { name = "utmp"; | 
					
						
							|  |  |  |             gid = ids.gids.utmp; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2007-06-10 20:13:12 +00:00
										 |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       addAttrs = | 
					
						
							|  |  |  |         { name, gid ? "" }: | 
					
						
							|  |  |  |         { inherit name gid; }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-18 18:00:09 +00:00
										 |  |  |     in map addAttrs (defaultGroups ++ config.users.extraGroups); | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |   # Note: the 'X' in front of the password is to distinguish between | 
					
						
							|  |  |  |   # having an empty password, and not having a password. | 
					
						
							|  |  |  |   serializedUser = u: "${u.name}\n${u.description}\n${toString u.uid}\n${u.group}\n${toString (concatStringsSep "," u.extraGroups)}\n${u.home}\n${u.shell}\n${toString u.createHome}\n${if u.password != null then "X" + u.password else ""}\n"; | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  |   serializedGroup = g: "${g.name}\n${toString g.gid}"; | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2009-03-06 12:26:16 +00:00
										 |  |  |   # keep this extra file so that cat can be used to pass special chars such as "`" which is used in the avahi daemon | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |   usersFile = pkgs.writeText "users" (concatStrings (map serializedUser users)); | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | in | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |   ###### interface | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |   options = { | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |     users.extraUsers = mkOption { | 
					
						
							|  |  |  |       default = []; | 
					
						
							|  |  |  |       example = | 
					
						
							|  |  |  |         [ { name = "alice"; | 
					
						
							|  |  |  |             uid = 1234; | 
					
						
							|  |  |  |             description = "Alice"; | 
					
						
							|  |  |  |             home = "/home/alice"; | 
					
						
							|  |  |  |             createHome = true; | 
					
						
							|  |  |  |             group = "users"; | 
					
						
							|  |  |  |             extraGroups = ["wheel"]; | 
					
						
							|  |  |  |             shell = "/bin/sh"; | 
					
						
							|  |  |  |             password = "foobar"; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |       description = ''
 | 
					
						
							|  |  |  |         Additional user accounts to be created automatically by the system. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |     users.extraGroups = mkOption { | 
					
						
							|  |  |  |       default = []; | 
					
						
							|  |  |  |       example = | 
					
						
							|  |  |  |         [ { name = "students"; | 
					
						
							|  |  |  |             gid = 1001; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |       description = ''
 | 
					
						
							|  |  |  |         Additional groups to be created automatically by the system. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ###### implementation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   config = { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 15:41:38 +00:00
										 |  |  |     system.activationScripts.rootPasswd = stringAfter [ "etc" ] | 
					
						
							|  |  |  |       ''
 | 
					
						
							|  |  |  |         # If there is no password file yet, create a root account with an | 
					
						
							|  |  |  |         # empty password. | 
					
						
							|  |  |  |         if ! test -e /etc/passwd; then | 
					
						
							|  |  |  |             rootHome=/root | 
					
						
							|  |  |  |             touch /etc/passwd; chmod 0644 /etc/passwd | 
					
						
							|  |  |  |             touch /etc/group; chmod 0644 /etc/group | 
					
						
							|  |  |  |             touch /etc/shadow; chmod 0600 /etc/shadow | 
					
						
							|  |  |  |             # Can't use useradd, since it complains that it doesn't know us | 
					
						
							|  |  |  |             # (bootstrap problem!). | 
					
						
							|  |  |  |             echo "root:x:0:0:System administrator:$rootHome:${config.users.defaultUserShell}" >> /etc/passwd | 
					
						
							|  |  |  |             echo "root::::::::" >> /etc/shadow | 
					
						
							|  |  |  |         fi | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     system.activationScripts.users = stringAfter [ "groups" ] | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |       ''
 | 
					
						
							| 
									
										
										
										
											2009-12-16 13:35:03 +00:00
										 |  |  |         echo "updating users..." | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 12:26:16 +00:00
										 |  |  |         cat ${usersFile} | while true; do | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  |             read name || break | 
					
						
							|  |  |  |             read description | 
					
						
							|  |  |  |             read uid | 
					
						
							|  |  |  |             read group | 
					
						
							|  |  |  |             read extraGroups | 
					
						
							|  |  |  |             read home | 
					
						
							|  |  |  |             read shell | 
					
						
							|  |  |  |             read createHome | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |             read password | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if ! curEnt=$(getent passwd "$name"); then | 
					
						
							|  |  |  |                 useradd --system \ | 
					
						
							|  |  |  |                     --comment "$description" \ | 
					
						
							|  |  |  |                     ''${uid:+--uid $uid} \
 | 
					
						
							|  |  |  |                     --gid "$group" \ | 
					
						
							|  |  |  |                     --groups "$extraGroups" \ | 
					
						
							|  |  |  |                     --home "$home" \ | 
					
						
							|  |  |  |                     --shell "$shell" \ | 
					
						
							| 
									
										
										
										
											2010-06-02 21:10:48 +00:00
										 |  |  |                     ''${createHome:+--create-home} \
 | 
					
						
							|  |  |  |                     "$name" | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |                 if test "''${password:0:1}" = 'X'; then | 
					
						
							| 
									
										
										
										
											2010-06-02 23:02:09 +00:00
										 |  |  |                     (echo "''${password:1}"; echo "''${password:1}") | ${pkgs.shadow}/bin/passwd "$name" | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |                 fi | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  |             else | 
					
						
							|  |  |  |                 #echo "updating user $name..." | 
					
						
							|  |  |  |                 oldIFS="$IFS"; IFS=:; set -- $curEnt; IFS="$oldIFS" | 
					
						
							|  |  |  |                 prevUid=$3 | 
					
						
							|  |  |  |                 prevHome=$6 | 
					
						
							|  |  |  |                 # Don't change the UID if it's the same, otherwise usermod | 
					
						
							|  |  |  |                 # will complain. | 
					
						
							|  |  |  |                 if test "$prevUid" = "$uid"; then unset uid; fi | 
					
						
							|  |  |  |                 # Don't change the home directory if it's the same to prevent | 
					
						
							|  |  |  |                 # unnecessary warnings about logged in users. | 
					
						
							|  |  |  |                 if test "$prevHome" = "$home"; then unset home; fi | 
					
						
							|  |  |  |                 usermod \ | 
					
						
							|  |  |  |                     --comment "$description" \ | 
					
						
							|  |  |  |                     ''${uid:+--uid $uid} \
 | 
					
						
							|  |  |  |                     --gid "$group" \ | 
					
						
							|  |  |  |                     --groups "$extraGroups" \ | 
					
						
							|  |  |  |                     ''${home:+--home "$home"} \
 | 
					
						
							| 
									
										
										
										
											2010-06-02 21:10:48 +00:00
										 |  |  |                     --shell "$shell" \ | 
					
						
							|  |  |  |                     "$name" | 
					
						
							| 
									
										
										
										
											2009-12-16 13:35:03 +00:00
										 |  |  |             fi | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 12:26:16 +00:00
										 |  |  |         done | 
					
						
							| 
									
										
										
										
											2010-09-13 15:41:38 +00:00
										 |  |  |       '';
 | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 15:41:38 +00:00
										 |  |  |     system.activationScripts.groups = stringAfter [ "rootPasswd" "binsh" "etc" "var" ] | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  |       ''
 | 
					
						
							| 
									
										
										
										
											2009-12-16 13:35:03 +00:00
										 |  |  |         echo "updating groups..." | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  |         while true; do | 
					
						
							|  |  |  |             read name || break | 
					
						
							|  |  |  |             read gid | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ! curEnt=$(getent group "$name"); then | 
					
						
							|  |  |  |                 groupadd --system \ | 
					
						
							| 
									
										
										
										
											2010-06-02 21:10:48 +00:00
										 |  |  |                     ''${gid:+--gid $gid} \
 | 
					
						
							|  |  |  |                     "$name" | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  |             else | 
					
						
							|  |  |  |                 #echo "updating group $name..." | 
					
						
							|  |  |  |                 oldIFS="$IFS"; IFS=:; set -- $curEnt; IFS="$oldIFS" | 
					
						
							|  |  |  |                 prevGid=$3 | 
					
						
							|  |  |  |                 if test -n "$gid" -a "$prevGid" != "$gid"; then | 
					
						
							| 
									
										
										
										
											2010-06-02 21:10:48 +00:00
										 |  |  |                     groupmod --gid $gid "$name" | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  |                 fi | 
					
						
							|  |  |  |             fi | 
					
						
							|  |  |  |         done <<EndOfGroupList | 
					
						
							|  |  |  |         ${concatStringsSep "\n" (map serializedGroup groups)} | 
					
						
							|  |  |  |         EndOfGroupList | 
					
						
							| 
									
										
										
										
											2010-09-13 15:41:38 +00:00
										 |  |  |       '';
 | 
					
						
							| 
									
										
										
										
											2007-06-08 15:41:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 16:07:01 +00:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2009-09-02 17:35:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-09 18:49:45 +00:00
										 |  |  | } |