From 44e15166e02c274c46a34424e85e23d60f724bfa Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Wed, 20 May 2026 23:34:07 -0400 Subject: [PATCH] nixos/system-environment: Export PATH to systemd transient environment Since e73170e38a27be96071b8da0f18c0e2b150dc627, we no longer patch systemd to prevent it resetting `PATH` for generators. Generators that depended on this deviating behavior will no longer work, which ironically includes the upstream `systemd-xdg-autostart-generator`. Previously, generators would see systemd's actual environment, which included environment variables set for the PAM session like `PATH`. To preserve the old behavior *exactly*, we'd really want to be replicating exactly what the `systemd-user` PAM service sets up, which could technically include things other than just what we put in `/etc/pam/environment`. But this is arguably a systemd bug (either because `systemd-xdg-autostart-generator` shouldn't use the generator's `PATH`, or because systemd should pass along the `PATH` it got from PAM), so for now, we can keep it simple and fix it by replicating what `/etc/pam/environment` does in `/etc/environment.d`. --- nixos/modules/config/system-environment.nix | 41 +++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/nixos/modules/config/system-environment.nix b/nixos/modules/config/system-environment.nix index aaf5e521350f..96cd67d93d40 100644 --- a/nixos/modules/config/system-environment.nix +++ b/nixos/modules/config/system-environment.nix @@ -11,6 +11,23 @@ let cfg = config.environment; + suffixedVariables = lib.flip lib.mapAttrs cfg.profileRelativeSessionVariables ( + envVar: suffixes: + lib.flip lib.concatMap cfg.profiles (profile: map (suffix: "${profile}${suffix}") suffixes) + ); + + combinedSessionVars = lib.zipAttrsWith (n: lib.concatLists) [ + # Make sure security wrappers are prioritized without polluting + # shell environments with an extra entry. Sessions which depend on + # pam for its environment will otherwise have eg. broken sudo. In + # particular Gnome Shell sometimes fails to source a proper + # environment from a shell. + { PATH = [ config.security.wrapperDir ]; } + + (lib.mapAttrs (n: lib.toList) cfg.sessionVariables) + suffixedVariables + ]; + in { @@ -73,13 +90,11 @@ in }; config = { + environment.etc."environment.d/50-systemd-path.conf".text = '' + PATH="${lib.concatStringsSep ":" combinedSessionVars.PATH}" + ''; environment.etc."pam/environment".text = let - suffixedVariables = lib.flip lib.mapAttrs cfg.profileRelativeSessionVariables ( - envVar: suffixes: - lib.flip lib.concatMap cfg.profiles (profile: map (suffix: "${profile}${suffix}") suffixes) - ); - # We're trying to use the same syntax for PAM variables and env variables. # That means we need to map the env variables that people might use to their # equivalent PAM variable. @@ -88,21 +103,7 @@ in pamVariable = n: v: ''${n} DEFAULT="${lib.concatStringsSep ":" (map replaceEnvVars (lib.toList v))}"''; - pamVariables = lib.concatStringsSep "\n" ( - lib.mapAttrsToList pamVariable ( - lib.zipAttrsWith (n: lib.concatLists) [ - # Make sure security wrappers are prioritized without polluting - # shell environments with an extra entry. Sessions which depend on - # pam for its environment will otherwise have eg. broken sudo. In - # particular Gnome Shell sometimes fails to source a proper - # environment from a shell. - { PATH = [ config.security.wrapperDir ]; } - - (lib.mapAttrs (n: lib.toList) cfg.sessionVariables) - suffixedVariables - ] - ) - ); + pamVariables = lib.concatStringsSep "\n" (lib.mapAttrsToList pamVariable combinedSessionVars); in '' ${pamVariables}