How can we use regular non-nix binaries in a local prefix?

For example, suppose I want to quickly be witching Node.js version in my home folder using n or nvm (NPM packages to manage Node versions). I set these tools to use a custom prefix in ~/.local or similar.

But upon trying to execute a node binary in this location, I get file not found because the library modules (.so files) are not found by the executable.

More details with example output here: https://github.com/tj/n/issues/603

How can we use these tools? Can we somehow modify LD_LIBRARY_PATH in our shell to make binaries in our home folder work?


My short term goal is to use NixOS to set up my system-level configuration, then use familiar tools in my home folder (f.e. n or nvm) to get working quickly.

NixOS has some nice pros, but this one is a downside of NixOS. It is nice and easy to get up and running quickly with NixOS, and it’s nice knowing I can revert an update and reproduce installs easily (both of which I haven’t had to do yet), but I’m having a tougher time getting to work in my home folder with standard tools (f.e. n).

I wonder if this area can be improved somehow?

Have you looked into using buildFHSUserEnv ?

1 Like

Thanks for pointing out buildFHSUserEnv. Based on the description, that seems like it might be what I need.

I read the whole section, but I’m not comfortable enough yet to know how to use it.

Once I have ran N_PREFIX=~/.node n latest which installed the latest version of the node binary into ~/.node/bin (and maybe some things into other FHS folders inside of ~/.node), how would I use buildFHSUserEnv to run ~/.node/bin/node?

Or am I thinking about it wrong, in that I’d need to run buildFHSUserEnv first to make an environment, and then after that use n inside the env to install node and finally use it?

With other distros of the FHS-type, I’ve been using npm, n, and other tools to install and use binaries/executables in my home folder. To keep doing so, would I need to create my home folder inside a buildFHSUserEnv env?

I found this article: https://brianmckenna.org/blog/running_binaries_on_nixos.

It’s tempting to do that, just add a bunch of common things that many apps need, and run stuff.

I think doing that may defeat the purpose. I suppose I should embrace nix package management for differing versions of node, etc (not sure how yet).

In Win/Linux/macOS, I have many git-tracked projects in a folder like ~/src, and I sometimes switch node or npm versions in my environment, or install and uninstall npm packages, depending on which project I’m working on, etc.

As that article says, we may just

want to run something just once or right now.

rather than spend time learning how to package things with nix, especially in a home folder.

Running n 11 or n 13 to switch versions of node when switching projects is super easy compared to packaging, at least as far as I know so far.

How does one manage many projects in a home folder, like in my case when coming to nix from traditional distros? Do I need to make local nix envs with specific dependencies on a per project basis?

After doing some investigation (thanks to @xaverdh for pointing me to buildFHSUserEnv), I’ve come to the conclusion that trying to use n or nvm in NixOS to manage node versions, and potentially running those node versions in a simulated FHS, it would be working against the grain of NixOS.

Instead I believe it will be more worthwhile to embrace nix and figure how to package and install (or swap between) multiple versions of node in the NixOS environment.

I must say, the following StackOverflow question/answer is one of the most helpful pages that I’ve found on the topic: Different methods to run a non-nixos executable on Nixos.

Maybe this should go in one of the manuals, or perhaps in the Wiki.

Maybe direnv is a tool that could help you. It’s useful on other linux distributions, but it really shines on NixOS, where it’s able to install programs.
Here’s an example I use for ansible:

$ cat .envrc
export ANSIBLE_LIBRARY=lib
export ANSIBLE_CONFIG=$(expand_path ansible.cfg)
export ANSIBLE_INVENTORY=$(expand_path hosts)
PATH_add bin
use nix -p ansible sshpass

As soon as I enter the directory the file is in, direnv ensures that I have ansible and sshpass in my PATH and the other variables are set.
That should also work with for example a default.nix or a shell.nix in the same directory.

1 Like

That’s neat. Does this require the dependencies to be in a channel (the main one?) that it finds the packages in? Can I specify an arbitrary channel for the nix command?

if you use the use nix -p pkg1 pkg...version it’s basically what nix run nixpkgs.pkg1 nixpkgs.pkg2 would give you.
If you use the default.nix variant, you have full control over everything and can use the default channel or specify pretty much anything you want, even specific nixpkgs-commits or packages that are not in nixpkgs at all.

1 Like