From d9c972803adc2d0a3c30ae8189a386733663eb3a Mon Sep 17 00:00:00 2001 From: Jose M Leon Date: Thu, 27 Nov 2025 19:24:47 +0000 Subject: [PATCH 1/2] feat(node): add support for custom Node.js mirror in nvm installs - Introduce nvmNodeJsOrgMirror option to specify a custom Node.js binaries mirror. - Pass NVM_NODEJS_ORG_MIRROR environment variable to nvm install commands. - Update devcontainer-feature.json to include new option. - Add tests to verify environment variable and nvm remote listing with mirror. Co-authored-by: terragon-labs[bot] --- src/node/devcontainer-feature.json | 6 +++++- src/node/install.sh | 7 +++++-- test/node/scenarios.json | 8 ++++++++ test/node/test_registry_override.sh | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100755 test/node/test_registry_override.sh diff --git a/src/node/devcontainer-feature.json b/src/node/devcontainer-feature.json index 1828ba0d5..c72803759 100644 --- a/src/node/devcontainer-feature.json +++ b/src/node/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "node", - "version": "1.6.3", + "version": "1.6.4", "name": "Node.js (via nvm), yarn and pnpm", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/node", "description": "Installs Node.js, nvm, yarn, pnpm, and needed dependencies.", @@ -50,6 +50,10 @@ "default": "latest", "description": "Version of NVM to install." }, + "nvmNodeJsOrgMirror": { + "type": "string", + "description": "The mirror of the Node.js binaries. Use this to point to a private mirror." + }, "installYarnUsingApt": { "type": "boolean", "default": true, diff --git a/src/node/install.sh b/src/node/install.sh index 46d448440..38beaefd1 100755 --- a/src/node/install.sh +++ b/src/node/install.sh @@ -11,6 +11,7 @@ export NODE_VERSION="${VERSION:-"lts"}" export PNPM_VERSION="${PNPMVERSION:-"latest"}" export NVM_VERSION="${NVMVERSION:-"latest"}" export NVM_DIR="${NVMINSTALLPATH:-"/usr/local/share/nvm"}" +export NVM_NODEJS_ORG_MIRROR="${NVMNODEJSORGMIRROR:-}" INSTALL_TOOLS_FOR_NODE_GYP="${NODEGYPDEPENDENCIES:-true}" export INSTALL_YARN_USING_APT="${INSTALLYARNUSINGAPT:-true}" # only concerns Debian-based systems @@ -302,6 +303,7 @@ find_version_from_git_tags NVM_VERSION "https://github.com/nvm-sh/nvm" nvm_install_snippet="$(cat << EOF set -e umask 0002 +${NVM_NODEJS_ORG_MIRROR:+export NVM_NODEJS_ORG_MIRROR="${NVM_NODEJS_ORG_MIRROR}"} # Do not update profile - we'll do this manually export PROFILE=/dev/null curl -so- "https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh" | bash || { @@ -318,6 +320,7 @@ EOF # Snippet that should be added into rc / profiles nvm_rc_snippet="$(cat << EOF +${NVM_NODEJS_ORG_MIRROR:+export NVM_NODEJS_ORG_MIRROR="${NVM_NODEJS_ORG_MIRROR}"} export NVM_DIR="${NVM_DIR}" [ -s "\$NVM_DIR/nvm.sh" ] && . "\$NVM_DIR/nvm.sh" [ -s "\$NVM_DIR/bash_completion" ] && . "\$NVM_DIR/bash_completion" @@ -350,7 +353,7 @@ if [ ! -d "${NVM_DIR}" ]; then else echo "NVM already installed." if [ "${NODE_VERSION}" != "" ]; then - su ${USERNAME} -c "umask 0002 && . '$NVM_DIR/nvm.sh' && nvm install '${NODE_VERSION}' && nvm alias default '${NODE_VERSION}'" + su ${USERNAME} -c "umask 0002 && . '$NVM_DIR/nvm.sh' && ${NVM_NODEJS_ORG_MIRROR:+NVM_NODEJS_ORG_MIRROR=\"${NVM_NODEJS_ORG_MIRROR}\"} nvm install '${NODE_VERSION}' && nvm alias default '${NODE_VERSION}'" fi fi @@ -366,7 +369,7 @@ if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then IFS="," read -a additional_versions <<< "$ADDITIONAL_VERSIONS" for ver in "${additional_versions[@]}"; do - su ${USERNAME} -c "umask 0002 && . '$NVM_DIR/nvm.sh' && nvm install '${ver}'" + su ${USERNAME} -c "umask 0002 && . '$NVM_DIR/nvm.sh' && ${NVM_NODEJS_ORG_MIRROR:+NVM_NODEJS_ORG_MIRROR=\"${NVM_NODEJS_ORG_MIRROR}\"} nvm install '${ver}'" # possibly install yarn (puts yarn in per-Node install on RHEL, uses system yarn on Debian) install_yarn "${ver}" done diff --git a/test/node/scenarios.json b/test/node/scenarios.json index d9a0c527e..78229d894 100644 --- a/test/node/scenarios.json +++ b/test/node/scenarios.json @@ -7,6 +7,14 @@ } } }, + "test_registry_override": { + "image": "debian:11", + "features": { + "node": { + "nvmNodeJsOrgMirror": "https://nodejs.org/dist" + } + } + }, "install_additional_node": { "image": "debian:11", "features": { diff --git a/test/node/test_registry_override.sh b/test/node/test_registry_override.sh new file mode 100755 index 000000000..e5dfc0855 --- /dev/null +++ b/test/node/test_registry_override.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +# Import test library +source dev-container-features-test-lib + +# Check if env var is set +check "NVM_NODEJS_ORG_MIRROR is set" bash -c "echo $NVM_NODEJS_ORG_MIRROR | grep 'https://nodejs.org/dist'" + +# Check if nvm can list remote versions (verifies network/config is vaguely sane) +check "nvm ls-remote" bash -c ". /usr/local/share/nvm/nvm.sh && nvm ls-remote | head" + +reportResults From a8a4b2d32b34c7c6b7dcdbbc16832d735847e8ca Mon Sep 17 00:00:00 2001 From: Jose M Leon Date: Thu, 27 Nov 2025 19:31:50 +0000 Subject: [PATCH 2/2] feat(node): add private mirror option for Node.js binaries Introduce the `nvmNodeJsOrgMirror` option to allow using a private Node.js binary mirror. This supports air-gapped or restricted environments by enabling downloads from custom URLs. - Updated README.md and NOTES.md with documentation and usage examples for the new option. Co-authored-by: terragon-labs[bot] --- src/node/NOTES.md | 12 ++++++++++++ src/node/README.md | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/node/NOTES.md b/src/node/NOTES.md index 506fa1b4e..8e0a18a03 100644 --- a/src/node/NOTES.md +++ b/src/node/NOTES.md @@ -25,3 +25,15 @@ Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, and Rocky Linux distributi **Note**: RedHat 7 Family (RedHat, CentOS, etc.) must use Node versions less than 18 due to its system libraries and long-term support (LTS) policies. `bash` is required to execute the `install.sh` script. + +## Setting a private Node.js mirror + +If you need to use a private mirror for downloading Node.js binaries (e.g. in an air-gapped environment), you can use the `nvmNodeJsOrgMirror` option: + +```json +"features": { + "ghcr.io/devcontainers/features/node:1": { + "nvmNodeJsOrgMirror": "https://my-private-registry.com/node-dist" + } +} +``` diff --git a/src/node/README.md b/src/node/README.md index 328af529f..ad7a6fd4f 100644 --- a/src/node/README.md +++ b/src/node/README.md @@ -20,6 +20,7 @@ Installs Node.js, nvm, yarn, pnpm, and needed dependencies. | nvmInstallPath | The path where NVM will be installed. | string | /usr/local/share/nvm | | pnpmVersion | Select or enter the PNPM version to install | string | latest | | nvmVersion | Version of NVM to install. | string | latest | +| nvmNodeJsOrgMirror | The mirror of the Node.js binaries. Use this to point to a private mirror. | string | - | | installYarnUsingApt | On Debian and Ubuntu systems, you have the option to install Yarn globally via APT. If you choose not to use this option, Yarn will be set up using Corepack instead. This choice is specific to Debian and Ubuntu; for other Linux distributions, Yarn is always installed using Corepack, with a fallback to installation via NPM if an error occurs. | boolean | true | ## Customizations @@ -56,6 +57,18 @@ Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, and Rocky Linux distributi `bash` is required to execute the `install.sh` script. +## Setting a private Node.js mirror + +If you need to use a private mirror for downloading Node.js binaries (e.g. in an air-gapped environment), you can use the `nvmNodeJsOrgMirror` option: + +```json +"features": { + "ghcr.io/devcontainers/features/node:1": { + "nvmNodeJsOrgMirror": "https://my-private-registry.com/node-dist" + } +} +``` + ---