morgangraphics.ansible-role-nvm
Rol de Ansible: NVM
Instala NVM y Node.js en sistemas Debian/Ubuntu, RHEL/CentOS y otros sistemas *nix.
La peculiaridad de Ansible con SSH y los shells (no) interactivos hace que trabajar con NVM y Ansible sea un poco problemático. Esta publicación de stack overflow explica algunas de las soluciones que otras personas han encontrado para sortear este problema en particular.
Dónde otros roles son insuficientes
Otros roles de Ansible que instalan NVM y/o Node.js fallan en varias áreas.
Usan los gestores de paquetes apt-get o yum para instalar Node.js. Esto a menudo significa que el paquete de Node.js es más viejo que lo que está actualmente disponible en el repositorio de Node.js. En algunos casos, esos paquetes pueden no ser una versión LTS y si necesitas múltiples versiones de Node.js funcionando en el mismo host, no tendrás suerte.
A menudo instalan NVM y Node.js como usuario
root
(sudo su
obecome: true
). Esto puede añadir complicaciones con los permisos relacionados con la gestión de plugins de NPM, así como con el funcionamiento de Node junto con NVM, además de ser un riesgo de escalada de privilegios innecesario.No puedes ejecutar comandos ad hoc de nvm, npm, node, bash o shell.
Dónde este rol difiere de otros roles
- Puedes instalar NVM mediante wget, curl o git.
- Puedes usar NVM como lo harías en tu línea de comandos en tus propias tareas y playbooks de Ansible.
- Puedes instalar cualquier versión o versiones de Node.js que desees.
- No instala NVM ni Node.js como root.
- Puede ejecutar comandos arbitrarios de nvm, npm, node, bash o shell, eliminando potencialmente la necesidad de un rol Ansible de Node separado.
Requisitos
Versión de Ansible (ansible-core) 2.16.0 o superior.
:triangular_flag_on_post: Para una versión de este rol que funcione en versiones más antiguas de Ansible, consulta la rama 1.5.X legacy.
Consulta Versiones de Ansible abajo.
Instalación
- Clona este repositorio en tu carpeta de roles.
- Apunta la variable
roles_path
a la carpeta de roles, por ejemplo,roles_path = ../ansible-roles/
en tu archivoansible.cfg
. - Incluye el rol en tu playbook.
:warning: ¡ADVERTENCIA!
¡NO EJECUTES ESTE ROL COMO ROOT! (por ejemplo, become: true|yes|1
).
Hay varias razones para esto:
Es un riesgo de escalada de privilegios innecesario. Es muy poco probable que necesites ejecutar todas las tareas en todos los roles como
root_user
. Si, por cualquier razón, necesitas hacer todo comoroot_user
, reconsidera lo que hace el rol y por qué necesita acceso root para todo.Este rol instala NVM en el mismo contexto/shell/sesión que ejecutarías Node.js. No se ejecuta Node.js como
root
.Ansible cambiará el contexto del shell de inicio a
root
y NVM se instalará en el directorio home deroot_user
, por ejemplo/root/.bashrc
. Esto significa que si tu usuario principal es vagrant, ec2-user, ubuntu, etc., el rol NO FUNCIONARÁ COMO SE ESPERA.
MAL :thumbsdown:
- hosts: all
become: true # ESTO EJECUTA TODAS LAS TAREAS, PARA TODOS LOS HOSTS, COMO ROOT_USER
become_method: sudo # ESTO EJECUTA TODAS LAS TAREAS, PARA TODOS LOS HOSTS, COMO ROOT_USER
roles:
- role: ansible-role-nvm
nodejs_version: "8.16.0"
nvm_commands:
- "nvm exec default npm install"
- role: some-other-role
...
MEJOR :thumbsup:
- hosts: all
roles:
- role: ansible-role-nvm
nodejs_version: "8.16.0"
nvm_commands:
- "nvm exec default npm install"
- role: some-other-role
...
become: true # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER
become_method: sudo # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER
MEJOR :metal:
- hosts: all
roles:
- role: ansible-role-nvm
nodejs_version: "8.16.0"
nvm_commands:
- "nvm exec default npm install"
become: true # ESTO CAMBIA EL CONTEXTO DE INICIO PARA USAR EL USUARIO DE ABAJO
become_user: ec2-user # ESTO INSTALA NVM EN EL CONTEXTO DEL EC2-USER/USUARIO POR DEFECTO. ¡ESTE USUARIO DEBE EXISTIR EN EL SISTEMA!
- role: some-other-role
...
become: true # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER
become_method: sudo # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER
Consulta Problemas abajo para más detalles.
Ejemplos de Playbooks
Super Simple
Incluye el rol tal como está y se instalará la última versión LTS de Node.js.
- hosts: all
roles:
- role: ansible-role-nvm
Simple
Incluye el rol y especifica la versión específica de Node.js que deseas instalar.
- hosts: all
roles:
- role: ansible-role-nvm
nodejs_version: "8.15.0"
Más Complejado
Este ejemplo muestra cómo podrías configurar múltiples entornos (Dev/Prod) con diferentes opciones. La configuración de Prod aprovecha la opción de nvm_commands
para instalar, compilar y ejecutar la aplicación. El rol soporta y aprovecha la sintaxis de variables de Ansible, por ejemplo, {{ variable_name }}
.
- hosts: dev
vars_files:
- vars/dev.yml
roles:
- role: ansible-role-nvm
nodejs_version: "{{ config.dev.nodejs.version }}"
- hosts: prod
vars_files:
- vars/prod.yml
roles:
- role: ansible-role-nvm
nvm_install: "curl"
nvm_dir: "/usr/local/nvm"
nvm_commands:
- "nvm install {{ config.prod.client-1.nodejs.version }}"
- "nvm alias default {{ config.prod.client-1.nodejs.version }}"
- "nvm exec default npm install"
- "nvm exec default npm run prod"
Instalación/Ejecución/Mantenimiento o Actualización de múltiples versiones de Node.js en el mismo host
Por defecto, la primera versión de Node.js que se instancie en tu Playbook se aliased automáticamente como la versión "predeterminada", sin importar qué versión instales después o cuántas veces ejecutes el rol. Es importante declarar cuál versión se espera que sea la "versión predeterminada" si estás instalando múltiples versiones de Node.js en una sola máquina.
Hay dos alias preexistentes de NVM: default
(versión "activa" actual de Node.js) y system
(la versión base de Node.js del SO).
El alias es una característica muy poderosa de NVM y es una mejor práctica recomendada para gestionar tu entorno.
Instalación Múltiple
- hosts: host-1
roles:
# Servicios
- role: ansible-role-nvm
nodejs_version: "8.15.0" # <= Esta será la versión "predeterminada" de Node.js.
# Aplicación
- role: ansible-role-nvm
nodejs_version: "10.15.0"
Instalación Múltiple con predeterminada
- hosts: host-2
roles:
# Servicios
- role: ansible-role-nvm
nodejs_version: "8.15.0"
# Aplicación
- role: ansible-role-nvm
default: true
nodejs_version: "10.15.0" # <= Esta ahora es la "versión predeterminada" de Node.js.
Notas sobre comandos NVM
Los comandos NVM son una característica muy poderosa de este rol que aprovecha el trabajo que NVM ha establecido. Aprovechar nvm_commands
podría eliminar potencialmente la necesidad de un rol específico de Node para gestionar tus aplicaciones Node en absoluto.
Hay una diferencia entre los comandos nvm run
y nvm exec
. nvm run
es funcionalmente equivalente a node server.js
o node server
, donde estás invocando un archivo JavaScript.
nvm exec
se ejecuta en un contexto de subproceso y es funcionalmente equivalente a npm run server
, donde server
es un nombre clave en la sección de scripts en el archivo package.json
.
{
"name": "my_application",
"version": "0.1.0",
"private": true,
"scripts": {
"preserver": "npm run dbService &",
"server": "nodemon ./bin/www",
"build": "node build/build.js",
"dbService": "nodemon ./data-service/server.js --ignore node_modules/"
},
"dependencies": {
"..."
}
}
O
nvm exec
puede ejecutar algún archivo de script arbitrario, por ejemplo nvm exec hello-world.py
.
Por ejemplo, hello-world.py
#!/usr/bin/env python
print('hello-world')
:warning: Debes incluir un encabezado de script para que esto funcione correctamente.
O
ejecutar algún comando bash arbitrario.
ls -al >> output.txt
nvm_commands
facilita mucho la configuración de una aplicación Node y una capa API de Node ejecutando diferentes versiones de Node.js en el mismo host.
- hosts: host-1
roles:
# Servicios
# ¿QUÉ ESTÁ PASANDO?
# 1. Ejecuta el archivo JavaScript de servicios con Node versión 8.15.0.
# ¡ADVERTENCIA! Esta está aliasada como la versión predeterminada de Node.js en este punto.
# Por lo tanto, debemos especificar explícitamente la versión que estamos utilizando porque
# la versión predeterminada de Node.js cambia en la sección de Aplicación a continuación.
- role: ansible-role-nvm
nodejs_version: "8.15.0"
nvm_commands:
- "nvm exec 8.15.0 npm run services"
# Aplicación
# ¿QUÉ ESTÁ PASANDO?
# 1. Establece la versión predeterminada de Node.js a la versión 10.15.0.
# 2. Instala las dependencias del paquete con npm.
# 3. Establece el entorno a Producción, ejecuta el archivo JavaScript de construcción.
# 4. Luego ejecuta el script de implantación en producción.
- role: ansible-role-nvm
nodejs_version: "10.15.0"
nvm_commands:
- "nvm alias webapp {{ nodejs_version }}" # <= Cambia la versión predeterminada de NVM (soporta la sintaxis de variable de Ansible).
- "nvm exec webapp npm install" # instala dependencias de la aplicación.
- "NODE_ENV=production nvm run webapp build" # invoca Node.js directamente para ejecutar el script de construcción en producción.
- "nvm exec webapp npm run prod" # invoca npm para ejecutar el script de producción en tu archivo package.json.
Otro ejemplo
- hosts: host-2
roles:
# Servicios
# ¿QUÉ ESTÁ PASANDO?
# 1. Crea un alias para la versión 8.15.0 llamado service-default (soporta la sintaxis de variable de Ansible).
# 2. Ejecuta el script de servicios.
#
# ** Se recomienda que aliasas tus versiones de Node.js y las referencias en consecuencia. **
- role: ansible-role-nvm
nodejs_version: "8.15.0"
nvm_commands:
- "nvm alias service-default {{ nodejs_version }}" # <= (soporta la sintaxis de variable de Ansible).
- "nvm exec service-default npm run services" # ejecuta el script de servicios en tu archivo package.json.
# Aplicación - No se necesita un rol Ansible de Node separado.
# ¿QUÉ ESTÁ PASANDO?
# 1. Instala la versión 10.15.0 de Node.js.
# 2. Establece la versión predeterminada de Node.js a la versión 10.15.0.
# 3. Ejecuta el archivo test.js invocando Node.js directamente.
# 4. Luego ejecuta el script de implantación de producción.
- role: ansible-role-nvm
nodejs_version: "10.15.0"
nvm_commands:
- "nvm alias default 10.15.0" # <= Cambia la versión predeterminada de NVM.
- "nvm exec default node test.js" # invoca Node.js directamente para ejecutar el script de prueba.
- "nvm exec ./deploy.sh" # ejecuta un script bash arbitrario.
Cualquier argumento de línea de comando que uses para iniciar tu aplicación, o scripts de comando que has declarado en tu archivo package.json pueden colocarse dentro de la sección nvm_commands: []
de este rol.
- hosts: host1
pre_tasks:
# test-user necesita ser un usuario real en el sistema antes de que podamos instalar nvm en su perfil.
- name: agregar nuevo usuario
user:
name: "test-user"
become: true
roles:
- role: ansible-role-nvm
nodejs_version: "8.16.0"
nvm_profile: "/home/test-user/.bashrc"
nvm_commands:
- "whoami"
- "node --version"
- "nvm --version"
- "npm --version"
- "python3 -m hello"
become_user: test-user
become: true
Advertencias
Por defecto, la primera versión listada en tu Playbook, en la primera ejecución, será automáticamente aliasada como la "versión predeterminada" de Node.js, sin importar qué versión instales después o cuántas veces ejecutes el rol. El primero en entrar/instalar siempre es el predeterminado. Como resultado, si esperas que una versión de Node.js declarada más adelante en el playbook se establezca como predeterminada, usa
default: true
o configúralo explícitamente en la lista denvm_commands
, como- "nvm alias default <TU_VERSIÓN>"
.Si tienes
default: true
declarado explícitamente como una variable del rol Y- "nvm alias default <OTRA_VERSIÓN>"
como parte de tusnvm_commands
, la versión condefault: true
SIEMPRE se ejecutará primero. Esto se debe a que necesitamos que Node.js esté disponible antes de hacer cualquier otra cosa.NVM es sin estado, en el sentido de que si tienes múltiples versiones de Node.js instaladas en una máquina, es posible que tengas que ejecutar
nvm use <VERSION>
como parte de tu script para ejecutar la versión de Node.js que deseas/esperas. Sin embargo, se recomienda encarecidamente que asignes alias a tus versiones en consecuencia y las referencias de esa manera. Consulta los ejemplos anteriores.
Problemas
"nvm: comando no encontrado"
Esto es a menudo el resultado de ejecutar el rol en un contexto de usuario distinto al que nvm
y node
se ejecutarán dentro de la máquina. Si agregas become: true
a todos los roles en tu playbook para evitar errores que esos roles arrojan debido a problemas de permisos, entonces este rol instalará nvm
bajo el ROOT_USER
(generalmente /root/.bashrc
). Lo más probable es que desees ejecutar nvm y node como un usuario predeterminado, por ejemplo, vagrant, ec2-user, ubuntu, etc. Si, por cualquier razón, no puedes eliminar el become: true
para todo, puedes sortear el problema de become: true
especificando become: true
Y become_user: ec2-user
para este rol en particular. Consulta bash: comando nvm no encontrado para una explicación detallada del problema.
"no se puede encontrar /usr/bin/python"
Se debe a que algunos sistemas operativos que ejecutan Python 3 de forma predeterminada (por ejemplo, Fedora). Necesitarás especificar la variable del intérprete de python de Ansible en el archivo de inventario o a través de la línea de comando.
[fedora1]
192.168.0.1 ansible_python_interpreter=/usr/bin/python3
[fedora2]
192.168.0.2
[fedora2:vars]
ansible_python_interpreter=/usr/bin/python3
o
ansible-playbook my-playbook.yml -e "ansible_python_interpreter=/usr/bin/python3"
glibc_2.28' no encontrado (requerido por node)
Estás intentando ejecutar una versión de Node.js en un sistema operativo que no es compatible con la versión de Node.js que estás instalando. Esto no es un problema de NVM ni con el rol. Debes actualizar el SO o reducir la versión de Node.js que estás intentando instalar.
Soporte de Versiones de Ansible
ansible-core 2.16 +
Ha habido un cambio fundamental en cómo Ansible gestiona las inclusiones/importaciones. Ansible ha eliminado ansible.builtin.include
de ansible-core y lo ha reemplazado con ansible.builtin.include_tasks
. Desafortunadamente, Ansible no puede limitar ansible.builtin.include
para ignorar versiones más antiguas, etc., por lo que actualicé este rol para soportar completamente ansible-core 2.16 +.
Si requieres soporte para ansible-core 2.15 o inferior, por favor usa la rama legacy 1.5.X.
ansible-core 2.15 y versiones anteriores
Por favor utiliza la rama 1.5.X legacy.
Variables del Rol
Las variables disponibles se enumeran a continuación, junto con sus valores por defecto. Consulta defaults/main.yml.
La versión de Node.js a instalar. La última versión "lts" es la predeterminada y funciona en la mayoría de los sistemas operativos soportados.
nodejs_version: "lts"
Método conveniente para instalar autocompletado bash de NVM (nvm <TAB>
) cuando un usuario tiene que mantener un servidor o estación de trabajo manualmente.
autocomplete: false
Instala NVM desde cero, eliminando CUALQUIER y TODAS las referencias existentes o anteriores a .nvm
(directorios) y CUALQUIER y TODAS las referencias existentes o anteriores en entradas de perfil, por ejemplo, .bashrc
en el sistema.
clean_install: false
clean_install: true
busca todas las referencias en/home
,/root
,/etc
, ydirectorios de instalación personalizados
así como cualquier carpeta.nvm
en el sistema. Esto equivale a una configuración de nueva máquina, ÚSALO CON PRECAUCIÓN.
default: false
Establece la versión predeterminada de Node al mantener/instalar múltiples versiones de Node.
NVM hará alias automáticamente la primera versión instalada como "predeterminada", lo que es más que probable que sea lo que las personas usarán este rol.
Lista de comandos NVM para ejecutar. Por defecto, es una lista vacía.
nvm_commands: []
Tipo de instalación de NVM. Las opciones son wget, curl y git.
nvm_install: "wget"
Directorio de instalación de NVM.
nvm_dir: ""
NVM instalará, por defecto, el directorio
.nvm
en el home del usuario, por ejemplo,/home/vagrant/.nvm
. Puedes sobreescribir el directorio de instalación cambiando esta variable, por ejemplo,/opt/nvm
para ponerlo en un espacio global (no ligado a una cuenta de usuario específica) si lo deseas. Esta variable respetará las variables de sustitución de Ansible, por ejemplo,{{ansible_env.HOME}}
.
Ubicación del perfil de NVM. Las opciones son .bashrc, .cshrc, .tcshrc, .zshrc.
nvm_profile: ".bashrc"
La ubicación del archivo de perfil del SHELL de inicio que cargará el comando nvm. Hay dos contextos potenciales a considerar:
Globalmente, lo que significa que todos los que inicien sesión tendrán acceso a nvm (lo cual puede o no ser lo que realmente deseas).
por ejemplo,
/etc/bash.bashrc
,/etc/profile
, etc.O
A nivel de usuario, ligado a una cuenta de usuario específica.
por ejemplo,
/home/vagrant/.bashrc
.*Este rol creará el archivo de perfil apropiado si no existe.
Si especificas explícitamente nvm_profile: "/home/node-user/.bashrc" y el usuario node-user no es un usuario real en la máquina, entonces nvm no funcionará como esperas. Las rutas de become, become_user y nvm_profile son simbióticas.
:warning: TEN EN CUENTA LAS LIMITACIONES DE DECLARAR EXPLÍCITAMENTE ARCHIVOS .profile O .bash_profile EN SISTEMAS UBUNTU.
https://askubuntu.com/a/969923 Explica en detalle
https://kb.iu.edu/d/abdy Muestra opciones para cada tipo de shell.
Las ubicaciones de los perfiles de NVM son:
BASH: .bashrc
CSH: /etc/csh.cshrc, .cshrc
TSH: /etc/csh.cshrc, .tcshrc, .cshrc
ZSH: .zshrc
Ubicación de la fuente de NVM, es decir, si hosteas tu propia bifurcación de NVM.
nvm_source: ""
Versión de NVM a instalar.
nvm_version: "0.39.7"
Desinstalar NVM, eliminará el directorio .nvm y limpiará el archivo ubicado en la ruta de la variable {{ nvm_profile }}
(generalmente $HOME/.bashrc) donde quiera que ese archivo esté.
uninstall: False
Dependencias
Ninguna.
Registro de Cambios
2.0.0 Consulta las NOTAS DE LANZAMIENTO.
Licencia
MIT / BSD.
Información del Autor
dm00000 a través de MORGANGRAPHICS, INC.
Este rol se basa en gran medida en el rol de Node.js de Jeff Geerling, autor de Ansible for DevOps.
NVM installation for Linux
ansible-galaxy install morgangraphics.ansible-role-nvm