I am new to nix, so sorry if this is a stupid question. 
Basically, I am trying to manage nodejs
versions in a sane way where I have one default version installed via home-manager:
home.packages = [
pkgs.nodejs_22
]
But then during some points when I am testing/debugging, I want to be able to switch to use a different nodejs version. I thought I could do this by running nix shell nixpkgs#nodejs_18
but it seems like the node version from the flake added in the nix shell
actually gets appended to the end of the PATH and so does not override the base version of node installed by home-manager.
$ node --version
v22.8.0
$ whereis node
node: /nix/store/pzbymxal2vfak7f1fiwpn4n4s5345mg3-home-manager-path/bin/node
$ nix shell -v nixpkgs#nodejs_18
$ node --version
v22.8.0
$ whereis node
node: /nix/store/pzbymxal2vfak7f1fiwpn4n4s5345mg3-home-manager-path/bin/node /nix/store/lgw9z5sf9n6pm2dqmd92z4gq4irslnq1-nodejs-18.20.4/bin/node
If I run nix shell -i ...
then I do see node 18 as expected, but it drops everything else from my PATH (which is not what I want).
Am I missing something obvious here? Is there a different way to achieve my desired functionality? Thanks!
Interestingly it seems like when using nix-shell
and an explicitly defined shell.nix
file I do not have this issue:
$ node --version
v22.8.0
$ cat shell.nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# nativeBuildInputs is usually what you want -- tools you need to run
nativeBuildInputs = with pkgs.buildPackages; [ nodejs_18 ];
}
$ nix-shell
$ node --version
v18.20.4
Okay, I think I basically figured this out. I am not using home-manager to manage my bash (I am running on Fedora, not NixOS). Because of this, I was sourcing ~/.nix-profile/etc/profile.d/hm-session-vars.sh
in my .bashrc
to get the home-manager session variables into my PATH.
When running nix shell...
the .bashrc
was getting sourced again after the new flakes were added to the path. So whatever was referenced in my .bashrc
was taking preference over the new things added in the shell.
My fix was to move all the PATH
manipulation our of my .bachrc
to where it belongs in the .bash_profile
file (so that it only gets executed for new login shells).
Hmm, actually turns out it was not ~/.nix-profile/etc/profile.d/hm-session-vars.sh
. That only runs once (controlled by __HM_SESS_VARS_SOURCED
).
It turns out it was this code in my default Fedora .bashrc
:
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
Moving just that to my .bash_profile
keeps my PATH
from getting all screwy inside the shell.