Run sudo dnf install nodejs on Fedora 45 and you get Node.js 22, a line that only receives critical and security fixes now. Node 24 and Node 26 sit in the same Fedora repository under their own package names, so the version you end up with depends on which name you type. The first decision is the release line, not the install method.
This guide shows you how to install Node.js and npm on Fedora from the official repositories and make one version the default while keeping the others. It also fixes the npm EACCES error and covers fnm and NodeSource for when the Fedora packages fall behind. Every command was run on Fedora 45 and smoke-tested on Fedora 44 in October 2026. Fedora 44 has no Node 26 packages and packages Node 22 slightly differently, and the sections below point out where that matters.
Choose a Node.js version for Fedora
Install Node 24 from the Fedora repositories unless something forces your hand. It keeps security support until April 2028, both Fedora 45 and Fedora 44 ship it, and it moves from Active LTS to maintenance on October 20, 2026, which changes nothing for a running app. Node 26 takes over as the Active LTS on October 28, 2026, and it is the line to start a new long-lived project on.
Get Node 26 from fnm or NodeSource rather than Fedora for now, because Fedora’s nodejs26 was thirteen releases behind upstream when we tested (26.3.1 against 26.12.0). Fedora’s nodejs24 also missed July’s security release, but it trails by five releases rather than thirteen, and it is the line both Fedora releases carry. Node 22 only makes sense for an app that is already pinned to it, because it reaches end of life in April 2027. Dates come from the Node.js release schedule, and the package versions are what the Fedora 45 repository held when we tested:
| Fedora package | Version on Fedora 45 | Upstream status | End of life |
|---|---|---|---|
nodejs22 (pulled in by nodejs) | 22.23.1 | Maintenance LTS since 2025-10-21 | 2027-04-30 |
nodejs24 | 24.18.0 | Active LTS, maintenance from 2026-10-20 | 2028-04-30 |
nodejs26 (Fedora 45 only) | 26.3.1 | Current, LTS from 2026-10-28 | 2029-04-30 |
The plain nodejs package is the trap. On Fedora 45 it’s a metapackage whose only job is to require nodejs22, and its summary calls it a “rolling stream”, so expect it to follow a newer line in a later Fedora release without asking you. You can see the dependency before installing anything:
dnf repoquery --requires nodejs
It resolves to the Node 22 package and nothing else, which is how a fresh install ends up on a maintenance-only line.
nodejs22 = 1:22.23.1-4.fc45
On Fedora 44 the same name is provided by nodejs22 directly instead of a separate metapackage, and the choice is between Node 20, 22 and 24. The install and switching commands below work on both releases, but the exact packages dnf removes during a switch differ. Old guides that tell you to run dnf module enable nodejs:22 are out of date. Fedora dropped modular repositories, and on Fedora 45 dnf module list nodejs answers “No matches found: no module streams exist.”
Install Node.js 24 with dnf
Each Node line on Fedora is split into several packages so that several lines can live side by side. These are the ones that matter, and only the two -bin packages touch the plain node command:
nodejs24andnodejs24-libs: the runtime as/usr/bin/node-24nodejs24-npm: npm asnpm-24andnpx-24nodejs24-bin: the/usr/bin/nodesymlinknodejs24-npm-bin: thenpmandnpxsymlinks
Name the two -bin packages when you want Node 24 to be the default, and dnf pulls in the rest as dependencies.
sudo dnf install nodejs24-bin nodejs24-npm-bin
By default dnf also pulls in two weak dependencies, the API docs (53 MiB installed) and nodejs24-full-i18n (32 MiB), the ICU data that formats dates and numbers in non-English locales. On a server you can skip both, which keeps the install to five packages and a 21 MiB download:
sudo dnf install --setopt=install_weak_deps=False nodejs24-bin nodejs24-npm-bin
Only five packages land, and the runtime library is the heavy one.
Installing:
nodejs24-bin noarch 1:24.18.0-4.fc45 fedora 154.0 KiB
nodejs24-npm-bin noarch 2:11.16.0-1.24.18.0.4.fc45 fedora 13.0 KiB
nodejs24 x86_64 1:24.18.0-4.fc45 fedora 313.3 KiB
nodejs24-libs x86_64 1:24.18.0-4.fc45 fedora 62.8 MiB
nodejs24-npm noarch 2:11.16.0-1.24.18.0.4.fc45 fedora 8.8 MiB
Installing: 5 packages
Total size of inbound packages is 21 MiB. Need to download 21 MiB.
Complete!
Keep the i18n package if your app renders anything for users outside English locales. We removed it on the test VM and asked Node 24 for a German month name: with the package it printed “Oktober”, without it “October”, and nothing logged a warning. That is the kind of bug you only notice in production. Confirm the runtime and npm versions.
node --version
npm --version
Node 24 ships with npm 11.
v24.18.0
11.16.0
Switch the default node between versions
Because the versioned packages do not fight over /usr/bin/node, you can keep Node 22 for an old service and Node 26 for testing on the same machine. Install the extra lines by their base package names, which skips the -bin symlinks and leaves your default alone:
sudo dnf install nodejs22 nodejs22-npm nodejs26 nodejs26-npm
Each line now answers to its own command (node-22, node-26, npm-26), which is handy in scripts and CI jobs that must not depend on whatever the default happens to be. Changing the default is different, because only one package may own the unversioned symlinks. If you started from the plain nodejs package, asking for another -bin package fails with a conflict:
Failed to resolve the transaction:
Problem 1: problem with installed package
- installed package nodejs-1:22.23.1-4.fc45.x86_64 conflicts with alternative-for(nodejs-bin) provided by nodejs24-bin-1:24.18.0-4.fc45.noarch from fedora
- package nodejs-1:22.23.1-4.fc45.x86_64 from fedora conflicts with alternative-for(nodejs-bin) provided by nodejs24-bin-1:24.18.0-4.fc45.noarch from fedora
- conflicting requests
Add --allowerasing so dnf can swap the symlink owners in one transaction. On Fedora 45 it removes only nodejs and nodejs-npm, the two tiny packages that held the symlinks, and leaves nodejs22 installed and working as node-22. Read the removal list before you confirm on Fedora 44, where the symlinks belong to Node 22’s own packages:
sudo dnf install --allowerasing nodejs24-bin nodejs24-npm-bin
The same command with nodejs26-bin nodejs26-npm-bin moves the default to Node 26, and naming the 24 packages again moves it back. The result with all three lines installed and Node 24 as the default looks like this:

