Correctness of "resolving EACCES Permissions errors when installing packages globally"

Can anyone comment on the correctness of https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally ?

The article seems to suggest you should install global packages in a specific user’s home directory. That seems contradictory to me and doesn’t fix the problems people have with globally installed packages, namely that permissions are not set correctly (see also https://github.com/npm/npm/issues/3849) and as a result they are not usable.

Configuring the global packages directory to not be something like /usr/lib/node_modules but instead a user’s home directory, as suggested by the “resolving EACCES Permissions” article only solves this problem for that particular user. However, a global package would need to be accessible by all users.

I’m also not clear on how the first “solution” (using a Node Version Manager to install NodeJS and npm - https://docs.npmjs.com/downloading-and-installing-node-js-and-npm#using-a-node-version-manager-to-install-node-js-and-npm) fixes this problem. According to the documentation there, using a Node Version Manager:

allow(s) you to install and switch between multiple versions of Node.js and npm on your system so you can test your applications on multiple versions of npm to ensure they work for users on different versions.

That seems like an entirely different issue.

I don’t come from a NodeJS or even a Javascript background, so I’m aware that you guys’ way of thinking might be a lot different from what I’m used to. So please help me understand :slight_smile:

However, if there is consensus that the article doesn’t provide a valid solution for the problem it says it solves (making sure that globally installed packages are readable and executable by all users on the machine), we can decide on a proper solution and open a PR to fix the documentation.

Thanks,
Frans

1 Like

Hi Frans. Thanks for your input. It’s eye-opening to see a non-JS person’s take on npm :wink:.

The word “global” is a little misleading. In the npm community, when we say “global”, we mean that the package can be used in any project space, not used by any user.

Back in the day, it was a huge convenience to have them installed globally, but now that there are node version managers, it has become more of an unspoken best practice to manage all of a project’s dependencies locally, and manage all the tasks that you would usually need to run globally with local packages (namely with npm scripts in the package.json). This keeps your environments siloed, which leads to more flexibility, maintainability, and reusability.

A lot of the caveats you may discover with npm are mostly community-driven, and it’s ever-evolving.

1 Like

Hi Frans, thanks so much for sharing your perspective on this article. It’s one of the ones we’ve flagged for revision, but I’m not sure how soon we’ll be able to get to it. I’m tracking all the feedback we get on it internally. Using a Node version manager helps make sure that npm is initially installed with the correct user permissions, and as a bonus, it can help you switch between Node versions. Let me know if that answers your question, and if I can help you out further.

1 Like

Thanks, Brian. How you explain global is also how I understood it. But some pages seem to have a different take on it, like this one:

https://nodejs.org/en/blog/npm/npm-1-0-global-vs-local-installation/ :

In general, the rule of thumb is:

  1. If you’re installing something that you want to use in your program, using require('whatever') , then install it locally, at the root of your project.
  2. If you’re installing something that you want to use in your shell , on the command line or something, install it globally, so that its binaries end up in your PATH environment variable.

Also, the way my package manager (yum on CentOS) installed npm, it configured the global packages to end up in /usr/lib/node_module which is definitely a system global location.

So there seems to be a lot of misunderstanding and misalignment on what global means, especially since the term generally means something else than what it apparently means in an npm context.

So perhaps this requires a whole review of all the npm documentation regarding local vs global, to make sure it’s clear and consistent?

2 Likes

Ah, I misunderstood the docs. As Kiera stated, it’s on the agenda. I agree with you that it needs to be looked at. Nice catch!

Sure. Let me know if I can help out somewhere.

@fransflippo good question. This area is something I have been thinking about for a while. This is the first of probably a few replies covering different aspects.

I personally think the advice in https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally is not a very clear response to the stated problem. However, the goal of the article is not to “make sure that globally installed packages are readable and executable by all users on the machine”. You are quite right it does not do that! I think a better statement of the goal is to be able to install your global packages without using sudo and without having permission problems. So what do we mean by global then…

Global

Say you have two packages you are developing, dev1 and dev2. You are considering installing np which adds a CLI command to help with running npm publish. You can install np locally into dev1, and/or dev2, or as a global package which is runnable directly on the command line. The global install location might be to a system directory or to a directory in your home directory, but it is still “global” rather than inside the package you are currently working on.

This global location does not actually need to be accessible by other users, although you might reasonably have assumed that based on the name. Firstly, worth noting that in practice most developers are probably using a single account and the only user of the computer so there aren’t actually other users. Secondly if there are other users, it may actually be better they have their own global packages rather than having conflicts over what version of packages are needed. Which leads nicely into…

Common advice these days is to favour local installs over global installs where it makes sense. The advantages are:

  • easier for someone downloading dev1 (or dev2), they just run npm install and do not need to separately install np or other expected global packages
  • better to manage dependencies, dev1 and dev2 can require different versions of np

(Next up: why suggest a node version manager?)

@shadowspawn John pointed me to this topic. After many years (I think I’ve been using node off and on for probably 8 years or more) I’ve finally decided to track down the source of the constant EACCES errors I’m getting with node. I’d like to add to the discussion here.

First, please put yourself into the shoes of a Linux user who wants to use node+npm to work with, say create-react-app. Such a person would naturally follow the instructions for Linux-based systems linked from the node.js website.

If they do that, then this user is doomed the very moment they issue an npm … -g command. They are forced to use sudo at which point the caches in their personal home directory end up with files written using root.root. Why might such a user use the -g flag? First, up until recently, the instructions for installing popular packages such as create-react-app advised to use -g. Second, even as of today, when npm performs an update check and if it detects that a new version is available, it advises the user to update via -g, requiring sudo in the process. If the user follows the unprompted advice, which is not unreasonable on the user’s part, the permissions in the $HOME/.npm/_cacache directory are toast. (For me personally, having sufficient background in managing Unix permissions, this is a mere nuisance. In the class I’m teaching, it causes lots of headaches for the students, some even giving up on the assignment altogether.)

This thread suggests that we misunderstand ‘global’ and that there’s a discrepancy in how node.js/npm views the meaning of global and others do. I think I disagree. To me, this looks like a bug (and I’m trying to track down the issue where this is discussed.)

The way things should work, IMO, is that if npm is run with sudo (in this case, the variable SUDO_USER and other variables are set), then it must decide: (a) access any file under $HOME after dropping to SUDO_UID/SUDO_GID; or (b) don’t access any file under $HOME (and write to a suitable location in the global install directory instead).

The current practice of npm to write - without dropping privileges - to the invoking user’s $HOME directory (specifically to such locations as $HOME/.npm/_cacache where this error usually occurs) appears very unfortunate indeed and should be fixed. Alternatively, if node is incompatible with standard Linux install conventions, the installation instructions should be updated. At the very least, don’t have npm output a recommendation which, when followed, compromises the user’s ability to issue further npm commands.

I tracked down the source of the root-owned directories left by sudo npm install -g in my $HOME/.npm/_cacache directory and left an issue in the pacote bug tracker.

2 Likes

I also looked for the opposite mistake (leaving behind user-owned files in /usr/lib/node_modules on Linux when running under sudo). I left an issue with pacote as well pointing out one example where such files and directories are created.