···167167168168 # We know that the `user` attribute exists because we set a default value
169169 # for it above, allowing us to use it without worries here
170170- users.users.${cfg.settings.user} = {};
170170+ users.users.${cfg.settings.user} = { isSystemUser = true; };
171171172172 # ...
173173 };
+7
nixos/doc/manual/release-notes/rl-2105.xml
···846846 </para>
847847 </listitem>
848848 <listitem>
849849+ <para>
850850+ When defining a new user, one of <xref linkend="opt-users.users._name_.isNormalUser" /> and <xref linkend="opt-users.users._name_.isSystemUser" /> is now required.
851851+ This is to prevent accidentally giving a UID above 1000 to system users, which could have unexpected consequences, like running user activation scripts for system users.
852852+ Note that users defined with an explicit UID below 500 are exempted from this check, as <xref linkend="opt-users.users._name_.isSystemUser" /> has no effect for those.
853853+ </para>
854854+ </listitem>
855855+ <listitem>
849856 <para>
850857 The GNOME desktop manager once again installs <package>gnome3.epiphany</package> by default.
851858 </para>
+1
nixos/modules/config/pulseaudio.nix
···306306 description = "PulseAudio system service user";
307307 home = stateDir;
308308 createHome = true;
309309+ isSystemUser = true;
309310 };
310311311312 users.groups.pulse.gid = gid;
+25-9
nixos/modules/config/users-groups.nix
···9292 the user's UID is allocated in the range for system users
9393 (below 500) or in the range for normal users (starting at
9494 1000).
9595+ Exactly one of <literal>isNormalUser</literal> and
9696+ <literal>isSystemUser</literal> must be true.
9597 '';
9698 };
9799···107109 <option>useDefaultShell</option> to <literal>true</literal>,
108110 and <option>isSystemUser</option> to
109111 <literal>false</literal>.
112112+ Exactly one of <literal>isNormalUser</literal> and
113113+ <literal>isSystemUser</literal> must be true.
110114 '';
111115 };
112116···521525 };
522526 nobody = {
523527 uid = ids.uids.nobody;
528528+ isSystemUser = true;
524529 description = "Unprivileged account (don't use!)";
525530 group = "nogroup";
526531 };
···608613 Neither the root account nor any wheel user has a password or SSH authorized key.
609614 You must set one to prevent being locked out of your system.'';
610615 }
611611- ] ++ flip mapAttrsToList cfg.users (name: user:
612612- {
616616+ ] ++ flatten (flip mapAttrsToList cfg.users (name: user:
617617+ [
618618+ {
613619 assertion = (user.hashedPassword != null)
614614- -> (builtins.match ".*:.*" user.hashedPassword == null);
620620+ -> (builtins.match ".*:.*" user.hashedPassword == null);
615621 message = ''
616616- The password hash of user "${user.name}" contains a ":" character.
617617- This is invalid and would break the login system because the fields
618618- of /etc/shadow (file where hashes are stored) are colon-separated.
619619- Please check the value of option `users.users."${user.name}".hashedPassword`.'';
620620- }
621621- );
622622+ The password hash of user "${user.name}" contains a ":" character.
623623+ This is invalid and would break the login system because the fields
624624+ of /etc/shadow (file where hashes are stored) are colon-separated.
625625+ Please check the value of option `users.users."${user.name}".hashedPassword`.'';
626626+ }
627627+ {
628628+ assertion = let
629629+ xor = a: b: a && !b || b && !a;
630630+ isEffectivelySystemUser = user.isSystemUser || (user.uid != null && user.uid < 500);
631631+ in xor isEffectivelySystemUser user.isNormalUser;
632632+ message = ''
633633+ Exactly one of users.users.${user.name}.isSystemUser and users.users.${user.name}.isNormalUser must be set.
634634+ '';
635635+ }
636636+ ]
637637+ ));
622638623639 warnings =
624640 builtins.filter (x: x != null) (