When running npm and node, you may find yourself getting permission errors that ultimately lead you to using `sudo` in your commands. While this helps get around the issue in the short-term, it also places stricter permissions on those installs and it becomes a slippery slope where soon you may need sudo for more than you bargained for. Also, do you really want to be using `sudo` to install npm packages?
UPDATE: Easier path
**Jan 28, 2018**After discussing this with Tierney Cyren, there are good reasons to use the official Node.js install and (awesomely) there are now easier ways to avoid the sudo hell. hey ... it's been 3+ years since I wrote this post, so it's great to see progress!
The keys are to install Node.js from the Node web site. Then create your own folder for the global npm packages (I made mine ~/.npm-packages
). Then we use the npm config
command to tell npm where we want them. That's it!
Go here to read the steps, in detail.
The rest of this post is here in case you are interested in what I used to do. Please read the above update first, as it is much simpler and more recent.
What I Used to Do
I went down this path and some experienced Mac developers helped me see why I needed to relieve myself of `sudo` for npm. Since then I've read several great posts with directions on how to do this including Dan Herbert's fixing npm for Homebrew users and Sindre Sorhus's No Sudo instructions. Each of these has something to offer, of which I combined into a single set of steps in this post. Also, special thanks to Brian Noyes, Ward Bell, Jesse Warden, Mike Callaghan, and Sam Artioli for their help.
Some people already have node and npm packages. So there is some cleanup to do first. Others have fresh machines, so it's a bit easier. While these steps are not the only way to go, they have been repeatable on a few machines for me. So why create a new set of instructions? For one, I can add some additional comments of what is going on to try to explain what's really happening. Also, I was able to take some of the steps and make them all run from terminal, so you can literally copy and paste some of them (see where this is recommended below).
Disclaimer: I offer no warranty nor guarantee of the success of these steps. These are simply what works in my experience. Follow these steps with a cautious eye as you would any steps you find on the internet.
I also encourage you to refer to either of the posts I mention above as they are both excellent and have also worked for me.
What Are We Really Doing?
Good question! When node installs it puts npm packages in a specific folder, usually `/usr/local/lib/node_modules`. This location is what we are moving in these steps. Why? Because that location requires root permissions and thus the use of sudo proliferates needlessly. So these steps are all about moving the location of where the npm packages will live, and then pointing OSX and node to the new location via paths. Think of it as moving to a newer neighborhood :)
Homebrew
I assume you have Homebrew. If not, go get it. It's awesome for OSX. You can install tons of great stuff quickly and efficiently with it. Instructions are at the link or for your convenience, run this:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Already Have Node ?
If you have Node installed already via brew, remove it and npm first. Run step 1 by itself and be careful, we are running as sudo and we are removing files forcefully.
This removes, forcefully, everything in the old npm folders.
sudo rm -rf /usr/local/lib/node_modules
sudo rm -rf ~/.npm
This removes node and puts it back without npm
brew uninstall node
Install Node and NPM
-
This adds node, sans npm
brew install node --without-npm
-
Create a directory for your global packages. I prefer to name my folder
.npm-packages
, you can choose what you want as long as you replace it throughout these steps. The${HOME}
is a variable that translates to~/
or/Users/john/
for me.
mkdir "${HOME}/.npm-packages"
-
Reference this directory for future usage in your
.bashrc
file. Theecho
command helps write the statement. The>>
tells it where to write it which is followed by the file to write it to.
echo NPM_PACKAGES="${HOME}/.npm-packages" >> ${HOME}/.bashrc
-
Indicate to npm where to store your globally installed package, in your
~/.npmrc
file.
echo prefix=${HOME}/.npm-packages >> ${HOME}/.npmrc
-
This gets and installs the latest npm, which is 2.1.16 at the time of this writing.
curl -L https://www.npmjs.org/install.sh | sh
-
Ensure node will find the packages by adding the path to your
.bashrc
. Notice the escape characters before special characters.
echo NODE_PATH=\"\$NPM_PACKAGES/lib/node_modules\:\$NODE_PATH\" >> ${HOME}/.bashrc
-
Ensure you'll find installed binaries by adding the following to your
.bashrc
.
echo PATH=\"\$NPM_PACKAGES/bin\:\$PATH\" >> ${HOME}/.bashrc
-
Ensure that you source your
.bashrc
file by adding the following to your.bash_profile
.
echo source "~/.bashrc" >> ${HOME}/.bash_profile
-
Source your
.bashrc
file once. Previous step did this for the future, but this does it right away.
source ~/.bashrc
These echo
commands will create the file if it is not already there. But if the file is there, it will simply append these commands to the end of the file. If you already had these it will add a duplicate, which you then should remove. See the section below for details.
Checking Your Files
When you are done, you should have a files that looks something like the following:
~/.npmrc
prefix=/Users/john/.npm-packages
~/.bashrc
NPM_PACKAGES=/Users/john/.npm-packages
NODE_PATH="$NPM_PACKAGES/lib/node_modules:$NODE_PATH"
PATH="$NPM_PACKAGES/bin:$PATH"
~/.bash_profile
Make sure you have the source ~/.bashrc
in your ~/.bash_profile
To see the files beginning with .
such as .bashrc
and .npmrc
you need to show hidden files for OSX. In terminal run the following command: defaults write com.apple.finder AppleShowAllFiles YES
Verification
Run these commands to test if you were successful:
- Run
node -v
to see the version of node - Run
npm -v
to see the version of npm - Run
npm list -g --depth=0
to see the global npm packages you have installed (should just be npm right now)
Advanced Users
For advanced users, the rest of these can be run via copy and paste into terminal.
brew install node --without-npm
mkdir "${HOME}/.npm-packages"
echo NPM_PACKAGES="${HOME}/.npm-packages" >> ${HOME}/.bashrc
echo prefix=${HOME}/.npm-packages >> ${HOME}/.npmrc
curl -L https://www.npmjs.org/install.sh | sh
echo NODE_PATH=\"\$NPM_PACKAGES/lib/node_modules:\$NODE_PATH\" >> ${HOME}/.bashrc
echo PATH=\"\$NPM_PACKAGES/bin:\$PATH\" >> ${HOME}/.bashrc
echo source "~/.bashrc" >> ${HOME}/.bash_profile
source ~/.bashrc
Handling Multiple Node Versions
What happens when a new version of node is released? What if you need version 0.10.36 for one app and 4.4.2 for another? Did you know version 6 is out now too? Yikes! it would be great if we could manage multiple versions of node on the same computer.
Check out this post for more on how to tackle multiple versions of node.