···117118- `services.keyd` changed API. Now you can create multiple configuration files.
11900120- `services.ddclient` has been removed on the request of the upstream maintainer because it is unmaintained and has bugs. Please switch to a different software like `inadyn` or `knsupdate`.
121122- The `vlock` program from the `kbd` package has been moved into its own package output and should now be referenced explicitly as `kbd.vlock` or replaced with an alternative such as the standalone `vlock` package or `physlock`.
···117118- `services.keyd` changed API. Now you can create multiple configuration files.
119120+- `baloo`, the file indexer/search engine used by KDE now has a patch to prevent files from constantly being reindexed when the device ids of the their underlying storage changes. This happens frequently when using btrfs or LVM. The patch has not yet been accepted upstream but it provides a significantly improved experience. When upgrading, reset baloo to get a clean index: `balooctl disable ; balooctl purge ; balooctl enable`.
121+122- `services.ddclient` has been removed on the request of the upstream maintainer because it is unmaintained and has bugs. Please switch to a different software like `inadyn` or `knsupdate`.
123124- The `vlock` program from the `kbd` package has been moved into its own package output and should now be referenced explicitly as `kbd.vlock` or replaced with an alternative such as the standalone `vlock` package or `physlock`.
+29-8
nixos/modules/config/update-users-groups.pl
···4use File::Slurp;
5use Getopt::Long;
6use JSON;
078# Keep track of deleted uids and gids.
9my $uidMapFile = "/var/lib/nixos/uid-map";
···20 my ($path, $contents, $perms) = @_;
21 return if $is_dry;
22 write_file($path, { atomic => 1, binmode => ':utf8', perms => $perms // 0644 }, $contents) or die;
000000000000000023}
2425sub nscdInvalidate {
···285286foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow", { binmode => ":utf8" }) : ()) {
287 chomp $line;
288- my ($name, $hashedPassword, @rest) = split(':', $line, -9);
289- my $u = $usersOut{$name};;
0290 next if !defined $u;
291- $hashedPassword = "!" if !$spec->{mutableUsers};
292- $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME
293- chomp $hashedPassword;
294- push @shadowNew, join(":", $name, $hashedPassword, @rest) . "\n";
295- $shadowSeen{$name} = 1;
0296}
297298foreach my $u (values %usersOut) {
299 next if defined $shadowSeen{$u->{name}};
300 my $hashedPassword = "!";
301 $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword};
00302 # FIXME: set correct value for sp_lstchg.
303- push @shadowNew, join(":", $u->{name}, $hashedPassword, "1::::::") . "\n";
304}
305306updateFile("/etc/shadow", \@shadowNew, 0640);
···4use File::Slurp;
5use Getopt::Long;
6use JSON;
7+use DateTime;
89# Keep track of deleted uids and gids.
10my $uidMapFile = "/var/lib/nixos/uid-map";
···21 my ($path, $contents, $perms) = @_;
22 return if $is_dry;
23 write_file($path, { atomic => 1, binmode => ':utf8', perms => $perms // 0644 }, $contents) or die;
24+}
25+26+# Converts an ISO date to number of days since 1970-01-01
27+sub dateToDays {
28+ my ($date) = @_;
29+ my ($year, $month, $day) = split('-', $date, -3);
30+ my $dt = DateTime->new(
31+ year => $year,
32+ month => $month,
33+ day => $day,
34+ hour => 0,
35+ minute => 0,
36+ second => 0,
37+ time_zone => 'UTC',
38+ );
39+ return $dt->epoch / 86400;
40}
4142sub nscdInvalidate {
···302303foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow", { binmode => ":utf8" }) : ()) {
304 chomp $line;
305+ # struct name copied from `man 3 shadow`
306+ my ($sp_namp, $sp_pwdp, $sp_lstch, $sp_min, $sp_max, $sp_warn, $sp_inact, $sp_expire, $sp_flag) = split(':', $line, -9);
307+ my $u = $usersOut{$sp_namp};;
308 next if !defined $u;
309+ $sp_pwdp = "!" if !$spec->{mutableUsers};
310+ $sp_pwdp = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME
311+ $sp_expire = dateToDays($u->{expires}) if defined $u->{expires};
312+ chomp $sp_pwdp;
313+ push @shadowNew, join(":", $sp_namp, $sp_pwdp, $sp_lstch, $sp_min, $sp_max, $sp_warn, $sp_inact, $sp_expire, $sp_flag) . "\n";
314+ $shadowSeen{$sp_namp} = 1;
315}
316317foreach my $u (values %usersOut) {
318 next if defined $shadowSeen{$u->{name}};
319 my $hashedPassword = "!";
320 $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword};
321+ my $expires = "";
322+ $expires = dateToDays($u->{expires}) if defined $u->{expires};
323 # FIXME: set correct value for sp_lstchg.
324+ push @shadowNew, join(":", $u->{name}, $hashedPassword, "1::::", $expires, "") . "\n";
325}
326327updateFile("/etc/shadow", \@shadowNew, 0640);
···311 '';
312 };
313314+ expires = mkOption {
315+ type = types.nullOr (types.strMatching "[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}");
316+ default = null;
317+ description = lib.mdDoc ''
318+ Set the date on which the user's account will no longer be
319+ accessible. The date is expressed in the format YYYY-MM-DD, or null
320+ to disable the expiry.
321+ A user whose account is locked must contact the system
322+ administrator before being able to use the system again.
323+ '';
324+ };
325 };
326327 config = mkMerge
···449 name uid group description home homeMode createHome isSystemUser
450 password passwordFile hashedPassword
451 autoSubUidGidRange subUidRanges subGidRanges
452+ initialPassword initialHashedPassword expires;
453 shell = utils.toShellPath u.shell;
454 }) cfg.users;
455 groups = attrValues cfg.groups;
···648 install -m 0700 -d /root
649 install -m 0755 -d /home
650651+ ${pkgs.perl.withPackages (p: [ p.FileSlurp p.JSON p.DateTime ])}/bin/perl \
652 -w ${./update-users-groups.pl} ${spec}
653 '';
654 };