Te encontrás en tu casa, y crees que es un buen momento para empezar un curso de programación de aplicaciones híbridas con Cordova, o decides seguir un tutorial sobre Firebase.

Llega el momento en que quieres hacer una instalacion global de un paquete con npm y te encontraste con con el error de EACCESS permission denied

No te preocupes, este mensaje de error aparece siempre una instalacion de NodeJS desde los repositorios. Y la solución es muy sencilla, seguí leyendo para ver como solucionar el error.

¿Qué es el error EACCES?

Claramente como indica el mensaje es un error de permisos, esto se debe a que instalamos NodeJS y npm a nivel del sistema mediante los repositorios, ya sean los de las distro o desde NodeSource.

Si revisamos donde instala npm los paquetes de forma global:

ariel@a-nb:~$ npm config get prefix
/usr

Vemos que lo hace en el directorio /usr, directorio al cual no tenemos acceso como usuarios normales, a alguien se le ocurrira querer solucionar el problema instalando el paquete de forma global pero como usuario root, no es lo recomendable.

En mi caso, quería instalar firebase-tools luego de haber hecho una instalacion nueva de un Debian mínimo con KDE en mi nuevo SSD y el mensaje es completo es el siguiente:

ariel@a-nb:~$ npm install -g firebase-tools
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated mkdirp@0.5.4: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
npm WARN checkPermissions Missing write access to /usr/lib/node_modules
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules/firebase-tools/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

npm ERR! code EACCES
npm ERR! syscall access
npm ERR! path /usr/lib/node_modules
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, access '/usr/lib/node_modules'
npm ERR! [Error: EACCES: permission denied, access '/usr/lib/node_modules'] {
npm ERR! stack: "Error: EACCES: permission denied, access '/usr/lib/node_modules'",
npm ERR! errno: -13,
npm ERR! code: 'EACCES',
npm ERR! syscall: 'access',
npm ERR! path: '/usr/lib/node_modules'
npm ERR! }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

npm ERR! A complete log of this run can be found in:
npm ERR! /home/ariel/.npm/_logs/2020-03-31T16_52_54_421Z-debug.log

Solución Error: EACCES: permission denied, access

La documentacion de npm, nos indica dos posibles formas de solucionar el error:

La segunda opción es la recomendada por la documentaciòn, no es la que a mi me gusta, si bien, al utilizar un gestor de versiones, tiene la ventaja que podemos tener todas las versiones de node que deseamos y cambiar entre ellas según las necesidades, no me gusta tener tantas cosas instaladas en mi computadora, en caso de necesitar alguna version en especifico de NodeJs prefiero utilizar Docker.

Manualmente cambiar el directorio por default de npm

Esta es la opción que utilizo para solucionar el problema de permisos, debido a que quiero mantener la versión de nodejs instalada mediante apt.

Como vimos, se trata de un problema de permisos con el directorio configurado por defecto, por lo tanto la solución es crear una nuevo directorio, en nuestra carpeta personal e indicarle a nom que use este directorio para las instalaciones globales. Manos a la obra:

1 - Crear un directorio oculto en nuestra carpeta personal, donde almacenar las instalaciones globales:

$ mkdir ~/.npm-global

2 - Configurar non para que utilice este nuevo directorio:

$ npm config set prefix '~/.npm-global'

3 - Agregar este nuevo directorio a la variable de sistema PATH de forma permanente:

$ echo "export PATH=~/.npm-global/bin:$PATH" >> ~/.profile

4 - Actualizar las variables de nuestra sección:

$ source ~/.profile

Con estos 4 simples pasos ya tenemos nuestro sistema configurado, ahora si intentamos instalar nuevamente el paquete:

ariel@a-nb:~$ npm uninstall -g firebase-tools
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules/firebase-tools/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

removed 535 packages in 2.436s
ariel@a-nb:~$ npm install -g firebase-tools
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated mkdirp@0.5.4: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
/home/ariel/.npm-global/bin/firebase -> /home/ariel/.npm-global/lib/node_modules/firebase-tools/lib/bin/firebase.js

> protobufjs@6.8.9 postinstall /home/ariel/.npm-global/lib/node_modules/firebase-tools/node_modules/protobufjs
> node scripts/postinstall

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules/firebase-tools/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ firebase-tools@7.16.2
added 535 packages from 344 contributors in 23.331s

Reinstalar npm mediante un gestor de versiones de node

Esta segunda alternativa, como comente no se adapta a mis necesidades, sin embargo a alguien le puede resultar útil, así que la detalló:

1 - Instalar nvm(Node Version Manager):

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

2 - Actualizar la sesión:

$ source ~/.profile

O bien podrías abrir y cerrar la terminal.

3 - Instalar Node:

$ nvm install <VERSION>

Nota: Para ver las versiones disponibles a instalar:

$ nvm ls-remote — lts

Y para cambiar entre las versiones que tengamos instaladas:

$ nvm use <VERSION>

Conclusión

El mensaje de error EACCESS es normal y de esperar que aparezca en una instalación limpia mediante el gestor de paquetes del sistema. Es un error debido a conflictos de permisos. Al realizar una instalación global de un módulo, como usuario normal, npm tiene como directorio por defecto /usr al cual no tenemos permisos de escritura.

Las posibles soluciones son dos y ambas son a nivel de usuario sin interferir en la configuración del sistema.

En mi caso opto simplemente crear un nuevo directorio y configurar npm para que use este directorio.

Y vos, ¿qué solución implementaste?