zsh running sudo does not inherit $PATH nor other important environment variables.
This is particularly annoying when running #!/usr/bin/env zsh scripts as root inside nix-shell.
This is not an issue with the default shell, Bash.
This file calls setEnvironment which overwrites the environment variables, including $PATH.
The call is conditional, guarded by $__ETC_ZSHENV_SOURCED and $__NIXOS_SET_ENVIRONMENT_DONE from being sourced again.
So, as intended, it's not called for regular (non-sudo) nested shells.
However, sudo clears these variables, but not $PATH.
This is not an issue for Bash because bash -c does not source any files by default.[^1]
[^1]: Unless $BASH_ENV is set, but let's keep these nuances aside.
Possible Solutions
Drop /etc/zshenv. We don't have it for Bash (because it's not possible), so maybe we don't need it for the Z shell either?
It would be sufficient to keep only /etc/zprofile, akin to /etc/profile for Bash.
Does this option have any unwanted implications?
Make sudo pass $__ETC_ZSHENV_SOURCED/$__NIXOS_SET_ENVIRONMENT_DONE variables by default by adding it to env_keep in the /etc/sudoers file.
Tho, to be honest, I don't like this solution.
Workaround
Set a guardian variable manually to prevent setEnvironment from being sourced.
cc @Mic92
Issue
zsh
runningsudo
does not inherit$PATH
nor other important environment variables. This is particularly annoying when running#!/usr/bin/env zsh
scripts as root insidenix-shell
. This is not an issue with the default shell, Bash.Steps to reproduce
Cause
This is caused by sourcing
/etc/zshenv
unconditionally when runningzsh
, even if-c
is passed.https://github.com/NixOS/nixpkgs/blob/7eceafd98fcc18e57305ae82f2e6cba51b06ceac/nixos/modules/programs/zsh/zsh.nix#L180-L189
This file calls
setEnvironment
which overwrites the environment variables, including$PATH
. The call is conditional, guarded by$__ETC_ZSHENV_SOURCED
and$__NIXOS_SET_ENVIRONMENT_DONE
from being sourced again. So, as intended, it's not called for regular (non-sudo
) nested shells. However,sudo
clears these variables, but not$PATH
.This is not an issue for Bash because
bash -c
does not source any files by default.[^1][^1]: Unless
$BASH_ENV
is set, but let's keep these nuances aside.Possible Solutions
Drop
/etc/zshenv
. We don't have it for Bash (because it's not possible), so maybe we don't need it for the Z shell either? It would be sufficient to keep only/etc/zprofile
, akin to/etc/profile
for Bash. Does this option have any unwanted implications?Make
sudo
pass$__ETC_ZSHENV_SOURCED
/$__NIXOS_SET_ENVIRONMENT_DONE
variables by default by adding it toenv_keep
in the/etc/sudoers
file. Tho, to be honest, I don't like this solution.Workaround
Set a guardian variable manually to prevent
setEnvironment
from being sourced.