nix package installed by nix-darwin ignore the PATH env passed by the parent process #16

Closed
opened 2025-12-29 04:20:48 +01:00 by adam · 4 comments
Owner

Originally created by @ryan4yin on GitHub (Dec 7, 2023).

Test Result on macOS with nix-darwin:

# remove bashrc to avoid interfering with test results
$ sudo rm -rf ~/.bashrc

# 1. bash installed by nix-darwin ignored the `PATH` env passed by the parent process
$ PATH=XXX /run/current-system/sw/bin/bash
bash-5.2$ echo $PATH
/Users/ryan/.nix-profile/bin:/etc/profiles/per-user/ryan/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin

bash-5.2$ exit
exit

# 2. macOS's builtin bash read the passed `PATH` successfully
$ PATH=XXX /bin/bash

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ echo $PATH
XXX
Originally created by @ryan4yin on GitHub (Dec 7, 2023). Test Result on macOS with nix-darwin: ``` # remove bashrc to avoid interfering with test results $ sudo rm -rf ~/.bashrc # 1. bash installed by nix-darwin ignored the `PATH` env passed by the parent process $ PATH=XXX /run/current-system/sw/bin/bash bash-5.2$ echo $PATH /Users/ryan/.nix-profile/bin:/etc/profiles/per-user/ryan/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin bash-5.2$ exit exit # 2. macOS's builtin bash read the passed `PATH` successfully $ PATH=XXX /bin/bash The default interactive shell is now zsh. To update your account to use zsh, please run `chsh -s /bin/zsh`. For more details, please visit https://support.apple.com/kb/HT208050. bash-3.2$ echo $PATH XXX ```
adam added the bug label 2025-12-29 04:20:48 +01:00
adam closed this issue 2025-12-29 04:20:48 +01:00
Author
Owner

@ryan4yin commented on GitHub (Dec 7, 2023):

Tried to make a shell wrapper with the expected PATH, but useless:

087d38487c (diff-96e580d4ef2e5de2c220100b5b9352d1c3da3ebeecc623736db9cb953798642aR158-R174)

@ryan4yin commented on GitHub (Dec 7, 2023): Tried to make a shell wrapper with the expected `PATH`, but useless: https://github.com/ryan4yin/nix-config/commit/087d38487ca5307c3afd14ca699768e68d70d39d#diff-96e580d4ef2e5de2c220100b5b9352d1c3da3ebeecc623736db9cb953798642aR158-R174
Author
Owner

@ryan4yin commented on GitHub (Dec 7, 2023):

Bash

Several config files used by Bash:

  • /etc/profile: A global configuration file that applies to all users. This file is read for login shells.
  • ~/.bash_profile or ~/.profile: A personal initialization file for login shells. This is read after /etc/profile.
  • ~/.bashrc: A personal initialization file for non-login shells. This is specific to each user and allows them to customize their shell environment.
  • /etc/bash.bashrc: A system-wide initialization file for non-login shells. This is a feature specific to Debian and Ubuntu-like systems.

The problem we have here is related to non-login shell, and we have deleted ~/.bashrc beafore we execute the test.
So /etc/bash.bashrc and /etc/bashrc may be the root cause of this problem.

