How to install NVM (Node Version Manager) in NixOS?

I am trying to install NVM in NixOS. This is my config file.

However, I cannot find the package.

Is there an alternative way of handling this?

2 Likes

Use a properly set up shell.nix.

Most of those xVM are in conflict with how nix works and either create binaries that won’t work anyway, or otherwise a hazzle for you to provide proper libraries and “dev-packages” in a way that the xVM can see them.

3 Likes

Thank you. Could you provide the template? An example or tutorial?

I have little experience with nix-shell

1 Like

Try this. Add this file to the root of your projec - call it shell.nix. then run nix-shell to spawn an environment with the dependencies you need. I would look into nix-direnv as well.

{ pkgs ? import <nixpkgs> { } }:
let
  mynode = pkgs.nodejs-14_x;
in
pkgs.stdenv.mkDerivation {
  name = "my-shell";
  packages = [  ];
  shellHook = "";
  buildInputs = [ mynode ];
}
2 Likes

Thanks for the help!

Before reading this answer, I was trying the following:


stdenv.mkDerivation {
    name = "node";
    buildInputs = [
        nodejs-16_x
        nodePackages.firebase-tools
        nodePackages.node-gyp
    ];
    shellHook = ''
        export PATH="$PWD/node_modules/.bin/:$PATH"
        export NPM_PACKAGES="$HOME/.npm-packages"
    '';
}

I tried to adapt the content of mine initial approach with your suggestion:

But, I am getting this error

Try:

stdenv.mkDerivation {
    name = "node";
    packages = with pkgs; [
        nodejs-16_x
        nodePackages.firebase-tools
        nodePackages.node-gyp
    ];
    shellHook = ''
        export PATH="$PWD/node_modules/.bin/:$PATH"
        export NPM_PACKAGES="$HOME/.npm-packages"
    '';
}

Note that, while buildInputs will work because this is all passed to mkDerivation in the end, packages is preffered because it makes more sense.

This probably won’t work as you expect it to, though. npm assumes packages are in the node_modules directory, having them installed globally doesn’t help.

You’ll probably need to use GitHub - nix-community/npmlock2nix: nixify npm based packages [maintainer=@andir].

1 Like

Thanks for trying to help, @TLATER.

Unfortunately, it is not working:

Ah, heh, ok, so the full file contents should be something like:

{pkgs ? import <nixpkgs> {}}:

let 
  inherit (pkgs) stdenv;
in
stdenv.mkDerivation {
    name = "node";
    packages = with pkgs; [
        nodejs-16_x
        nodePackages.firebase-tools
        nodePackages.node-gyp
    ];
    shellHook = ''
        export PATH="$PWD/node_modules/.bin/:$PATH"
        export NPM_PACKAGES="$HOME/.npm-packages"
    '';
}

shell.nix is a nix file, which the nix-shell command will evaluate, and then use to create your environment.

nix-shell will either take a simple expression like yours or it will take a function like this one and give it a pkgs argument, which refers to the <nixpkgs> channel of your system.

We need that pkgs argument if we want to install packages - it maps back to https://github.com/nixos/nixpkgs. Without it there are no packages, and even mkShell hasn’t been defined yet!

So, we make it explicit that our shell.nix is a function and takes the pkgs argument. I mix in some funny syntax, too, let me explain;

  • The ? means “if this argument is not defined, set it to”. I think technically this isn’t necessary at all, though it can come in handy if you ever want to import your shell. Basically, we’re cargo culting this because others do it this way.
  • import <nixpkgs> imports the default.nix of whatever your nixpkgs channel is. Unless your system is very weird that’ll be the nixpkgs repo, but again, this is only relevant as a fallback.
  • The let inherit (pkgs) stdenv in turn is like saying import stdenv from pkgs in python. Only there so we don’t need to use pkgs.stdenv.mkDerivation.

And that then should make it all work, because now the variables that were previously assumed to fall from the sky actually exist in context now :wink:

So well, sorry, I assumed the basics were covered and you cropped the “irrelevant” part from your snippets.

If you’re going to be playing with converting npm to nix, it’s worth learning the language a bit, though I appreciate that’s very yak shavey. Maybe consider working in a VM if you need things to go fast.

For interesting alternatives:

You could do the above without a function too, if you instead relied on import <nixpkgs> fully, but it’s nicer to use a function so nix-shell can do its job.

Also, in theory you could write your own custom nixos with a custom mkShell in one of these shell.nix files, and not rely on any import statements. Good luck if you ever attempt that :wink:

2 Likes

how to point pnpm version

Well part of the reason to use NVM is because of .nvmrc a file used by a development team to ensure all members are on the same nodejs version.

Its fine having a shell setting up your custom environment, but unless you convert all other team members to nix, or get it to work with existing tools, its going to be difficult to get going

Edit: Suppose what’s cool about using nix here is that you can just look back in nixpkgs for the older definition that you need, and fix it to that, without requiring extra maintainer burden for maintaining those older revisions. Provided that it still builds… but with reproducible builds, in theory it should.