nix-darwin icon indicating copy to clipboard operation
nix-darwin copied to clipboard

multi user install does not work in zsh (works in bash)

Open dmvianna opened this issue 5 years ago • 8 comments

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?

dmvianna avatar Aug 27 '19 06:08 dmvianna

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:

Screen Shot 2019-10-07 at 2 50 55 PM

jrolfs avatar Oct 07 '19 21:10 jrolfs

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:

  1. After running the nix-darwin installer script, edit ~/.nixpkgs/darwin-configuration.nix to uncomment the relevant lines for the shells you want to use:
    programs.zsh.enable = true;
    programs.fish.enable = true;
    
    Write the file.
  2. 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
    
  3. Use bash to rebuild. In Catalina, Terminal runs zsh by default, so you have to run bash 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.)

ericpashman avatar Dec 03 '19 02:12 ericpashman

Sorry for re-open this topic, I got the same issue in Big Sur, and set nix.nixPath is not worked.

c4dr01d avatar Jan 12 '21 10:01 c4dr01d

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

starcraft66 avatar Jan 27 '21 17:01 starcraft66

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.

starcraft66 avatar Jan 28 '21 20:01 starcraft66

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.

LnL7 avatar Jan 28 '21 23:01 LnL7

@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

rpearce avatar May 17 '21 02:05 rpearce

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?

WhiteAbeLincoln avatar Nov 20 '21 05:11 WhiteAbeLincoln