Open KatieK2 opened 9 years ago
As far as anti-patterns go, npm
actually does some clever things. It runs installation scripts as a non-root user; it's actually more secure from some attacks (malicious package scripts) when run as root because of this, because it can call setuid
.
However, the isolation of not needing to run as root is good for other reasons, too.
You can install node and npm to some place that does not require root access to write to. On a Mac, for a single user, chown -R $USER /usr/local
works nicely.
Making your own private place to install to and adding it to your $PATH
is also a great way to go:
cd ~
tar xzf node-v0.10.32-linux-x64.tar.gz
PATH="$HOME/node-v0.10.32/bin:$PATH"
And then there are tools like nvm which automate this and put it in a version-neutral place, so upgrades don't shake it all apart.
I can't wait until somebody asks this question about Windows; the answer is a nightmare. ;)
I personally follow Aria's suggestion (which is also how Homebrew on OS X wants me to have /usr/local
configured – and I run brew doctor
periodically to ensure that nothing has broken since the last time I looked). The simplest way to avoid permissions issues to avoid putting yourself in situations where they're relevant. As far as I can tell, this is the official npm recommendation as well.
It's true that npm tries to do the right thing when run as root, but it's also true that we've had to fix some bugs because npm didn't quite get things right. Right now, for instance, there's a bug (npm/npm#6548) that will cause a piece of the npm cache's internal machinery to get created with the wrong permissions when you install a git dependency for the first time as root. There have been others, some of which have been addressed relatively recently. I don't see these bugs, because I'm always running npm with regular privileges, so if you do things the same way that the npm developers do, you will have fewer problems as well. :tada: (This is not actually a good argument.)
From time to time, somebody will put together a Stack Overflow answer or a blog post showing how you can set up npm to use a subfolder of your home directory as its global location, and while you can do that, it's not the path of least resistance. @isaacs designed npm to put global scripts in /usr/local/bin
, and installing to /usr/local/lib/node_modules
follows from that decision. It's easier for most people to understand, and the trend, at least with OS X developer machines and servers in the clown, is for most hosts to be single-user, where it makes sense for that single user to have write permissions to /usr/local
.
So:
nvm
that installs global packages to a per-user prefix, orsudo
and clean things up periodicallyOne final recommendation: never run a local install (i.e. npm install
without -g
) as root. If your deployment strategy requires this, fix your deployment strategy. Also (and this is somewhat counter to what npm does in some cases), don't use nobody
to own files. The whole point of nobody
is that it doesn't own anything.
(It's bad for nobody
to own files because on unix systems, that account is meant to have the least privileges possible. When a service running as nobody
is compromised, you don't want it to be able to alter, delete, or even read any of the files on the compromised system.)
Got this idea from this SO question. Basically use npm config set prefix ~/npm
to tell npm to put global modules there and add that location to your $PATH variable. I've done it that way ever since and do not need to sudo anything.
@KatieK2 If you need executable scripts in a unix (linux/mac) environment you can export PATH=$PATH:./node_modules/.bin
. It allows you for example to run things like mocha from the local project directory instead of having to use npm -g install
all the time. Here's short post on that. Hope that helps!
@darrenderidder A few developers at npm follow that pattern, but I don't, for the same reason that I don't add .
to my PATH
– it's very easy to inadvertently run something you shouldn't that way. I think I prefer using a version manager like nave
or nvm
or configuring prefix
to be $HOME/npm
(or something similar).
Yeah. I'm torn on it; I add it to mine, but I'm very careful and not on a multi-user system. It's a clever hack, but I'd love to see npm
have an exec
command that'd run things with ./node_modules/.bin/
in the path.
Well, the docs specify ./node_modules/.bin
for local executables , so I find it convenient to have in $PATH
. It's optional - npm kindly adds ./node_modules/.bin/whatever
to your $PATH
for executable dependencies that you invoke as npm scripts (docs). I found sudo
was mostly necessary because of using npm -g
to install things globally, but I'm pretty sure it's been a couple of years since that was the recommended way.
Yup. Just gotta be careful if you cd
into a random repository that's not yours, that means someone could make an innocuous command like, say, ls
run something you don't expect.
Npm scripts already do this!
One trick I have been doing lately is to design modules that export binaries, installing them as dev dependencies, and just using npm scripts to call them. On Nov 15, 2014 8:25 PM, "Aria Stewart" notifications@github.com wrote:
Yeah. I'm torn on it; I add it to mine, but I'm very careful and not on a multi-user system. It's a clever hack, but I'd love to see npm have an exec command that'd run things with ./node_modules/.bin/ in the path.
— Reply to this email directly or view it on GitHub https://github.com/node-forward/help/issues/4#issuecomment-63203745.
@aredridel Agree, although ./
is kind of another discussion; some devs add it at the end ie. PATH=$PATH:./
for the reason you said, so commands don't get overridden unexpectedly...
@othiym23 not sure if this is the right repo to post this, but really interested in the install/introduction problem. I've been kicking an idea around for a bit now and am curious what other folks think.
What if we had a installno.de to point to? Braindump ways to address common problems and scenarios I've dealt with in this area:
node
, npm
and their practical applicationstwo sentences
from above ("This is a module for node.js XXXX") and a badge that links to installno.dedependencies
" -> now mention xcode requirements/steps not as the first sentence :)dependencies
" -> tell me what express means and give me links for info as the project's README is most likely full of assumptions that I know what "express" means @imlucas I love the idea. it would be great to have installation instructions available on a rememberable URL like that, since nodejs.org currently just links to compressed build, which is not very beginner-friendly. count me in if you need help.
also, maybe opening up a separate issue for this would be a good idea, since this issue is only about avoiding sudo.
I'm currently working on documenting this for npm, npm/docs.npmjs.com#48
What's the best way to install Node to allow packages the permissions they need to install, and to avoid having to
sudo
every package install?It seems like very install process I use results in having to
sudo install whatevs
which is a security anti-pattern. How can I install sanely on my development machine?