The Node.js version your project needs is almost never the one sitting in the Ubuntu or Debian repositories. Applications pin a major release, CI images pin another, and the distro package lags years behind both. Installing a specific Node.js version, not just whatever is newest, is the actual task, and there are two clean ways to do it: the NodeSource apt repository when the whole machine should run one major, and nvm when you need to switch versions per project.
This guide covers both, plus the parts that catch people out: downgrading between majors with apt, holding a version so unattended upgrades cannot move it, and letting a .nvmrc file pick the version for you. Everything below was run on an Ubuntu 24.04 base in August 2026, when the active LTS line was Node.js 24.19.0, with Node.js 22 and 20 as the pinned examples. The same commands apply on Debian.
Check What the Default Repositories Ship
Before adding anything, see what apt would give you today:
apt policy nodejs
On a current Ubuntu LTS system the candidate comes from universe and is already past its end of life:
nodejs:
Installed: (none)
Candidate: 18.19.1+dfsg-6ubuntu5
Version table:
18.19.1+dfsg-6ubuntu5 500
500 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages
That line stopped receiving security updates upstream in April 2025, and the distro package also ships without npm, which you would install separately. This is why neither method in this guide touches the default repositories. The Node.js release schedule is the reference for which majors are still supported: even numbered lines enter LTS each October and get roughly three years of updates.
Install a Specific Node.js Major from NodeSource
NodeSource publishes one apt repository per Node.js major. Set the major you want in a variable, then run the matching setup script. It imports the signing key and writes the repository definition for you:
export NODE_MAJOR=22
curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | sudo -E bash -
The script now writes a deb822 style file at /etc/apt/sources.list.d/nodesource.sources rather than the old one line nodesource.list, and the suite is a distro agnostic nodistro, so the same repository serves every Ubuntu and Debian release:
Types: deb
URIs: https://deb.nodesource.com/node_22.x
Suites: nodistro
Components: main
Architectures: amd64
Signed-By: /usr/share/keyrings/nodesource.gpg
Install the package. Unlike the distro build, the NodeSource nodejs package bundles npm and npx in the same package:
sudo apt install -y nodejs
node -v
npm -v
The reported versions match the pinned major:
v22.23.2
10.9.8
If you want the current LTS rather than a named major, setup_lts.x resolves to it automatically. At the time of testing it configured the same repository layout pointing at node_24.x, and the package arrived with npm, npx, and corepack included. There are dedicated walkthroughs for that default path in the Node.js 24 LTS on Ubuntu guide and, if you are on the newest release, Node.js on Ubuntu 26.04 with four install methods. Debian specifics are covered in installing Node.js on Debian, and the RHEL family in the Rocky Linux and AlmaLinux guide.
Fix “nodejs is already the newest version” When Switching Majors
Moving up a major is painless: run the setup script for the newer line and apt install nodejs upgrades in place. Moving down is where apt digs in. After switching the repository to an older line, the installed package still wins:
nodejs is already the newest version (24.19.0-1nodesource1).
0 upgraded, 0 newly installed, 0 to remove and 460 not upgraded.
apt refuses to downgrade on its own. Tell it explicitly, naming the exact version string shown by apt policy nodejs:
sudo apt install -y --allow-downgrades nodejs=22.23.2-1nodesource1
dpkg logs the downgrade and the binary follows:
dpkg: warning: downgrading nodejs from 24.19.0-1nodesource1 to 22.23.2-1nodesource1
Setting up nodejs (22.23.2-1nodesource1) ...
Once the machine runs the version your application was certified on, freeze it so a routine apt upgrade or unattended upgrades cannot move it:
sudo apt-mark hold nodejs
Release the hold with sudo apt-mark unhold nodejs when you are ready to take patch releases again. Holding across a whole major for long is a bad habit though, since patch releases within your pinned line carry the security fixes.
Install and Switch Versions Per Project with nvm
A system wide package only holds one version at a time. When different projects need different majors on the same machine, nvm keeps them side by side in your home directory, no root required. Detect the latest nvm release and install it:
export NVM_VER=$(curl -s https://api.github.com/repos/nvm-sh/nvm/releases/latest | grep -oP '"tag_name": "\K[^"]+')
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VER}/install.sh | bash
The installer appends its loader to your shell profile. Open a new terminal or source the profile, then pull in the versions you need. Named majors and the current LTS both work:
source ~/.bashrc
nvm install --lts
nvm install 22
nvm install 20
Each install lands under ~/.nvm/versions/node/ with its own matching npm. List what is present and jump between them:
nvm ls --no-alias
nvm use 22
The active version is marked with an arrow, and switching takes effect immediately in that shell:
v20.20.2 *
-> v22.23.2 *
v24.19.0 *
Now using node v22.23.2 (npm v10.9.8)
Two habits make nvm stick in real projects. First, set the version new shells start with:
nvm alias default 22
Second, commit a .nvmrc file to each repository so nobody has to remember which version the project expects:
echo "22" > .nvmrc
nvm use
nvm reads the file and activates the right runtime:
Found '/home/dev/legacy-app/.nvmrc' with version <22>
Now using node v22.23.2 (npm v10.9.8)
The same per project discipline pairs well with a workspace aware package manager once repositories grow, which the Turborepo and pnpm monorepo setup walks through.
Verify the Runtime Works
A version string proves the binary is on the PATH, not that it serves traffic. Create a minimal HTTP server to run:
vim hello.js
Paste in a server that reports its own runtime version, which confirms the exact binary answering requests:
const http = require("node:http");
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Node.js " + process.version + " is working\n");
});
server.listen(3000, () => console.log("Listening on http://localhost:3000"));
Start it and hit it from a second terminal:
node hello.js
curl http://localhost:3000
The response names the version that handled the request, in this run the machine wide NodeSource LTS install rather than the nvm managed copy:
Node.js v24.19.0 is working
If your dependencies compile native addons through node-gyp, install the toolchain they expect once per machine:
sudo apt install -y build-essential
Remove a NodeSource Install Cleanly
Migrating a machine from the apt package to nvm, or just retiring Node.js, takes three pieces: the package, the repository definition, and the signing key:
sudo apt purge -y nodejs
sudo rm -f /etc/apt/sources.list.d/nodesource.sources /usr/share/keyrings/nodesource.gpg /etc/apt/preferences.d/nsolid
sudo apt update
One detail worth knowing: purging the apt package does not touch nvm. In testing, node -v failed in a fresh shell after the purge, then worked again the moment the nvm loader ran, because the nvm managed copies live entirely under ~/.nvm. Individual nvm versions go away with nvm uninstall 20 style commands. Whichever method stays, the runtime you keep should be a supported line from the release schedule, and if you are building serious services on it, the picks in our Node.js book roundup go deeper than any install guide can.
Thank you so much for laying out this. I am trying to learn coding on a Chromebook and your guide is/was spot on. Many thanks.
Welcome and thanks for the comment.
Thank you.
Just what i needed.
Welcome
thanks mate
Welcome
Doesn’t work for Ubuntu 22.04.1 Jammy for Desktop
It fails at the apt install part
We have tested on Ubuntu 22.04 and it works. Check if you have another version of Node installed.
I get the following error when running:
$ sudo apt -y install nodejs
…
Preparing to unpack …/nodejs_14.21.3-deb-1nodesource1_amd64.deb …
Unpacking nodejs (14.21.3-deb-1nodesource1) over (12.22.9~dfsg-1ubuntu3) …
dpkg: error processing archive /var/cache/apt/archives/nodejs_14.21.3-deb-1nodesource1_amd64.deb (–unpack):
trying to overwrite ‘/usr/share/systemtap/tapset/node.stp’, which is also in package libnode72:amd64 12.22.9~dfsg-1ubuntu3
Errors were encountered while processing:
/var/cache/apt/archives/nodejs_14.21.3-deb-1nodesource1_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
any help would be appreciated!
Try running the commands below and share feedback:
sudo apt purge nodejs
sudo apt autoremove
sudo apt install nodejs
Also
sudo apt remove libnode72 && sudo apt install nodejs
It installed v18 not v14 as expected
Did you add the repos as in the guide?