NVM (Node Version Manager) is a shell script that lets you install and switch between multiple Node.js versions on the same machine without requiring root access or affecting system-wide packages. This is invaluable when you work on projects that require different Node.js versions simultaneously, or when you need to test your application against multiple runtimes. On RHEL 8, NVM installs entirely into your home directory and integrates with Bash and Zsh. This tutorial covers installing NVM, managing Node.js versions, pinning versions per project with .nvmrc, and correctly referencing NVM-managed Node.js binaries in systemd services.

Prerequisites

  • RHEL 8 server with a non-root user account
  • curl available (sudo dnf install -y curl)
  • Bash or Zsh as your login shell
  • No conflicting system Node.js installation required (NVM coexists with system Node.js)

Step 1 — Install NVM

The official NVM installer downloads the script directly from GitHub and appends the necessary initialization lines to your shell profile. Pin to a specific release tag rather than using HEAD for reproducibility.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

Reload your shell profile to activate NVM in the current session:

source ~/.bashrc

Verify NVM is loaded:

nvm --version

Step 2 — Install Node.js Versions

Use nvm install followed by a version number or LTS codename. NVM will download the binary and set it as the active version for your current shell session.

# Install the latest Node.js 20 LTS release
nvm install 20

# Install an additional version alongside it
nvm install 18

# List all installed versions
nvm ls

# List all available remote versions (long list — pipe to grep to filter)
nvm ls-remote | grep -i lts

Step 3 — Switch Between Versions and Set a Default

Use nvm use to activate a version for the current terminal session, and nvm alias default to set the version that is active in every new shell.

# Switch to Node.js 20 in the current session
nvm use 20

# Confirm the active version
node --version
npm --version

# Set Node.js 20 as the default for all new sessions
nvm alias default 20

# List aliases
nvm alias

Step 4 — Pin Versions Per Project with .nvmrc

A .nvmrc file in a project root tells NVM which Node.js version that project requires. This is the standard way to ensure all contributors and CI pipelines use the same runtime.

cd ~/myproject

# Create .nvmrc specifying Node.js 20
echo "20" > .nvmrc

# Activate the version specified in .nvmrc (run from the project directory)
nvm use

# Install the version from .nvmrc if it is not yet installed
nvm install

You can also add an auto-switch hook in ~/.bashrc that automatically calls nvm use when you cd into a directory containing a .nvmrc file — see the NVM README for the snippet.

Step 5 — Find the Absolute Node.js Path for systemd

systemd units do not source shell profiles, so NVM’s shims are not available in unit ExecStart lines. Use the full binary path instead.

# Find the exact path to the Node.js binary for the active version
nvm which 20

Example output: /root/.nvm/versions/node/v20.19.1/bin/node. Use this absolute path in your systemd service:

sudo tee /etc/systemd/system/mynodeapp.service > /dev/null << 'EOF'
[Unit]
Description=My Node.js Application
After=network.target

[Service]
User=youruser
WorkingDirectory=/home/youruser/myproject
ExecStart=/home/youruser/.nvm/versions/node/v20.19.1/bin/node app.js
Restart=always
RestartSec=10
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now mynodeapp
sudo systemctl status mynodeapp

Step 6 — Update and Remove Versions

NVM makes it straightforward to upgrade Node.js or clean up versions you no longer need.

# Install the latest patch release for Node.js 20 and migrate global packages
nvm install 20 --reinstall-packages-from=20

# Uninstall a specific version
nvm uninstall 18

# Update NVM itself by re-running the installer with the new version tag
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

Conclusion

NVM gives you fine-grained control over Node.js versions on RHEL 8, allowing different projects to run different runtimes without conflicts. The key operational detail is always using absolute binary paths in systemd units since those units do not inherit your shell environment. Pairing NVM with .nvmrc files ensures consistent runtimes across development and production environments.

Next steps: How to Deploy a Node.js Application with PM2 on RHEL 8, How to Install Node.js on RHEL 8, and Setting Up Nginx as a Reverse Proxy for Node.js on RHEL 8.