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-darwin
installer script, edit~/.nixpkgs/darwin-configuration.nix
to 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-darwin
will 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
bash
to rebuild. In Catalina, Terminal runszsh
by default, so you have to runbash
explicitly:> 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?