Getting rid of nix-daemon related files on macOS

I have installed nixpkgs on macOS as a single user and notice these two files:

~/.nix-profile/Library/LaunchDaemons/org.nixos.nix-daemon.plist
~/.nix-profile/etc/profile.d/nix-daemon.sh

Is there any way to avoid these files? Specifically the last one is bothering me because I would like to source ~/.nix-profile/etc/profile.d/*.sh (in my shell startup) so that derivations can create files in this location when they are related to “shell customizations”.

I currently take extra steps to skip nix-daemon.sh, but I would prefer to just not have the file created in the first place (seems cleaner).

The reason I don’t source nix-daemon.sh is that both this file, and nix.sh append the same things to environment variables like PATH, so I end up with ~/.nix-profile/bin twice in my PATH.

The LaunchDaemon file is harmless as launchd hasn’t been instructed to load it. The multi-user install script symlinks that file into /Library/LaunchDaemons (well, it symlinks it from the default profile, not from your ~/.nix-profile) so that way it will get loaded automatically, so without that step the file does nothing.

As for nix-daemon.sh, this is here for the same reason the LaunchDaemon is, which is that single-user and multi-user installs both install the same nix package, and that package is what includes this file. The single-user vs multi-user install only differs in how it sets up the system to interact with Nix.

If you really don’t want it, I suppose you could set up some wrapper derivation around nix that explicitly filters that one path out. Maybe something like

buildEnv {
  name = "single-user-nix";
  paths = [ nix ];
  # remove multi-user files
  postBuild = ''
    # $out/etc is a symlink. Remove it and replace it with deeper links.
    # There's probably a better way to do this that doesn't make assumptions
    # about the contents of this symlink.
    oldLink=$(readlink $out/etc)
    rm $out/etc
    mkdir -p $out/etc/profile.d
    ln -s $oldLink/profile.d/nix.sh $out/etc/profile.d/nix.sh
    # $out/Library just contains the launch daemon
    rm $out/Library
  '';
}

Having said that, I honestly think it’s much simpler just to filter nix-daemon.sh out from your local sourcing of ~/.nix-profile/etc/profile.d/*.sh.

Also, I do have to ask, are there any existing packages that dump files into etc/profile.d or are you trying to come up with your own convention? My guess is the latter because AFAIK Bash has no built-in mechanism of sourcing files from a folder. Given that you’re coming up with your own convention, you could just use a different folder entirely, like ~/.nix-profile/etc/profile.d/auto/*.sh instead.

Agree, I had hoped for an option somewhere. If I have to make customizations, they might as well exist in ~/.profile.

Mostly the latter, but yes, there are a few packages that install into profile.d/, for example bash-completion, and sourcing all files from profile.d/ is actually suggested in nix manual (last code listing in the linked section).

Bash completion goes in etc/bash_completion.d, not in etc/profile.d.

Oh boy. We should do something about that. This was probably written for NixOS where nix is a system package rather than in your profile. Heck, I expect that even on a multi-user install nix will be in the default profile instead of the per-user one, though in both cases this means scripts provided by system / root-installed packages won’t be sourced this way.

One possibility is to submit a PR adding the same header to nix.sh as exists on nix-daemon.sh:

# Only execute this file once per shell.
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
__ETC_PROFILE_NIX_SOURCED=1

and then to modify the manual suggestion to document that you must do this ~/.nix-profile/etc/profile.d/*.sh sourcing after directly sourcing the appropriate nix.sh or nix-daemon.sh on a non-NixOS system. That way re-sourcing either one will do nothing.

The setup/initialization file is installed as ~/.nix-profile/etc/profile.d/bash_completion.sh (and /etc/profile.d/bash_completion.sh on Ubuntu).

The etc/bash_completion.d is the obsolete directory for eagerly loaded completion files.

I do think it would be more elegant if a) nixpkgs would know whether or not it should install files for multi-user support (so I do not have unnecessary files in ~/.nix-profile) and b) that there was a designated “drop” directory for shell initialization.

There might be some challenges with the latter because of different shells, and the order in which they are sourced (e.g. should it be 000-nix.sh to ensure it gets sourced first?), but being able for derivations to install shell initialization code would not only make install/uninstall not require having to manually update ~/.profile but also that we can limit what needs to go into the global namespace, as a generated profile drop can reference dependencies directly using their nix store path.