When running as a non-login shell, zsh never gets the NixOS environment definitions that would let it find most binaries. This breaks things like git (because it can't find git-receive-pack or other helper binaries), and is a problem for running commands over ssh in general when the user you're running those commands as has zsh as their shell.
shell = pkgs.zshssh user@nix echo \$PATH/run/current-system/sw/bin is not in the $PATHWhen you log in, zsh executes its system zprofile script, which is in /nix/store/...zsh-$VERSION/etc/zprofile. This script in turn enables bash emulation and then sources /etc/profile, which sources /nix/store/...-set-environment. This latter script is responsible for setting up a whole pile of environment variables, including $PATH.
However, when running a command over ssh, this file is not executed; only zshenv is. This means that when logging in from the terminal or over ssh, everything works fine, but non-interactive ssh usage (including implicit use via, e.g., git or rsync) fails because it can't find any commands.
Bash doesn't have this problem because either /etc/profile or /etc/bashrc will be loaded regardless of how it's invoked, and /etc/bashrc sources /etc/profile if it hasn't been run already.
The solution is probably for Nix environment setup to be either written to, or sourced from, /etc/zshenv, which will be unconditionally executed on all zsh invocations.
16.09.909.238c7e0 (Flounder)nix-env (Nix) 1.11.4"16.09.909.238c7e0"What happens if the system is build with programs.zsh.enable = true in /etc/nixos/configuration.nix?
@Mic92 this resolves the problem for me! What do you think of maybe mentioning this in the configuration.nix man-page? I used the 'Example' from environment.shells thinking that's all I needed for zsh.
Anyway it'd be good for @ToxicFrog to report if that resolves the reported problem as well :).
That fixes it for me as well! I thought that evaluating pkgs.zsh would implicitly "enable" zsh as well.
To the extent that there's a bug here, then, I think it's in the documentation.
Yes we cannot generate "/etc/zshenv" from "pkgs.zsh", this has to be done by a module.
The default zshrc there is a file in the package itself: https://github.com/NixOS/nixpkgs/blob/master/pkgs/shells/zsh/default.nix#L36
Maybe zshenv could be added here as well, which then sources the file from system.build.setEnvironment
Just ran into the same problem. IMO, there are at least three different problems here:
programs.$SHELL.enable is a requirement for non-Bash shells to work correctlyprograms.$SHELL.enable is set, and error out if it is notprograms.zsh.*. It turns out this is documented in the appendix, but there are no top-level links in the manual that would tell someone it exists - I only found it by googling for the option.EDIT: Actually, it turns out that the need to enable the shell is documented here. So the real issue is the discoverability of the appendix and its contents.
Having this bug with mksh, but it's puzzling since it should be sourcing /etc/profile by default. Even tried symlinking ~/.profile to /etc/profile. It is in the list of the system's environment.shells.
Here's the relevant parts of mksh's manual:
~/.mkshrc User mkshrc profile (non-privileged interactive shells); see Startup files. The location can be changed at
compile time (for embedded systems); AOSP Android builds use /system/etc/mkshrc.
~/.profile User profile (non-privileged login shells); see Startup files near the top of this manual.
/etc/profile System profile (login shells); see Startup files.
/etc/shells Shell database.
/etc/suid_profile Suid profile (privileged shells); see Startup files.
Startup files
For the actual location of these files, see FILES. A login shell processes the system profile first. A privileged shell then
processes the suid profile. A non-privileged login shell processes the user profile next. A non-privileged interactive shell
checks the value of the ENV parameter after subjecting it to parameter, command, arithmetic and tilde (‘~’) substitution; if
unset or empty, the user mkshrc profile is processed; otherwise, if a file whose name is the substitution result exists, it is
processed; non-existence is silently ignored. A privileged shell then drops privileges if neither was the -p option given on
the command line nor set during execution of the startup files.
Just ran into this problem. Another option would be to patch zsh to look at /nix/store/..../etc/zshenv instead or something.
I've run into this too and only now found the issue.
Thank you for your contributions.
This has been automatically marked as stale because it has had no activity for 180 days.
If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.
Here are suggestions that might help resolve this more quickly:
Most helpful comment
What happens if the system is build with
programs.zsh.enable = truein /etc/nixos/configuration.nix?