From ca0c46ace5329a94467896a86552c8cdb2f1d4c8 Mon Sep 17 00:00:00 2001 From: Emily Date: Thu, 30 Jan 2025 00:55:52 +0000 Subject: [PATCH] {activation-scripts,activate-system}: purify environment again --- modules/services/activate-system/default.nix | 42 +++++++++++++++++++- modules/system/activation-scripts.nix | 33 +++++++++++---- tests/nix-enable.nix | 4 ++ 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/modules/services/activate-system/default.nix b/modules/services/activate-system/default.nix index df0b48e4..f935ee1b 100644 --- a/modules/services/activate-system/default.nix +++ b/modules/services/activate-system/default.nix @@ -1,5 +1,35 @@ { config, lib, pkgs, ... }: +let + activationPath = + lib.makeBinPath ( + [ + pkgs.gnugrep + pkgs.coreutils + ] ++ lib.optionals config.nix.enable [ config.nix.package ] + ) + + lib.optionalString (!config.nix.enable) '' + $( + # If `nix.enable` is off, there might be an unmanaged Nix + # installation (say in `/nix/var/nix/profiles/default`) that + # activation scripts (such as Home Manager) want to find on the + # `$PATH`. Search for it directly to avoid polluting the + # activation script environment with everything on the + # `environment.systemPath`. + if nixEnvPath=$( + PATH="${config.environment.systemPath}" command -v nix-env + ); then + printf ':' + ${lib.getExe' pkgs.coreutils "dirname"} -- "$( + ${lib.getExe' pkgs.coreutils "readlink"} \ + --canonicalize-missing \ + -- "$nixEnvPath" + )" + fi + )'' + + ":/usr/bin:/bin:/usr/sbin:/sbin"; +in + { imports = [ (lib.mkRemovedOptionModule [ "services" "activate-system" "enable" ] "The `activate-system` service is now always enabled as it is necessary for a working `nix-darwin` setup.") @@ -10,7 +40,17 @@ script = '' set -e set -o pipefail - export PATH="${pkgs.gnugrep}/bin:${pkgs.coreutils}/bin:@out@/sw/bin:/usr/bin:/bin:/usr/sbin:/sbin" + + PATH="${activationPath}" + + export PATH + export USER=root + export LOGNAME=root + export HOME=~root + export MAIL=/var/mail/root + export SHELL=$BASH + export LANG=C + export LC_CTYPE=UTF-8 systemConfig=$(cat ${config.system.profile}/systemConfig) diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index 9ab1b7b7..646929da 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -14,10 +14,12 @@ let }; activationPath = - lib.makeBinPath [ - pkgs.gnugrep - pkgs.coreutils - ] + lib.makeBinPath ( + [ + pkgs.gnugrep + pkgs.coreutils + ] ++ lib.optionals config.nix.enable [ config.nix.package ] + ) + lib.optionalString (!config.nix.enable) '' $( # If `nix.enable` is off, there might be an unmanaged Nix @@ -37,8 +39,7 @@ let )" fi )'' - + ":@out@/sw/bin:/usr/bin:/bin:/usr/sbin:/sbin"; - + + ":/usr/bin:/bin:/usr/sbin:/sbin"; in { @@ -80,18 +81,36 @@ in ]; system.activationScripts.script.text = '' - #! ${stdenv.shell} + #!/usr/bin/env -i ${stdenv.shell} + # shellcheck shell=bash + # shellcheck disable=SC2096 + set -e set -o pipefail PATH="${activationPath}" + export PATH + export USER=root + export LOGNAME=root + export HOME=~root + export MAIL=/var/mail/root + export SHELL=$BASH + export LANG=C + export LC_CTYPE=UTF-8 systemConfig=@out@ # Ensure a consistent umask. umask 0022 + cd / + + if [[ $(id -u) -ne 0 ]]; then + printf >&2 '\e[1;31merror: `activate` must be run as root\e[0m\n' + exit 2 + fi + ${cfg.activationScripts.preActivation.text} ${cfg.activationScripts.etcChecks.text} diff --git a/tests/nix-enable.nix b/tests/nix-enable.nix index e052aa2f..bf84d556 100644 --- a/tests/nix-enable.nix +++ b/tests/nix-enable.nix @@ -12,5 +12,9 @@ printf >&2 'checking for late‐bound Nix lookup in /activate\n' grep nixEnvPath= ${config.out}/activate + + printf >&2 'checking for late‐bound Nix lookup in activation service\n' + script=$(cat ${config.out}/Library/LaunchDaemons/org.nixos.activate-system.plist | awk -F'[< ]' '$6 ~ "^/nix/store/.*" {print $6}') + grep nixEnvPath= "$script" ''; }