Skip to content

Commit

Permalink
nixos/nscd: start in early boot
Browse files Browse the repository at this point in the history
Services that have dynamic users require nscd to resolve users
via pam_systemd. Those services might not even create
their own dynamic users itself i.e. iptables.
To make sure nscd is always started when this is happening we move
nscd to sysinit.target and make sure that it is always started before
starting/reloading/restarting any other service.
  • Loading branch information
Mic92 committed Apr 4, 2022
1 parent e281389 commit 6ea1fff
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 19 deletions.
43 changes: 25 additions & 18 deletions nixos/modules/services/system/nscd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,20 @@ in
systemd.services.nscd =
{ description = "Name Service Cache Daemon";

before = [ "nss-lookup.target" "nss-user-lookup.target" ];
wants = [ "nss-lookup.target" "nss-user-lookup.target" ];
wantedBy = [ "multi-user.target" ];

environment = { LD_LIBRARY_PATH = nssModulesPath; };

# We need system users to be resolveable in late-boot. nscd is the proxy between
# nss-modules in NixOS and thus if you have nss-modules providing system users
# (e.g. when using DynamicUser) then nscd needs to be available before late-boot is ready
# We add a dependency of sysinit.target to nscd to ensure
# these units are started after nscd is fully started.
unitConfig.DefaultDependencies = false;
wantedBy = [ "sysinit.target" ];
before = [ "sysinit.target" "shutdown.target" ];
conflicts = [ "shutdown.target" ];
wants = [ "local-fs.target" ];
after = [ "local-fs.target" ];

restartTriggers = [
config.environment.etc.hosts.source
config.environment.etc."nsswitch.conf".source
Expand All @@ -68,20 +76,19 @@ in
# privileges after all the NSS modules have read their configuration
# files. So prefix the ExecStart command with "!" to prevent systemd
# from dropping privileges early. See ExecStart in systemd.service(5).
serviceConfig =
{ ExecStart = "!@${nscd}/sbin/nscd nscd";
Type = "forking";
DynamicUser = true;
RuntimeDirectory = "nscd";
PIDFile = "/run/nscd/nscd.pid";
Restart = "always";
ExecReload =
[ "${nscd}/sbin/nscd --invalidate passwd"
"${nscd}/sbin/nscd --invalidate group"
"${nscd}/sbin/nscd --invalidate hosts"
];
};
serviceConfig = {
ExecStart = "!@${nscd}/sbin/nscd nscd";
Type = "forking";
DynamicUser = true;
RuntimeDirectory = "nscd";
PIDFile = "/run/nscd/nscd.pid";
Restart = "always";
ExecReload = [
"${nscd}/sbin/nscd --invalidate passwd"
"${nscd}/sbin/nscd --invalidate group"
"${nscd}/sbin/nscd --invalidate hosts"
];
};
};

};
}
10 changes: 9 additions & 1 deletion nixos/modules/system/activation/switch-to-configuration.pl
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ sub filter_units {
}

my @units_to_stop_filtered = filter_units(\%units_to_stop);

my $start_nscd = delete $unitsToStart{"nscd.service"};

# Show dry-run actions.
if ($action eq "dry-activate") {
Expand Down Expand Up @@ -722,6 +722,7 @@ sub filter_units {
print STDERR "would restart the following units: ", join(", ", sort(keys(%units_to_restart))), "\n";
}
my @units_to_start_filtered = filter_units(\%units_to_start);
print STDERR "would start nscd\n" if $start_nscd;
if (scalar(@units_to_start_filtered)) {
print STDERR "would start the following units: ", join(", ", @units_to_start_filtered), "\n";
}
Expand Down Expand Up @@ -822,6 +823,13 @@ sub filter_units {
print STDERR "setting up tmpfiles\n";
system("$new_systemd/bin/systemd-tmpfiles", "--create", "--remove", "--exclude-prefix=/dev") == 0 or $res = 3;

# We need to start nscd before any other service, since they might need
# to resolve users/groups only exposed by nss modules (i.e. DynamicUser via nss_systemd)
if ($start_nscd) {
print STDERR "starting nscd\n";
system("@systemd@/bin/systemctl", "start", "nscd.service") == 0 or $res = 4;
}

# Before reloading we need to ensure that the units are still active. They may have been
# deactivated because one of their requirements got stopped. If they are inactive
# but should have been reloaded, the user probably expects them to be started.
Expand Down

0 comments on commit 6ea1fff

Please sign in to comment.