From f449242e83bd441300f009321157dd308326cfcc Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sat, 29 Sep 2018 10:55:46 -0700 Subject: [PATCH 1/8] nixos/systemd: remove activation dependency As far as I can tell, the systemd snippet hasn't depended on groups being initialized since 5d02c02a9bfd6912e4e0f700b1b35e76d1d6bd3f in 2015, when a `setfacl` call was removed. --- nixos/modules/system/boot/systemd.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 12e029ae57f..c96a502a892 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -783,7 +783,7 @@ in services.dbus.enable = true; - system.activationScripts.systemd = stringAfter [ "groups" ] + system.activationScripts.systemd = '' mkdir -m 0755 -p /var/lib/udev From 8d40083690c2d20d20c32d7d90b9fd7b7f559042 Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sat, 29 Sep 2018 11:35:00 -0700 Subject: [PATCH 2/8] nixos/stage-2: create empty machine-id at boot Previously, the activation script was responsible for ensuring that /etc/machine-id exists. However, the only time it could not already exist is during stage-2-init, not while switching configurations, because one of the first things systemd does when starting up as PID 1 is to create this file. So I've moved the initialization to stage-2-init. Furthermore, since systemd will do the equivalent of systemd-machine-id-setup if /etc/machine-id doesn't have valid contents, we don't need to do that ourselves. We _do_, however, want to ensure that the file at least exists, because systemd also uses the non-existence of this file to guess that this is a first-boot situation. In that case, systemd tries to create some symlinks in /etc/systemd/system according to its presets, which it can't do because we've already populated /etc according to the current NixOS configuration. This is not necessary for any other activation script snippets, so it's okay to do it after stage-2-init runs the activation script. None of them declare a dependency on the "systemd" snippet. Also, most of them only create files or directories in ways that obviously don't need the machine-id set. --- nixos/modules/system/boot/stage-2-init.sh | 8 ++++++++ nixos/modules/system/boot/systemd.nix | 4 ---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh index 49764b75a55..03daafa1ce4 100644 --- a/nixos/modules/system/boot/stage-2-init.sh +++ b/nixos/modules/system/boot/stage-2-init.sh @@ -152,6 +152,14 @@ ln -sfn /run/booted-system /nix/var/nix/gcroots/booted-system @shell@ @postBootCommands@ +# Ensure systemd doesn't try to populate /etc, by forcing its first-boot +# heuristic off. It doesn't matter what's in /etc/machine-id for this purpose, +# and systemd will immediately fill in the file when it starts, so just +# creating it is enough. This `: >>` pattern avoids forking and avoids changing +# the mtime if the file already exists. +: >> /etc/machine-id + + # Reset the logging file descriptors. exec 1>&$logOutFd 2>&$logErrFd exec {logOutFd}>&- {logErrFd}>&- diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index c96a502a892..94bbd6180a8 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -787,10 +787,6 @@ in '' mkdir -m 0755 -p /var/lib/udev - if ! [ -e /etc/machine-id ]; then - ${systemd}/bin/systemd-machine-id-setup - fi - # Keep a persistent journal. Note that systemd-tmpfiles will # set proper ownership/permissions. mkdir -m 0700 -p /var/log/journal From 10e865051548f39e8bff205ea09a648c49304d11 Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sat, 29 Sep 2018 12:16:45 -0700 Subject: [PATCH 3/8] nixos/systemd: let journald create /var/log/journal The default value for journald's Storage option is "auto", which determines whether to log to /var/log/journal based on whether that directory already exists. So NixOS has been unconditionally creating that directory in activation scripts. However, we can get the same behavior by configuring journald.conf to set Storage to "persistent" instead. In that case, journald will create the directory itself if necessary. --- nixos/modules/system/boot/systemd.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 94bbd6180a8..c0d1bd75065 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -747,6 +747,7 @@ in "systemd/journald.conf".text = '' [Journal] + Storage=persistent RateLimitInterval=${config.services.journald.rateLimitInterval} RateLimitBurst=${toString config.services.journald.rateLimitBurst} ${optionalString (config.services.journald.console != "") '' @@ -786,10 +787,6 @@ in system.activationScripts.systemd = '' mkdir -m 0755 -p /var/lib/udev - - # Keep a persistent journal. Note that systemd-tmpfiles will - # set proper ownership/permissions. - mkdir -m 0700 -p /var/log/journal ''; users.users.systemd-network.uid = config.ids.uids.systemd-network; From bbc0f6f005fa856d914711149838d2f75f9fe41b Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sun, 30 Sep 2018 11:05:47 -0700 Subject: [PATCH 4/8] nixos/systemd: don't create /var/lib/udev As far as I can tell, systemd has never used this directory, so I think this is a holdover from before udev merged into systemd. --- nixos/modules/system/boot/systemd.nix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index c0d1bd75065..f1b8878d04e 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -784,11 +784,6 @@ in services.dbus.enable = true; - system.activationScripts.systemd = - '' - mkdir -m 0755 -p /var/lib/udev - ''; - users.users.systemd-network.uid = config.ids.uids.systemd-network; users.groups.systemd-network.gid = config.ids.gids.systemd-network; users.users.systemd-resolve.uid = config.ids.uids.systemd-resolve; From ae3d3b0fffe4827a7f126368e01fd8c2c8a4c7fe Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sat, 29 Sep 2018 12:28:54 -0700 Subject: [PATCH 5/8] nixos/polkit: use tmpfiles to clean old dirs These don't need to get cleaned up during activation; that can wait until systemd-tmpfiles-setup runs. --- nixos/modules/security/polkit.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nixos/modules/security/polkit.nix b/nixos/modules/security/polkit.nix index 04685f2c9ea..7f1de81d5b7 100644 --- a/nixos/modules/security/polkit.nix +++ b/nixos/modules/security/polkit.nix @@ -88,11 +88,11 @@ in "polkit-agent-helper-1".source = "${pkgs.polkit.out}/lib/polkit-1/polkit-agent-helper-1"; }; - system.activationScripts.polkit = - '' - # Probably no more needed, clean up - rm -rf /var/lib/{polkit-1,PolicyKit} - ''; + systemd.tmpfiles.rules = [ + # Probably no more needed, clean up + "R /var/lib/polkit-1" + "R /var/lib/PolicyKit" + ]; users.users.polkituser = { description = "PolKit daemon"; From dab5c632bd2664555292665192cd9f096b5c5bcf Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sat, 29 Sep 2018 18:02:49 -0700 Subject: [PATCH 6/8] nixos/activation: don't create /run/nix Nix 2.0 no longer uses these directories. /run/nix/current-load was moved to /nix/var/nix/current-load in 2017 (Nix commit d7653dfc6dea076ecbe00520c6137977e0fced35). Anyway, src/build-remote/build-remote.cc will create the current-load directory if it doesn't exist already. /run/nix/remote-stores seems to have been deprecated since 2014 (Nix commit b1af336132cfe8a6e4c54912cc512f8c28d4ebf3) when the documentation for $NIX_OTHER_STORES was removed, and support for it was dropped entirely in 2016 (Nix commit 4494000e04122f24558e1436e66d20d89028b4bd). --- nixos/modules/system/activation/activation-script.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index 93a1b13a81d..b7415388531 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -128,9 +128,6 @@ in '' # Various log/runtime directories. - mkdir -m 0755 -p /run/nix/current-load # for distributed builds - mkdir -m 0700 -p /run/nix/remote-stores - mkdir -m 0755 -p /var/log touch /var/log/wtmp /var/log/lastlog # must exist From 188bdfb95d7218b931f7d605ad0a5e6961dc3a34 Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sat, 29 Sep 2018 22:52:27 -0700 Subject: [PATCH 7/8] nixos/opengl: create /run/opengl-driver using tmpfiles.d Anything that uses OpenGL starts after sysinit.target, so systemd-tmpfiles runs before anything that needs these symlinks. --- nixos/modules/hardware/opengl.nix | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix index b371af353cf..46d06d71333 100644 --- a/nixos/modules/hardware/opengl.nix +++ b/nixos/modules/hardware/opengl.nix @@ -129,17 +129,17 @@ in message = "Option driSupport32Bit only makes sense on a 64-bit system."; }; - system.activationScripts.setup-opengl = - '' - ln -sfn ${package} /run/opengl-driver - ${if pkgs.stdenv.isi686 then '' - ln -sfn opengl-driver /run/opengl-driver-32 - '' else if cfg.driSupport32Bit then '' - ln -sfn ${package32} /run/opengl-driver-32 - '' else '' - rm -f /run/opengl-driver-32 - ''} - ''; + systemd.tmpfiles.rules = [ + "L+ /run/opengl-driver - - - - ${package}" + ( + if pkgs.stdenv.isi686 then + "L+ /run/opengl-driver-32 - - - - opengl-driver" + else if cfg.driSupport32Bit then + "L+ /run/opengl-driver-32 - - - - ${package32}" + else + "r /run/opengl-driver-32" + ) + ]; environment.sessionVariables.LD_LIBRARY_PATH = [ "/run/opengl-driver/lib" ] ++ optional cfg.driSupport32Bit "/run/opengl-driver-32/lib"; From b63f65aea0dea11c20e9299210af1d2ee4299b58 Mon Sep 17 00:00:00 2001 From: Jamey Sharp Date: Sat, 29 Sep 2018 23:30:02 -0700 Subject: [PATCH 8/8] nixos/pam: create wtmp/lastlog iff using pam_lastlog I think pam_lastlog is the only thing that writes to these files in practice on a modern Linux system, so in a configuration that doesn't use that module, we don't need to create these files. I used tmpfiles.d instead of activation snippets to create the logs. It's good enough for upstream and other distros; it's probably good enough for us. --- nixos/modules/security/pam.nix | 7 +++++++ nixos/modules/system/activation/activation-script.nix | 5 ----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index bef10b4fe61..926c6d77d3b 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -548,6 +548,13 @@ in environment.etc = mapAttrsToList (n: v: makePAMService v) config.security.pam.services; + systemd.tmpfiles.rules = optionals + (any (s: s.updateWtmp) (attrValues config.security.pam.services)) + [ + "f /var/log/wtmp" + "f /var/log/lastlog" + ]; + security.pam.services = { other.text = '' diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index b7415388531..cd6dc1fb820 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -128,11 +128,6 @@ in '' # Various log/runtime directories. - mkdir -m 0755 -p /var/log - - touch /var/log/wtmp /var/log/lastlog # must exist - chmod 644 /var/log/wtmp /var/log/lastlog - mkdir -m 1777 -p /var/tmp # Empty, immutable home directory of many system accounts.