Reputation: 801
I'm looking for a way to install a given version of node via ansible and nvm, the installation of nvm is working as expected because if I connect with the root user, I can execute the command nvm install 8.11.3 but this same command doesn't work with Ansible, I don't understand why.
---
- name: Install nvm
git: repo=https://github.com/creationix/nvm.git dest=~/.nvm version=v0.33.11
tags: nvm
- name: Source nvm in ~/.{{ item }}
lineinfile: >
dest=~/.{{ item }}
line="source ~/.nvm/nvm.sh"
create=yes
tags: nvm
with_items:
- bashrc
- profile
- name: Install node and set version
become: yes
become_user: root
shell: nvm install 8.11.3
...
error log
TASK [node : Install node and set version] *************************************************************************************
fatal: [51.15.128.164]: FAILED! => {"changed": true, "cmd": "nvm install 8.11.3", "delta": "0:00:00.005883", "end": "2018-12-03 15:05:10.394433", "msg": "non-zero return code", "rc": 127, "start": "2018-12-03 15:05:10.388550", "stderr": "/bin/sh: 1: nvm: not found", "stderr_lines": ["/bin/sh: 1: nvm: not found"], "stdout": "", "stdout_lines": []}
to retry, use: --limit .../.../ansible/stater-debian/playbook.retry
Upvotes: 9
Views: 15528
Reputation: 12619
NodeSource seems to do a pretty good job when it comes to nodejs enterprise distributions. My goal was to have an independent node version on a Debian machine that would be major-version locked, no matter I upgrade Debian or not. n
or nvm
are great for development, but why should I install additional packages, that I will never touch again after the setup? Maybe you want to consider to overthink your decision about using nvm
?
I rather deploy the version of node that I need immediately, and only it and nothing else. Here is an example for node v18 on Debian by using the NodeSource PPA via their helper script:
- setup: # gather facts
- name: Upgrade via OS package manager
package: upgrade=full update_cache=yes
- stat: path=/etc/apt/sources.list.d/nodesource.list get_checksum=yes
register: stat_nodesource_list_before
- name: Ensure nodesource repository (Debian)
shell: curl -sL https://deb.nodesource.com/setup_18.x | bash -
when: ansible_facts['os_family'] == "Debian"
changed_when: False
- stat: path=/etc/apt/sources.list.d/nodesource.list get_checksum=yes
register: stat_nodesource_list_after
- debug: msg='nodesource.list has been refreshed'
changed_when: "stat_nodesource_list_before.stat.checksum != stat_nodesource_list_after.stat.checksum"
- name: Ensure packages (Debian)
package:
name:
- nodejs
when: ansible_facts['os_family'] == "Debian"
register: package_debian
- fail: msg='Unsupported OS'
when: "package_debian is skipped"
NodeSource's script will always tee
to nodesource.list
, so I added some checksum checks to have a way to tell the file was changed. The sample is ready to be extended for more distributions.
Upvotes: 0
Reputation: 153
Based on all the posts found on stack and tweaked a little for my own needs - I found this solution worked perfectly for both installing NVM (the easy part) and creating a loop that allows you to insert 1 or many versions of Node as needed
# test if nvm has been installed by the user desired
- stat:
path: /home/yournonrootuser/.nvm
register: nvm_path
- name: Setup NodeVersionManager and install node version
become: yes
# Execute config files such as .profile (Ansible uses non-interactive login shells)
become_flags: -i
become_user: yournonrootuser
block:
- name: Install nvm
shell: >
curl -o- https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
args:
executable: /bin/bash
chdir: "$HOME"
creates: "$HOME/.nvm/nvm.sh"
- name: Setup .profile of yournonrootuser
lineinfile:
path: ~/.profile
# This will make sure Node is on the users PATH
line: source ~/.nvm/nvm.sh
create: yes
become_flags: -i
when: nvm_path.stat.exists == false
# if we got here we already know node version manager is installed
- name: installing node versions using loop
command: sudo -iu yournonrootuser nvm install {{item}}
args:
executable: /bin/bash
chdir: "$HOME"
creates: "$HOME/.nvm/versions/node/v{{item}}"
loop:
- 14.18.3
Upvotes: 2
Reputation: 652
This worked for me on Ubuntu 20.04 using nvm version 0.39.1:
- name: Install NVM
shell: >
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
args:
creates: "/root/.nvm/nvm.sh"
- name: Install Node Versions
shell: ". /root/.bashrc && nvm install {{item}}"
with_items:
- 'v10.24.1'
- 'v16.17.0'
- '--lts'
- 'node'
Upvotes: 0
Reputation: 163
I will just post under here, because there are hundreds of these posts.
- name: Install node
become: true
become_user: root
shell: "source /root/.nvm/nvm.sh && nvm install {{ personal_node_version }} && nvm alias default {{ personal_node_version }}"
args:
executable: /bin/bash
worked for me.
Upvotes: 0
Reputation: 801
It's okay, here's the configuration that works
- name: Install node and set version
become: yes
become_user: root
shell: "source /root/.nvm/nvm.sh && nvm install 8.11.3"
args:
executable: /bin/bash
Upvotes: 21
Reputation: 3056
I think the clue in the output you need is:
"/bin/sh: 1: nvm: not found"
To run a command without including the full path to that command (i.e. nvm
rather than /the/dir/nvm/is/installed/in/nvm
), then the directory that contains the command, must be in the $PATH environment variable for the shell that runs the command.
In this case it looks like that is not present for the shell that Ansible spawns, versus the shell your interactive commands run in. Change:
- name: Install node and set version
become: yes
become_user: root
shell: nvm install 8.11.3
to
- name: Install node and set version
become: yes
become_user: root
shell: /full/path/to/nvm install 8.11.3
If you don't know what to put in place of '/full/path/to', try either:
which nvm
or
find / -name nvm
Upvotes: 1