eth3rnit3
eth3rnit3

Reputation: 801

Ansible install node with nvm

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

Answers (6)

Martin Braun
Martin Braun

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

Jay Lepore
Jay Lepore

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

ggedde
ggedde

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

Taavi Ansper
Taavi Ansper

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

eth3rnit3
eth3rnit3

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

clockworknet
clockworknet

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

Related Questions