From 6ea1fff01def38b9bb8d6aa41595e338c9b023c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 7 Dec 2020 20:59:03 +0100 Subject: [PATCH] nixos/nscd: start in early boot 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. --- nixos/modules/services/system/nscd.nix | 43 +++++++++++-------- .../activation/switch-to-configuration.pl | 10 ++++- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix index 00a87e788dc4d..43b05c5b14d12 100644 --- a/nixos/modules/services/system/nscd.nix +++ b/nixos/modules/services/system/nscd.nix @@ -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 @@ -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" + ]; + }; }; - }; } diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl index 9e5b760434a05..1cfe29f7200a8 100755 --- a/nixos/modules/system/activation/switch-to-configuration.pl +++ b/nixos/modules/system/activation/switch-to-configuration.pl @@ -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") { @@ -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"; } @@ -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.