nvm icon indicating copy to clipboard operation
nvm copied to clipboard

Installation fails, if not using `bash` (new intended behavior)

Open DJAlPee opened this issue 1 year ago • 3 comments

Operating system and version:

Using a hardened Alpine container image as base image for our CI/CD container image.

nvm debug output:

/app # nvm debug
nvm --version: v0.39.2
$SHELL: 
$SHLVL: 1
whoami: 'root'
${HOME}: /root
${NVM_DIR}: '${HOME}/.nvm'
${PATH}: ${NVM_DIR}/versions/node/v14.20.1/bin:/usr/local/share/.config/yarn/global/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$PREFIX: ''
${NPM_CONFIG_PREFIX}: ''
$NVM_NODEJS_ORG_MIRROR: 'https://unofficial-builds.nodejs.org/download/release'
$NVM_IOJS_ORG_MIRROR: ''
sh: --version: not found
shell version: ''
uname -a: 'Linux 5.15.64-0-virt #1-Alpine SMP Mon, 05 Sep 2022 08:02:49 +0000 x86_64 GNU/Linux'
checksum binary: 'sha256sum'
OS version: Authorized uses only. All activity may be monitored and reported.
curl: /usr/bin/curl, curl 7.79.1 (x86_64-alpine-linux-musl) libcurl/7.79.1 OpenSSL/1.1.1l zlib/1.2.11 brotli/1.0.9 nghttp2/1.43.0
wget: /usr/bin/wget, GNU Wget 1.21.1 built on linux-musl.
git: /usr/bin/git, git version 2.32.3
grep: /bin/grep, BusyBox v1.33.1 () multi-call binary.
awk: /usr/bin/awk, BusyBox v1.33.1 () multi-call binary.
sed: /bin/sed, BusyBox v1.33.1 () multi-call binary.
cut: /usr/bin/cut, cut (GNU coreutils) 8.32
basename: /usr/bin/basename, basename (GNU coreutils) 8.32
rm: /bin/rm, rm (GNU coreutils) 8.32
mkdir: /bin/mkdir, mkdir (GNU coreutils) 8.32
xargs: /usr/bin/xargs, BusyBox v1.33.1 () multi-call binary.
nvm current: v14.20.1
which node: ${NVM_DIR}/versions/node/v14.20.1/bin/node
which iojs: 
which npm: ${NVM_DIR}/versions/node/v14.20.1/bin/npm
npm config get prefix: ${NVM_DIR}/versions/node/v14.20.1
npm root -g: ${NVM_DIR}/versions/node/v14.20.1/lib/node_modules

nvm ls output:

/app # nvm ls
->     v14.20.1 *
       v16.18.0 *
       v18.11.0 *
         system *
default -> 14 (-> v14.20.1 *)
iojs -> N/A (default)
node -> stable (-> v18.11.0 *) (default)
stable -> 18.11 (-> v18.11.0 *) (default)
unstable -> N/A (default)
lts/* -> lts/gallium (-> v16.18.0 *)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.12 (-> N/A)
lts/fermium -> v14.20.1 *
lts/gallium -> v16.18.0 *

How did you install nvm?

ARG VERSION_NVM=0.39.2
ARG VERSION_NODE="14 16 18"
ENV NVM_NODEJS_ORG_MIRROR=https://unofficial-builds.nodejs.org/download/release
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v${VERSION_NVM}/install.sh | sh && \
    NVM_DIR=${HOME}/.nvm && \
    source ${HOME}/.nvm/nvm.sh && \
    nvm_get_arch() { nvm_echo "${ARCH_NODE}"; } && \
    for version in ${VERSION_NODE}; do nvm install --latest-npm ${version}; done

Create container image

docker build .

What steps did you perform?

I updated VERSION_NVM from 0.39.1 to 0.39.2 (Patch version change!). Now docker build fails: Error: the install instructions explicitly say to pipe the install script to 'bash'; please follow them. Changing the curl installation part from sh to bash solved this issue, although I want to avoid using bash. Bash is not installed by default on Alpine and could be removed at any time from our hardened container image.

This check had been introduced with this commit: https://github.com/nvm-sh/nvm/commit/39d9a42c359df5dbf37c5000af8192f14a280b94

The commands above had been executed, after sucessfull installation with bash.

What did you expect to happen?

Usage of sh should still be possible, but maybe with a big warning message, that this is not the "official" way to install it.

Is there anything in any of your profile files that modifies the PATH?

Nope.

If you are having installation issues, or getting "N/A", what does curl -I --compressed -v https://nodejs.org/dist/ print out?

/app # curl -I --compressed -v https://nodejs.org/dist/
*   Trying 104.20.22.46:443...
* Connected to nodejs.org (104.20.22.46) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.nodejs.org
*  start date: Jan 11 00:00:00 2022 GMT
*  expire date: Feb 11 23:59:59 2023 GMT
*  subjectAltName: host "nodejs.org" matched cert's "nodejs.org"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x4001cfaa90)
> HEAD /dist/ HTTP/2
> Host: nodejs.org
> user-agent: curl/7.79.1
> accept: */*
> accept-encoding: deflate, gzip, br
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 256)!
< HTTP/2 200 
HTTP/2 200 
< date: Fri, 14 Oct 2022 10:20:31 GMT
date: Fri, 14 Oct 2022 10:20:31 GMT
< content-type: text/html
content-type: text/html
< last-modified: Fri, 14 Oct 2022 09:05:15 GMT
last-modified: Fri, 14 Oct 2022 09:05:15 GMT
< cache-control: max-age=14400
cache-control: max-age=14400
< cf-cache-status: HIT
cf-cache-status: HIT
< age: 2622
age: 2622
< vary: Accept-Encoding
vary: Accept-Encoding
< strict-transport-security: max-age=31536000; includeSubDomains; preload
strict-transport-security: max-age=31536000; includeSubDomains; preload
< x-content-type-options: nosniff
x-content-type-options: nosniff
< server: cloudflare
server: cloudflare
< cf-ray: 759f953908550b5f-AMS
cf-ray: 759f953908550b5f-AMS
< content-encoding: br
content-encoding: br

< 
* Connection #0 to host nodejs.org left intact

DJAlPee avatar Oct 14 '22 10:10 DJAlPee

Lots of things aren't installed by default on alpine, but they're required for use of nvm and/or node - all the "minimalism" of alpine seems to get erased once you add all the things your toolchain needs ¯\_(ツ)_/¯

The install script is bash-specific, so it won't work reliably on sh. You could certainly set the BASH_VERSION env var to a fake value before running the install script, but I wouldn't recommend it.

ljharb avatar Oct 14 '22 19:10 ljharb

Coupling NVM to a specific shell is a bad idea. NVM already works for zsh on macs, why can't it support sh? Didn't it used to?

I currently can't find a documented way to install NVM in a docker image—which is a pretty common use case. This issue seems to be the limiting factor.

robbyemmert avatar Apr 02 '24 12:04 robbyemmert

@robbyemmert nvm itself definitely works on sh - the install script NEVER has worked reliably on anything but bash.

There's an official nvm docker image on dockerhub, and a Dockerfile in this repo: https://github.com/nvm-sh/nvm/blob/HEAD/Dockerfile

ljharb avatar Apr 02 '24 16:04 ljharb