/etc/bash.bashrc(used by macOS's builtin bash):

# Nix
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
    . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
fi
# End Nix

/etc/bashrc(used by nix-darwin's bash):

# /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
# This file is read for interactive shells.

[ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM"

# Only execute this file once per shell.
if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi
__ETC_BASHRC_SOURCED=1

# Don't execute this file when running in a pure nix-shell.
if [ "$IN_NIX_SHELL" = "pure" ]; then return; fi

if [ -z "$__NIX_DARWIN_SET_ENVIRONMENT_DONE" ]; then
  . /nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment
fi

# Return early if not running interactively, but after basic nix setup.
[[ $- != *i* ]] && return

# Make bash check its window size after a process completes
shopt -s checkwinsize

source /nix/store/sxwsmk522l5zm83s9y73qklfgn3w6val-nix-index-0.1.7/etc/profile.d/command-not-found.sh

# Read system-wide modifications.
if test -f /etc/bash.local; then
  source /etc/bash.local
fi

set-environment seems like a key word related to this issue, take a look at it:

/nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment:

# Prevent this file from being sourced by child shells.
export __NIX_DARWIN_SET_ENVIRONMENT_DONE=1

export PATH=$HOME/.nix-profile/bin:/etc/profiles/per-user/$USER/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
export EDITOR="nvim"
export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api"

# ...

Oh set __NIX_DARWIN_SET_ENVIRONMENT_DONE to 1 may prevent bash clear my PATH! let's test it!

# check its value, it's empty
$ echo =${__NIX_DARWIN_SET_ENVIRONMENT_DONE}=
==

# try to prevent bash import environment from `/nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment`
bash-5.2$ __NIX_DARWIN_SET_ENVIRONMENT_DONE=1 PATH=XXX /run/current-system/sw/bin/bash
bash-5.2$ echo $PATH
XXX:/Users/ryan/bin:/Users/ryan/.local/bin:/Users/ryan/go/bin

Succeeded!
So the root cause is the environemnt variable __NIX_DARWIN_SET_ENVIRONMENT_DONE is missing, it should be 1

@ryan4yin commented on GitHub (Dec 7, 2023): # Bash Several config files used by Bash: * `/etc/profile`: A global configuration file that applies to all users. This file is read for login shells. * `~/.bash_profile` or `~/.profile`: A personal initialization file for login shells. This is read after /etc/profile. * `~/.bashrc`: A personal initialization file for non-login shells. This is specific to each user and allows them to customize their shell environment. * `/etc/bash.bashrc`: A system-wide initialization file for non-login shells. This is a feature specific to Debian and Ubuntu-like systems. * nixpkgs's bash use `/etc/bashrc` as its system-wide initialization file: https://github.com/NixOS/nixpkgs/blob/nixos-23.11/pkgs/shells/bash/5.nix#L44 The problem we have here is related to non-login shell, and we have deleted `~/.bashrc` beafore we execute the test. So `/etc/bash.bashrc` and `/etc/bashrc` may be the root cause of this problem. `/etc/bash.bashrc`(used by macOS's builtin bash): ```bash # Nix if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' fi # End Nix ``` `/etc/bashrc`(used by nix-darwin's bash): ```bash # /etc/bashrc: DO NOT EDIT -- this file has been generated automatically. # This file is read for interactive shells. [ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM" # Only execute this file once per shell. if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi __ETC_BASHRC_SOURCED=1 # Don't execute this file when running in a pure nix-shell. if [ "$IN_NIX_SHELL" = "pure" ]; then return; fi if [ -z "$__NIX_DARWIN_SET_ENVIRONMENT_DONE" ]; then . /nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment fi # Return early if not running interactively, but after basic nix setup. [[ $- != *i* ]] && return # Make bash check its window size after a process completes shopt -s checkwinsize source /nix/store/sxwsmk522l5zm83s9y73qklfgn3w6val-nix-index-0.1.7/etc/profile.d/command-not-found.sh # Read system-wide modifications. if test -f /etc/bash.local; then source /etc/bash.local fi ``` `set-environment` seems like a key word related to this issue, take a look at it: `/nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment`: ```bash # Prevent this file from being sourced by child shells. export __NIX_DARWIN_SET_ENVIRONMENT_DONE=1 export PATH=$HOME/.nix-profile/bin:/etc/profiles/per-user/$USER/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin export EDITOR="nvim" export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api" # ... ``` Oh set `__NIX_DARWIN_SET_ENVIRONMENT_DONE` to `1` may prevent bash clear my `PATH`! let's test it! ```bash # check its value, it's empty $ echo =${__NIX_DARWIN_SET_ENVIRONMENT_DONE}= == # try to prevent bash import environment from `/nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment` bash-5.2$ __NIX_DARWIN_SET_ENVIRONMENT_DONE=1 PATH=XXX /run/current-system/sw/bin/bash bash-5.2$ echo $PATH XXX:/Users/ryan/bin:/Users/ryan/.local/bin:/Users/ryan/go/bin ``` Succeeded! So the root cause is the environemnt variable `__NIX_DARWIN_SET_ENVIRONMENT_DONE` is missing, it should be `1`!
Author
Owner

@ryan4yin commented on GitHub (Dec 7, 2023):

Zsh

It has the same problem as bash:

/etc/zshenv:

# /etc/zshenv: DO NOT EDIT -- this file has been generated automatically.
# This file is read for all shells.

# Only execute this file once per shell.
# But don't clobber the environment of interactive non-login children!
if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi
export __ETC_ZSHENV_SOURCED=1

# Don't execute this file when running in a pure nix-shell.
if test -n "$IN_NIX_SHELL"; then return; fi

if [ -z "$__NIX_DARWIN_SET_ENVIRONMENT_DONE" ]; then
  . /nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment
fi



# Read system-wide modifications.
if test -f /etc/zshenv.local; then
  source /etc/zshenv.local
fi
@ryan4yin commented on GitHub (Dec 7, 2023): # Zsh It has the same problem as bash: `/etc/zshenv`: ```bash # /etc/zshenv: DO NOT EDIT -- this file has been generated automatically. # This file is read for all shells. # Only execute this file once per shell. # But don't clobber the environment of interactive non-login children! if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi export __ETC_ZSHENV_SOURCED=1 # Don't execute this file when running in a pure nix-shell. if test -n "$IN_NIX_SHELL"; then return; fi if [ -z "$__NIX_DARWIN_SET_ENVIRONMENT_DONE" ]; then . /nix/store/icwhz17wr4wgwp89n95mrs1ngj859c6m-set-environment fi # Read system-wide modifications. if test -f /etc/zshenv.local; then source /etc/zshenv.local fi ```
Author
Owner

@ryan4yin commented on GitHub (Dec 7, 2023):

My default shell used in terminal is nushell, but nix-darwin do not support to set nushell as a login shell.
nix-darwin has option programs.zsh.loginShellInit but do not have a programs.nushell.loginShellInit, which caused this problem!

@ryan4yin commented on GitHub (Dec 7, 2023): My default shell used in terminal is `nushell`, but nix-darwin do not support to set `nushell` as a login shell. nix-darwin has option [programs.zsh.loginShellInit](https://daiderd.com/nix-darwin/manual/index.html#opt-programs.zsh.loginShellInit) but do not have a `programs.nushell.loginShellInit`, which caused this problem!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/nix-config-ryan4yin#16