Check ls -l /usr/bin/node whenever a tool reports a different Node version than you expect. The symlink target tells you which -bin package won, and it is the quickest way to tell a Fedora default apart from a version manager that has put its own node earlier in your PATH.
Fix npm EACCES errors on global installs
A Fedora-packaged npm installs global packages under /usr/local, which your user can’t write to, so the first npm install -g fails with a permission error:
npm error code EACCES
npm error syscall mkdir
npm error path /usr/local/lib/node_modules
npm error errno -13
npm error Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules'
Don’t answer it with sudo npm install -g. That runs every package’s install scripts as root and leaves root-owned files that the next non-root npm run trips over. Point npm’s global prefix at your home directory instead. Fedora’s default shell profile already puts ~/.local/bin on your PATH, so the tools work right away:
npm config set prefix ~/.local
npm install -g typescript
The setting lands in ~/.npmrc. Check that the TypeScript compiler is on your path without sudo:
command -v tsc
tsc --version
It resolves to your home directory:
/home/josphat/.local/bin/tsc
Version 7.0.2
If your project uses another package manager, the Fedora repositories carry the common ones as separate packages. Corepack is not bundled with Fedora’s Node packages, and upstream stopped bundling it with Node 25, so the corepack enable step in many READMEs fails on Fedora’s packages and on any Node 26 until you install it:
pnpm: version 10.33 on Fedora 45yarnpkg: Yarn classic, version 1.22nodejs-corepack: Corepack 0.36.0, for Yarn 4 and pinned pnpm
All three require /usr/bin/node, and pnpm and Yarn also set a minimum Node version, so they follow whichever line you made the default. On our Node 24 machine sudo dnf install pnpm added a single package, and nodejs-corepack resolved to a single package too. Corepack also asks for the generic nodejs capability, which nodejs22 provided there, so on a machine without Node 22 check what dnf wants to pull in before you confirm.
A project that pins Yarn 4 through its packageManager field needs Corepack either way. The official Node 24 build that fnm installs below still includes it. On an fnm or NodeSource Node 26, run npm install -g corepack instead, which put Corepack 0.36.0 in ~/.local/bin on our VM. It also adds pnpm, yarn and yarnpkg shims there, which take precedence over the Fedora packages above, so pick one route per machine and remove any globally installed pnpm or yarn first.
Manage per-project Node versions with fnm
The Fedora packages give you one default and a versioned command per line, which is fine on a server. On a laptop where one repo wants Node 22 and the next wants 24, a version manager that switches automatically on cd saves you from typing node-22 everywhere. We use fnm for that. It isn’t in the Fedora repositories, so it comes from its own install script, which needs unzip, downloads one binary into ~/.local/share/fnm and appends a block to ~/.bashrc:
sudo dnf install unzip
curl -fsSL https://fnm.vercel.app/install | bash
The block it writes loads fnm but doesn’t switch versions when you change directory, so a project’s version file would sit there unused. Add --use-on-cd so a version file takes effect as soon as you enter the project, and --version-file-strategy=recursive, which fnm’s own docs recommend, so leaving the project puts you back on your default. Then confirm the line changed and reload the shell:
sed -i "s|eval \"\$(fnm env --shell bash)\"|eval \"\$(fnm env --use-on-cd --version-file-strategy=recursive --shell bash)\"|" ~/.bashrc
grep "fnm env" ~/.bashrc
source ~/.bashrc
The grep should print the line with both flags. If it still shows the bare fnm env --shell bash, a newer installer wrote a different line, so edit ~/.bashrc by hand. Now install Node 24 and an older line, make 24 the default, then list what fnm manages. Name the line rather than using fnm install --lts, which follows whatever the current LTS is and switches to Node 26 on October 28, 2026.
fnm install 24
fnm install 22
fnm default 24
fnm list
fnm pulls official builds from nodejs.org rather than the Fedora packages. The system entry is the Fedora-packaged default it can fall back to, and default marks the line every new shell starts on:
* v22.23.3
* v24.22.0 default
* system
Look at the Node 24 number. fnm installed 24.22.0 while the Fedora repository still carried 24.18.0, five releases behind upstream on the day we tested. One of the five, 24.18.1 from July 28, 2026, was a security release. That lag is the strongest argument for a version manager on a developer machine that runs untrusted dependencies. Pin a project to a line by dropping a .node-version file in its root (fnm also reads .nvmrc):
mkdir -p ~/legacy-app
echo 22 > ~/legacy-app/.node-version
Check both directions in an interactive shell, because the way back is where the two strategies differ:
cd ~/legacy-app
node --version
cd ~
node --version
Entering the project switches to Node 22, and leaving it switches back to the default:
Using Node v22.23.3
v22.23.3
Using Node v24.22.0
v24.22.0
We first ran with --use-on-cd alone, and there cd ~ kept Node 22 until we entered another project or opened a new shell. That is the default local strategy, and it is how one project’s runtime ends up running commands in the next.
Each fnm version takes about 200 MB in your home directory (199 MB for 22 and 204 MB for 24 here), and fnm’s node shadows the Fedora one in every shell that loads ~/.bashrc. The ~/.npmrc prefix from the previous section applies to fnm’s npm as well, so global tools in ~/.local are shared by every Node line. Systemd services don’t load ~/.bashrc, which is why the service at the end of this guide calls a Fedora binary by its full path. If the same laptop also needs Python, Go and Rust, the polyglot Fedora dev environment sets those up next to Node.
Node 26 from fnm needs one library that Node 22 and 24 don’t. On our VM, after removing Fedora’s Node packages (which had pulled it in), fnm install 26 succeeded but every node call failed. A minimal Fedora 45 install doesn’t ship the library either, so expect the same on a fresh server or cloud image:
node: error while loading shared libraries: libatomic.so.1: cannot open shared object file: No such file or directory
Install it from the Fedora repositories, after which Node 26 started and reported v26.12.0:
sudo dnf install libatomic
NodeSource’s Node 26 RPM declares that library as a dependency, so dnf installs it for you on that path, and the error only shows up with fnm or another tarball-based manager.
Install the newest Node.js from NodeSource
NodeSource is the option when a server needs the newest point release through dnf, for example to close a security advisory before Fedora rebuilds its package. Its setup script writes a generic “nodistro” RPM repository, so it doesn’t wait for a Fedora-specific tree and worked on Fedora 45 as it stands. Treat it as an alternative to the Fedora packages, not an addition. On a machine that still has nodejs24-bin installed, the install fails at the RPM transaction:
Transaction failed: Rpm transaction failed.
- file /usr/bin/npm from install of nodejs-2:24.22.0-1nodesource.x86_64 conflicts with file from package nodejs24-npm-bin-2:11.16.0-1.24.18.0.4.fc45.noarch
- file /usr/bin/npx from install of nodejs-2:24.22.0-1nodesource.x86_64 conflicts with file from package nodejs24-npm-bin-2:11.16.0-1.24.18.0.4.fc45.noarch
- file /usr/bin/node from install of nodejs-2:24.22.0-1nodesource.x86_64 conflicts with file from package nodejs24-bin-1:24.18.0-4.fc45.noarch
- file /usr/share/man/man1/node.1.gz from install of nodejs-2:24.22.0-1nodesource.x86_64 conflicts with file from package nodejs24-bin-1:24.18.0-4.fc45.noarch
So remove the Fedora Node packages first. That takes every installed line with it, plus anything that depends on them, such as the pnpm package (19 packages and 542 MiB on our VM). Then download the setup script and run it as a separate step, so you can read what it does before it touches your repositories. For Node 26, fetch setup_26.x instead; we tested the 24 script:
sudo dnf remove "nodejs2*" nodejs nodejs-npm
curl -fsSL https://rpm.nodesource.com/setup_24.x -o /tmp/ns.sh
sudo bash /tmp/ns.sh
sudo dnf install nodejs
The NodeSource package is a single nodejs RPM (133.5 MiB installed) with npm bundled, and dnf asks you to trust the NodeSource signing key (fingerprint 242B813831AF09562B6C46F76B88DA4E3AF28A14) on the first install. Check node --version, npm --version and rpm -q nodejs, which reported the newer releases:
v24.22.0
11.19.1
nodejs-24.22.0-1nodesource.x86_64
Two details in /etc/yum.repos.d/nodesource-nodejs.repo decide how it behaves. The repository sets priority=9, and its packages carry epoch 2 against Fedora’s epoch 1, so dnf will always prefer NodeSource’s nodejs from now on, including during dnf upgrade. That is what you want on a box that follows NodeSource, and a surprise on one that doesn’t. There is no node-24 on such a machine either, so a systemd unit uses plain /usr/bin/node. To back out, remove the package and the repository files, then clear the cached metadata:
sudo dnf remove nodejs
sudo rm -f /etc/yum.repos.d/nodesource-nodejs.repo /etc/yum.repos.d/nodesource-nsolid.repo
sudo dnf clean all
Test Node.js with an Express app
A small Express app proves that npm can reach the registry and that the runtime handles ES modules, and it gives the firewall step something to point at. Any editor works for the one file it needs; if you want an IDE, VS Code on Fedora is the usual pick. Create the project and pull in Express:
mkdir -p ~/hello-api && cd ~/hello-api
npm init -y
npm pkg set type=module
npm install express
Then open the entry point in your editor. The vim command comes from the vim-enhanced package, so install that first if your machine only has vi, or use nano, which is Fedora’s default editor.
vim ~/hello-api/server.js
Add a single route that reports the Node version and process ID. That makes it obvious later which runtime a service is really using, which matters once systemd starts it for you:
import express from 'express';
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({ node: process.version, pid: process.pid });
});
app.listen(port, '0.0.0.0', () => {
console.log(`hello-api listening on port ${port}`);
});
Start it with node server.js and query it from a second terminal with curl -s localhost:3000. You should get JSON back with whichever node comes first in your PATH. A Fedora-only setup shows the packaged 24.18.0 below, while anyone who set up fnm or NodeSource sees their newer build:
{"node":"v24.18.0","pid":7474}
Whether other machines can reach port 3000 depends on the Fedora edition, because each one starts from a different firewall default:
- Workstation: zone
FedoraWorkstation, ports 1025-65535 already open - Server: zone
FedoraServer, only cockpit, ssh and dhcpv6-client - Cloud images: no firewalld installed at all
So a Workstation needs nothing, and a Server needs the port opened by hand. A cloud VM without firewalld isn’t filtering anything on the host, so the provider’s security group or cloud firewall is what decides whether port 3000 is reachable. If you want host filtering there too, install firewalld with sudo dnf install firewalld and add ports before you start it, with sudo firewall-offline-cmd --add-port=3000/tcp. Its default public zone allows SSH only on port 22, so add your SSH port the same way if you moved it, or sudo systemctl enable --now firewalld locks you out. On our cloud VM the offline rule was active as soon as firewalld started. On a Server, where firewalld already runs, add the app port permanently and reload. The firewalld guide for Fedora covers zones and rich rules if you need to limit who can connect:
sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports
The last command should list 3000/tcp. For anything public, put Nginx or another reverse proxy in front with TLS rather than exposing the Node port directly.
Run the Node.js app as a systemd service
A node server.js in a terminal dies with your SSH session, so a real deployment runs under systemd with its own unprivileged user. Create a system account with no login shell, then copy the project to /opt and hand it over:
sudo useradd --system --home-dir /opt/hello-api --shell /sbin/nologin nodeapp
sudo cp -r ~/hello-api /opt/
sudo chown -R nodeapp:nodeapp /opt/hello-api
Create the unit file. The editor opens an empty buffer because nothing on Fedora ships a unit by this name.
sudo vim /etc/systemd/system/hello-api.service
The one line worth thinking about is ExecStart. It calls /usr/bin/node-24 rather than /usr/bin/node, so the service keeps its runtime when someone moves the system default to another line. On a NodeSource machine there is no node-24, so use /usr/bin/node there:
[Unit]
Description=hello-api Node.js service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=nodeapp
WorkingDirectory=/opt/hello-api
Environment=NODE_ENV=production
Environment=PORT=3000
ExecStart=/usr/bin/node-24 server.js
Restart=on-failure
[Install]
WantedBy=multi-user.target
Load the unit, start it and enable it at boot. Run the status check right after, because a typo in the unit only shows up there.
sudo systemctl daemon-reload
sudo systemctl enable --now hello-api
systemctl status hello-api --no-pager
A healthy service shows active (running), about 22 MB of memory for this app, and the same JSON over curl:

We checked the pin the hard way. With the service running on node-24, we moved the system default to Node 26 with --allowerasing and restarted the unit, and the app still answered "node":"v24.18.0". Had the unit called /usr/bin/node, that restart would have quietly put production on a different major version. SELinux stayed enforcing throughout and ausearch -m avc -ts recent returned no denials, because the unit runs a packaged binary against files under /opt. If your app is a container rather than a plain process, Podman Quadlet gives you the same systemd lifecycle, and the rest of a fresh workstation setup is in our Fedora 45 post-install checklist.
Sadly, these instructions no longer work on Centos7
## Your distribution, identified as “centos-release-7-9.2009.1.el7.centos.x86_64”, is not currently supported, please contact NodeSource at https://github.com/nodesource/distributions/issues if you think this is incorrect or would like your distribution to be considered for support
Ok I was able to get it working on centos7 but had to remove the previously installed stuff and modify the steps and drop the sudo.
yum remove -y nodejs npm
curl -sL https://rpm.nodesource.com/setup_12.x | bash –
yum install -y nodejs