Nodejs the proper way without using sudo

Update existing proper installation

Run these two commands as is:

npm i -g n
N_PREFIX=$HOME/.local n stable

first installation

If it is the first time you are installing this, simply download the LTS from nodejs.org

Create a ~/.local dir, which is used by many other programs (so it should already exist).

cp -fR ~/Downloads/node-v12.13.1-linux-x64/* ~/.local/

Add the .local/bin dir to your exports path. To do so add the following line to ~/.bashrc:

export PATH="$HOME/.local/bin:$PATH"

Now all your global modules should live inside .local/

Updating to latest version (if you changed the global node modules dir)

You should not sudo too much on programs you do not know.

That should have convinced you that the only way to update node is through a node module called n.

You probably have a version of node lying around. And you have installed npm. Npm should be installed properly without the sudo part. To do so you have changed the global node modules installation directory. It should be something like $HOME/.node_modules_global. You should also have added it to $PATH in your .bashrc. This way you can run the binaries.

Now if you want to update node the wrongly suggested way is to use

sudo npm i -g n #don't use sudo!

We said no sudo! The correct way is to simply run the same command without sudo

npm i -g n

This has the effect of installing the n module in your $HOME/.node_modules_global. Since it is in the path, you can now proceed to the next step, which is to update node using:

(following is a wrong way, it will give you an error)

n stable

  installing : node-v12.13.1
       mkdir : /usr/local/n/versions/node/12.13.1
mkdir: cannot create directory ‘/usr/local/n’: Permission denied

  Error: sudo required (or change ownership, or define N_PREFIX)

The solution is NOT to change ownership of /usr/local/n, because there are many other dirs that n wants to write to like these:

(following is a failed attempt by sudo mkdir /usr/local/n && chown $(WHOAMI) /usr/local/n, if we run n stable again it will show you all the dirs n wants to write to, which of course we DON'T want to chown)

n stable

  installing : node-v12.13.1
       mkdir : /usr/local/n/versions/node/12.13.1
       fetch : https://nodejs.org/dist/v12.13.1/node-v12.13.1-linux-x64.tar.gz
cp: cannot create directory '/usr/local/lib/node_modules': Permission den
ied
cp: cannot create regular file '/usr/local/bin/node': Permission denied
cp: cannot create symbolic link '/usr/local/bin/npm': Permission denied
cp: cannot create symbolic link '/usr/local/bin/npx': Permission denied
cp: cannot create directory '/usr/local/include/node': Permission denied
cp: cannot create directory '/usr/local/share/systemtap': Permission denied
cp: cannot create directory '/usr/local/share/doc': Permission denied
cp: cannot create directory '/usr/local/share/man/man1': Permission denied
/home/g/.node_modules_global/bin/n: line 569: /usr/local/bin/node: No such file or directory

The true solution

The true solution is to call n stable BUT using N_PREFIX, where N_PREFIX points to the location you want to install node in.

A proper /usr/local that does not require sudo is $HOME/.local. It is adopted by many other programs. If you don't have this dir create it:

mkdir ~/.local

Now pass it to n so that it can install node under ~/.local/bin/node.

So here is the main step:

N_PREFIX=$HOME/.local n stable

  installing : node-v12.13.1
       mkdir : /home/g/.local/n/versions/node/12.13.1
       fetch : https://nodejs.org/dist/v12.13.1/node-v12.13.1-linux-x64.tar.gz
   installed : v12.13.1 to /home/g/.local/bin/node
      active : v8.10.0 at /usr/bin/node

You see that with a proper N_PREFIX the output greets us, but in a weird way: we have managed to install it but the active version is one in /usr/bin/node. Don't worry, simply delete that old node version: sudo rm -rf /usr/local/node and run the following command again to see what the active version is:

N_PREFIX=$HOME/.local n stable

   installed : v12.13.1

The output tells us that now there is no active version. Whish means at least we removed to old one properly.

To activate the new node version, we simply need to tell our .bashrc where to find it, so vim ~/.bashrc and paste the following:

export PATH="$HOME/.local/bin:$PATH"

Then close and open a new terminal window and check the node version with:

node -v

v12.13.1

And we are done. So for reference what we have done is to use a npm module n to update node without using sudo. We now have a clean setup where global node modules are installed by npm to ~/.node_modules_global and we have our open-source binaries for (node, npm, npx) living in our home directory under ~/.local.

Which is pretty neat.