Repository navigation
How to install Node to avoid sudo #4
Description
Activity
As far as anti-patterns go,
npmactually 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 callsetuid.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/localworks nicely.Making your own private place to install to and adding it to your
$PATHis 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/localconfigured – and I runbrew doctorperiodically 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. 🎉 (This is not actually a good argument.)
A little historical context
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_modulesfollows 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.upshot
So:
- change /usr/local to be writable by your normal user account, or
- use a version manager like
nvmthat installs global packages to a per-user prefix, or - use
sudoand clean things up periodically
One final recommendation: never run a local install (i.e.
npm installwithout-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 usenobodyto own files. The whole point ofnobodyis that it doesn't own anything.(It's bad for
nobodyto own files because on unix systems, that account is meant to have the least privileges possible. When a service running asnobodyis 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 ~/npmto 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 usenpm -g installall 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 myPATH– it's very easy to inadvertently run something you shouldn't that way. I think I prefer using a version manager likenaveornvmor configuringprefixto 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
npmhave anexeccommand that'd run things with./node_modules/.bin/in the path.Well, the docs specify
./node_modules/.binfor local executables , so I find it convenient to have in$PATH. It's optional - npm kindly adds./node_modules/.bin/whateverto your$PATHfor executable dependencies that you invoke as npm scripts (docs). I foundsudowas mostly necessary because of usingnpm -gto 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
cdinto a random repository that's not yours, that means someone could make an innocuous command like, say,lsrun 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
#4 (comment).@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:
Somebody told me to install node.js on my macbook
- auto-detect platform to download a binary like node.js
- less religion/marketing talk than .org that explains in two sentences
node,npmand their practical applications - current .org copy is "Node.js® is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications." and 9/10 people I send to that page immediately glaze over causing them to miss the big "download" button
I want to install and manage node with my package manager
- snippets flow
- "on what platform?"
- "ubuntu" -> "copy and paste this"
- "... but I don't have sudo" -> "copy and paste this"
- "ubuntu" -> "copy and paste this"
- "on what platform?"
- markdown badge/snippet to drop into README's
- "osx" -> homebrew and co.
I made a node module
- rather than not mentioning node.js at all, or even worse providing misinformation, give me a snippet that explains like
two sentencesfrom above ("This is a module for node.js XXXX") and a badge that links to installno.de - badge has reference to repo url like heroku deploy button that provides extra context on install page like:
- "You're using OSX and the module has leveldb in it's
dependencies" -> now mention xcode requirements/steps not as the first sentence :) - "express in it's
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
- "You're using OSX and the module has leveldb in it's
@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
sudoevery package install?It seems like very install process I use results in having to
sudo install whatevswhich is a security anti-pattern. How can I install sanely on my development machine?