nix-darwin
nix-darwin copied to clipboard
multi user install does not work in zsh (works in bash)
That took me the whole day to figure out. Installation runs smoothly, and installs what's in darwin-configuration.nix, but when I type this in zsh
$ darwin-rebuild switch
building the system configuration...
error: file 'darwin-config' was not found in the Nix search path (add it using $NIX_PATH or -I), at /nix/store/i5gakh46n16945x7yllxwha24dy9m1gc-darwin/darwin/default.nix:1:40
(use '--show-trace' to show detailed location information)
$
Whereas under bash...
~ AusNet$ darwin-rebuild switch
building the system configuration...
warning: Nix search path entry '/Users/AusNet/.nix-defexpr/channels/darwin' does not exist, ignoring
Password:
warning: Nix search path entry '/Users/AusNet/.nix-defexpr/channels/darwin' does not exist, ignoring
user defaults...
setting up user launchd services...
setting up ~/Applications...
setting up /etc...
warning: not linking environment.etc."nix/nix.conf" because /etc/nix/nix.conf exists, skipping...
warning: not linking environment.etc."zprofile" because /etc/zprofile exists, skipping...
warning: not linking environment.etc."zshrc" because /etc/zshrc exists, skipping...
system defaults...
setting up launchd services...
reloading nix-daemon...
configuring networking...
$
Phew!
Also: could different users have different darwin-configuration.nix? It seems not?
I believe this output is likely indicative of your problem with zsh:
warning: not linking environment.etc."nix/nix.conf" because /etc/nix/nix.conf exists, skipping...
warning: not linking environment.etc."zprofile" because /etc/zprofile exists, skipping...
warning: not linking environment.etc."zshrc" because /etc/zshrc exists, skipping...
I could be wrong as I think /etc/zshenv sets $NIX_PATH but it's worth a shot to move/backup those files and run darwin-rebuild switch again in bash to allow nix-darwin to properly link those init files:
sudo mv /etc/nix/nix.conf /etc/nix/nix.conf.backup-before-nix-darwin
sudo mv /etc/zprofile /etc/zprofile.backup-before-nix-darwin
sudo mv /etc/zshrc /etc/zshrc.backup-before-nix-darwin
In bash:
darwin-rebuild switch
Then you should be able to verify the links:
This issue has added salience since macOS Catalina switched the default shell to zsh. The above advice worked for me to get everything set up correctly for both zsh and fish, albeit in a single-user setup. The full process:
- After running the
nix-darwininstaller script, edit~/.nixpkgs/darwin-configuration.nixto uncomment the relevant lines for the shells you want to use:
Write the file.programs.zsh.enable = true; programs.fish.enable = true; - Move the Nix and shell configuration files as @jrolfs instructed above so that
nix-darwinwill write its own:sudo mv /etc/nix/nix.conf /etc/nix/nix.conf.backup-before-nix-darwin sudo mv /etc/zprofile /etc/zprofile.backup-before-nix-darwin sudo mv /etc/zshrc /etc/zshrc.backup-before-nix-darwin - Use
bashto rebuild. In Catalina, Terminal runszshby default, so you have to runbashexplicitly:> bash bash-3.2$ source /etc/static/bashrc bash-3.2$ darwin-rebuild switch
You should now be able to run darwin-rebuild and use the rest of the nix-darwin functionality from bash, zsh, and fish (modulo which shells you enabled). Presumably something similar will work for a multi-user setup if you start by modifying the multi-user darwin-configuration.nix. (That said, I couldn't get a multi-user Nix to install on Catalina; even getting a single-user installation working is a bit of an ordeal at present.)
Sorry for re-open this topic, I got the same issue in Big Sur, and set nix.nixPath is not worked.
I'm also experiencing this issue on Big Sur. My shell is managed by nix-darwin (programs.zsh.enable = true;), my user shell is set to /etc/profiles/per-user/tristan/bin/zsh.
When trying to run darwin-rebuild switch, I get:
@NightmareMoon:~ ❯ darwin-rebuild switch
building the system configuration...
error: file 'darwin-config' was not found in the Nix search path (add it using $NIX_PATH or -I), at /nix/store/0882sb0p0lhf4b964apsbbfpijl94ngz-darwin/darwin/default.nix:2:19
(use '--show-trace' to show detailed location information)
This output suggest zsh isn't being configured to source the nix-darwin environment as it should...
@NightmareMoon:~ ❯ echo $__ETC_ZSHENV_SOURCED
1
@NightmareMoon:~ ❯ echo $__NIX_DARWIN_SET_ENVIRONMENT_DONE
0
I quickly identified the issue after running dtruss on zsh and finding out what exactly is being loaded.
The first configuration sourced is /etc/zshenv, which in turn sources /nix/store/fal6fp5fzkjfrmls5m63rsvvg566sc3j-set-environment and sets NIX_PATH to the expected value containing darwin-config=.... However, later in the load order, /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh is called from /etc/zshrc which completely overrides NIX_PATH and hardcodes it to nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixpkgs:/nix/var/nix/profiles/per-user/root/channels, wiping out darwin-config.
The load order for setting the nix-darwin environment seems to be wrong. By looking at how it is done with bash, /nix/store/fal6fp5fzkjfrmls5m63rsvvg566sc3j-set-environment should not be sourced in in /etc/zshenv. Rather, it should be sourced in /etc/static/zshrc which is called by /etc/zshrc after having called /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh.
I see, that's indeed different compared to bash, there the installer ensures that the declarative snippets are always loaded last. However since zsh has a separate file for general environment setup which is always loaded first, resulting it things getting overwritten.
@ericpashman's solution fixed this issue for me! I'm on Catalina still, and I had no $NIX_PATH set, so all environment variables, system packages, etc, were all absent
I've been having this same problem. Unfortunately, I didn't see this issue before I started debugging, so I ended up reproducing all of the work that @starcraft66 did in tracing the load order of the files. My solution is to add the following two entries to my nix-darwin config:
programs.zsh.shellInit = ''export OLD_NIX_PATH="$NIX_PATH";'';
programs.zsh.interactiveShellInit = ''
if [ -n "$OLD_NIX_PATH" ]; then
if [ "$NIX_PATH" != "$OLD_NIX_PATH" ]; then
NIX_PATH="$OLD_NIX_PATH"
fi
unset OLD_NIX_PATH
fi
'';
The shellInit line is added to /etc/zshenv just after the environment is set up by nix-darwin, allowing us to store the nix-path in a variable that won't get overwritten. The interactiveShellInit is added to /etc/static/zshrc, which is sourced at the very end of /etc/zshrc, i.e. after nix-daemon.sh has clobbered our NIX_PATH variable. With this, we can restore the NIX_PATH variable to the correct value. It is a bit of a hack though, and really depends on the order in which these scripts are run (though it should be pretty stable due to zsh's load order, which shouldn't change).
I am wondering though what the purpose of the nix-daemon.sh script is. It looks like nix-darwin has a setting (services.nix-daemon.enable) that as far as I can tell, does the same thing as what is in the script. Is the proper solution to this issue as simple as moving /etc/zshrc to /etc/zshrc.local and removing the nix-daemon lines which were added by the nix installer? Am I correct in thinking that nix-daemon.sh and nix-darwin's services.nix-daemon.enable do the same thing?