Install Node.js on Amazon Linux 2023: Node 24 or 22 with dnf, Switching Versions with alternatives, nvm and the sudo Trap, npm EACCES, systemd, pm2 and Port 80

Logeshwaran
—

To install Node.js on Amazon Linux 2023, name the version you want: sudo dnf install -y nodejs24 nodejs24-npm for Node.js 24, the current long-term support release (supported until April 30, 2028), or nodejs22 nodejs22-npm for Node.js 22 (until April 30, 2027). Amazon Linux 2023 packages Node.js 20, 22 and 24 side by side as separate, versioned packages, and the plain node and npm commands point at whichever one is active, which you switch with sudo alternatives --config node. Skip Node.js 20: it reached end of life on April 30, 2026. If you need a version Amazon Linux does not package, such as Node.js 26, or a different version per user, use nvm instead, and keep it away from sudo, which cannot see it. Below: every option with exact commands, switching versions, global npm packages without permission errors, running your app as a service with systemd or pm2, serving it on port 80, installing at launch with user data, and the errors people hit most.

Jake's new Express app ran perfectly on his laptop. On the EC2 instance, he followed a tutorial step by step: install nvm, run nvm install --lts, check node -v. Version 24. Then, because the app had to answer on port 80, he typed sudo node server.js. "sudo: node: command not found." He ran node -v again. Still version 24. "It exists," Jake told Ethan, "and it doesn't exist. Which one is it?" Ethan smiled. "Both. It exists for you. sudo is somebody else."

⚡ Quick Answer

• Most servers: sudo dnf install -y nodejs24 nodejs24-npm, then node -v. Install.

• Several versions: install each, switch with sudo alternatives --config node, or call node-22 directly. Switch.

• Node 26 or per-user versions: nvm, without sudo. nvm.

• Keep it running: a systemd service, with nginx in front for port 80. Service.

Also: which versions exist · global npm packages · install at launch · errors by symptom.

New to Amazon Linux 2023? Our guide to AL2023 versions and updates explains how its dnf releases work, and if you cannot reach the instance at all, start with the SSH permission denied fix. Still on Amazon Linux 2? Modern Node.js does not run there; see the GLIBC_2.28 guide first.

🧭 NEW HERE? READ THESE FIRST

New to Amazon Linux 2023, EC2 security groups or user data? These five pages cover the basics this one builds on:

📌 Bookmark this; the install line and the systemd unit are the parts you will copy again.

Which Node.js versions Amazon Linux 2023 has

Amazon Linux 2023 does not have one "nodejs" that changes over time. It packages each major version separately, with the version number in the package name, so several can sit on the same server without overwriting each other. Amazon Linux follows the upstream Node.js support schedule, which makes the choice simple:

VersionPackagesStatus in October 2026End of life
Node.js 24nodejs24, nodejs24-npmLong-term support; the best choice for new serversApril 30, 2028
Node.js 22nodejs22, nodejs22-npmMaintenance long-term support; fine for existing appsApril 30, 2027
Node.js 20nodejs20, nodejs20-npmEnd of life; move off itApril 30, 2026
Node.js 26not packaged; use nvmCurrent release, long-term support from October 28, 2026April 30, 2029
Node.js 18 and oldergoneEnd of life since April 30, 2025passed

Amazon Linux 2023 itself is supported until June 30, 2029, so on this operating system you will change Node.js versions at least twice. That is the main reason the versioned packages matter: moving from 22 to 24 is an install and a switch, not a removal and a rebuild.

What about plain sudo dnf install nodejs, the command most older tutorials show? At launch, Amazon Linux 2023 shipped Node.js 18 under that name, and 18 is now end of life. Rather than guess what the unversioned name resolves to on your release, ask for a version by name. Your future self, reading the server's setup script, will know exactly what it installs.

Install Node.js 24 (or 22) with dnf

This is the right method for most servers: packages from the Amazon Linux repository, updated with the rest of the system by dnf upgrade, and covered by Amazon Linux security updates.

  1. Connect to the instance as ec2-user, over SSH or Session Manager.
  2. Install Node.js and npm. The npm tool comes in its own package, so ask for both:
    sudo dnf install -y nodejs24 nodejs24-npm
  3. Check both commands.
    node -v        # v24.x.x
    npm -v
    which node     # /usr/bin/node, a link managed by alternatives
  4. Install your app's dependencies from its folder with npm ci (when a package-lock.json exists) or npm install.

For Node.js 22, change the numbers: sudo dnf install -y nodejs22 nodejs22-npm. The first version you install becomes the active node automatically. Every version also installs a fixed-name command, node-24 or node-22, and a matching npm-24 or npm-22, which always run that exact version whatever is active.

Building packages with native code, such as bcrypt or some image libraries, needs a compiler too. If npm install fails with "gyp ERR!" or "make: not found", add the build tools and try again:

sudo dnf install -y gcc-c++ make python3

Ethan's advice to Jake, after the sudo surprise, was this section and nothing else: "Install it the way the operating system expects, and sudo will find it, systemd will find it, and the next person will find it."

Run several versions and switch between them

Because each version has its own package, you can install 22 and 24 together, which is the safe way to upgrade: install the new one, test your app with it, then switch. The plain node and npm commands are managed by the alternatives tool, which points them at one installed version at a time.

sudo dnf install -y nodejs22 nodejs22-npm nodejs24 nodejs24-npm
alternatives --display node              # which version is active, and how it was chosen
sudo alternatives --config node          # pick from a numbered list
sudo alternatives --set node /usr/bin/node-24   # or set it directly, no menu
sudo alternatives --auto node            # hand the choice back to automatic mode
node-22 server.js                        # run one app on 22 regardless of the active version

A few details trip people up:

  • Installed versions have equal priority. In automatic mode the first one installed stays active, so installing 24 on a server that already has 22 does not switch node to 24. Switch it yourself.
  • The plain name can change under you. If a script or service must always use one version, call node-24 in it rather than node. Then a later switch on the server cannot surprise that app.
  • npm follows node only through the plain name. npm-22 always belongs to Node.js 22, which is useful for installing an app's dependencies with the same version that will run it.
  • Remove old versions when you are done. sudo dnf remove -y nodejs20 nodejs20-npm takes away an end-of-life version once nothing calls it.

When to use nvm instead, and the sudo trap

nvm (Node Version Manager) installs Node.js into your home folder instead of the system. Use it when you need a version Amazon Linux does not package, such as Node.js 26, an exact patch release to match production elsewhere, or a different version per user on a shared development box.

# check the nvm README for the newest install line; v0.40.3 shown
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
source ~/.bashrc
nvm install 24            # or: nvm install 26, nvm install --lts
nvm alias default 24
node -v

The catch is the one Jake met. nvm adds Node.js to your shell's PATH, in ~/.nvm. When you run sudo node, sudo starts the command with its own short, fixed PATH, which does not include your home folder, so it reports "command not found." The same happens to anything that is not your interactive shell: systemd services, cron jobs, and EC2 user data, which runs as root and would install nvm into /root/.nvm where ec2-user won't look.

Three ways out, best first:

  1. Run the app without sudo. Run it as ec2-user on a high port such as 3000 and put nginx in front for port 80 (see below).
  2. Use the dnf packages for servers and keep nvm for development machines.
  3. If you truly must, give the full path: sudo "$(which node)" server.js. It works, but every reboot script and service file now depends on a path inside one user's home folder.

One more thing to watch: if you install the dnf packages and nvm, you get two different answers to which node runs. For your own shell, nvm wins because it puts its folder first on PATH; for sudo, systemd and everyone else, the dnf version wins. Two answers to "which node?" is how afternoons disappear.

Global npm packages without "EACCES: permission denied"

With the dnf packages, global packages go into /usr/lib/node_modules, which belongs to root. So npm install -g pm2 as ec2-user fails with "EACCES: permission denied". You have three reasonable choices:

ChoiceCommandGood for
Install system-wide with sudosudo npm install -g pm2Tools every user and service needs, on a server you control
A personal global foldernpm config set prefix ~/.npm-global, then add ~/.npm-global/bin to PATH in ~/.bashrcDeveloper tools for one user, no sudo
No global install at alladd the tool to devDependencies and run it with npxBuild tools whose version should match the project

You will see tutorials that fix EACCES with sudo chown -R on /usr/lib or sudo chmod 777. Skip them: those "fixes" turn a permissions message into a security hole. Also remember that global packages belong to one Node.js version: after switching from 22 to 24, reinstall the global tools you use.

Need yarn or pnpm? Install them like any other global tool, for example sudo npm install -g pnpm, or follow your project's own instructions if it pins a package manager version.

Keep the app running: systemd, pm2 and port 80

An app started from an SSH session stops when the session ends or the server reboots. On Amazon Linux 2023 the built-in answer is a systemd service. Create /etc/systemd/system/myapp.service:

[Unit]
Description=My Node.js app
After=network-online.target
Wants=network-online.target

[Service]
User=ec2-user
WorkingDirectory=/home/ec2-user/myapp
Environment=NODE_ENV=production PORT=3000
ExecStart=/usr/bin/node-24 server.js
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f        # the app's console output

Note /usr/bin/node-24 rather than node: the service keeps running on Node.js 24 even if someone switches the server's default later. If you prefer pm2, it does the same job with extras such as clustering and log rotation: sudo npm install -g pm2, pm2 start server.js --name myapp, then pm2 startup systemd, which prints one sudo command to copy and run, and finally pm2 save so the app comes back after a reboot.

Port 80 and 443. On Linux, only root can listen on ports below 1024, which is exactly why Jake reached for sudo. The clean setup keeps the app on port 3000 as ec2-user and puts nginx in front:

sudo dnf install -y nginx
# in /etc/nginx/conf.d/myapp.conf
server {
    listen 80;
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
sudo systemctl enable --now nginx

nginx also handles HTTPS certificates and static files better than most apps do. If the instance sits behind an Application Load Balancer, you can skip nginx entirely: the load balancer listens on 80 and 443 and forwards to port 3000 on the instance.

Finally, the instance's security group must allow inbound traffic on the port clients use, 80 or 443 for nginx, or 3000 while testing. A missing rule looks exactly like a crashed app from the outside. Our security groups guide shows the rule to add.

Jake's final setup took ten minutes: nodejs24 from dnf, the service file above, nginx on port 80. He rebooted the instance on purpose, just to watch the app come back by itself. It did.

Small instances: npm install killed, memory and swap

On a t4g.micro or t3.micro with 1 GB of memory, npm install for a medium-sized project can simply stop with "Killed" and no other explanation. That is the Linux out-of-memory killer ending the process, and it is one of the most common reasons people think Node.js "won't install" on a small EC2 instance. You have three fixes, cheapest first:

  1. Add a swap file, so the install can borrow disk when memory runs out:
    sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
    free -h
  2. Build somewhere else. Run npm ci and any build step in CI or on your laptop for the same architecture, and copy the finished folder, or a container image, to the server.
  3. Use a bigger instance for the build, or permanently if the app itself needs the memory.

The app itself can hit the same wall. Node.js sets a default limit for its JavaScript heap based on the memory it sees, and a busy app can end with "JavaScript heap out of memory." You can raise the limit with NODE_OPTIONS=--max-old-space-size=768 (in megabytes) in the service's environment, but keep it comfortably below the instance's real memory, or the operating system will kill the process instead. If you find yourself raising it repeatedly, look for a memory leak before you buy a larger instance.

Graviton (arm64) instances such as the t4g family run Node.js well and usually cost less for the same work. The only catch is native modules: packages with compiled parts need arm64 builds, which npm downloads or compiles automatically on the server, but which you must build for arm64 if you prepare them elsewhere.

Environment variables, secrets and AWS credentials

Your app needs settings: a port, a database URL, an API key. Hard-coding them in the code or committing a .env file to Git is how secrets leak. On Amazon Linux 2023 you have better options that cost little or nothing:

  • Plain settings go in the systemd unit with Environment=, or in a separate file referenced with EnvironmentFile=/etc/myapp.env, owned by root and readable only by root (chmod 600). systemd reads it as root and passes the values to your app.
  • Secrets such as database passwords belong in AWS Secrets Manager or Systems Manager Parameter Store. Your app reads them at startup with the AWS SDK for JavaScript (v3), for example @aws-sdk/client-secrets-manager.
  • AWS credentials should never be in a file on the server at all. Attach an IAM role to the instance (an instance profile), and the SDK finds temporary credentials automatically through the instance metadata service. No access keys to rotate, and nothing to steal from disk.
// read a secret at startup with the AWS SDK v3 (credentials come from the instance role)
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
const sm = new SecretsManagerClient({ region: "us-east-1" });
const { SecretString } = await sm.send(new GetSecretValueCommand({ SecretId: "prod/myapp/db" }));
const db = JSON.parse(SecretString);

If the SDK says it cannot find credentials, the instance has no role attached, or the role lacks permission for that secret. Check with aws sts get-caller-identity on the instance: if it answers with a role ARN, the SDK will find the same credentials.

Logs: journald, rotation and CloudWatch

With a systemd service, everything your app writes to the console goes into the system journal. You read it with journalctl -u myapp, add -f to follow it live, and --since "1 hour ago" to narrow it down. The journal rotates itself, so a chatty app will not fill the disk the way a hand-made log file can.

Logs on one server disappear when the instance is replaced, though, and you cannot search across several servers. For anything in production, send them to Amazon CloudWatch Logs with the CloudWatch agent, which is packaged for Amazon Linux 2023:

sudo dnf install -y amazon-cloudwatch-agent
# then configure it (the wizard or a JSON config) to collect your log files or the journal,
# and give the instance role the CloudWatchAgentServerPolicy managed policy

If you use pm2 instead of systemd, its logs live under ~/.pm2/logs; install the pm2-logrotate module so they rotate, and point the CloudWatch agent at those files. Whichever you choose, write logs as one JSON object per line from the app, with a level and a request ID, and searching them later in CloudWatch Logs Insights becomes a query instead of an archaeology project.

Deploying updates without downtime

A deployment on a single server usually looks like this: pull the new code, run npm ci --omit=dev, and restart the service. With systemd, the restart drops connections for a second or two while the app starts. That is fine for an internal tool and not fine for a checkout page.

  • pm2 reload in cluster mode restarts the app's worker processes one at a time, so some workers are always answering. It is the simplest zero-downtime option on one server.
  • Two or more instances behind an Application Load Balancer are the standard answer in production. You update one instance at a time; the load balancer stops sending it traffic while it restarts, using its health check. This also protects you from a single instance failing.
  • AWS CodeDeploy automates that rolling update across an Auto Scaling group, with scripts for stop, install and start, and automatic rollback if health checks fail.
  • Containers on ECS take this further: the new version starts as new tasks, and the old ones stop only when the new ones are healthy.

Whatever you choose, keep the previous release folder on disk until the new one has run cleanly for a while. A rollback that means switching a symlink and restarting is a rollback you will actually do at 2 a.m.

Keeping Node.js and the server patched

Because you installed Node.js from the Amazon Linux repository, its security updates arrive with the rest of the system. Amazon Linux 2023 pins each server to a repository version, so updates arrive in two ways:

  • sudo dnf upgrade applies updates within the release the server is locked to.
  • sudo dnf check-release-update tells you a newer release exists, and sudo dnf upgrade --releasever=latest moves to it, which is where most new package versions, including Node.js patch releases, appear.

Our AL2023 versions and updates guide explains that model in detail. After a Node.js update, restart your service so it picks up the new binary; a running process keeps the old version in memory until it restarts.

Your own dependencies need patching too. Run npm audit regularly, update packages in your project, and redeploy. Amazon Inspector can scan EC2 instances and container images for known vulnerabilities in both operating system packages and npm dependencies, which helps when you manage more than a couple of servers.

One more Amazon Linux 2023 detail: SELinux is present but in permissive mode by default. If your security team switches it to enforcing, nginx is no longer allowed to open connections to your app on port 3000 until you run sudo setsebool -P httpd_can_network_connect 1. Remember that line if a perfectly good nginx setup suddenly returns "502 Bad Gateway" after a hardening change.

Still on Amazon Linux 2?

Many searches for "install Node.js on Amazon Linux" come from servers still running Amazon Linux 2. That operating system reached end of support on June 30, 2026, and it has a deeper problem for Node.js: its system C library is glibc 2.26, while the official Node.js builds from version 18 onward need glibc 2.28 or newer. That is the source of the "GLIBC_2.28 not found" error when you try nvm or a downloaded binary there.

There are workarounds, such as unofficial builds compiled against the older library, or running Node.js in a container on the old host, but they are stopgaps. The lasting fix is to move the app to an Amazon Linux 2023 instance and install Node.js with the steps on this page. Our GLIBC_2.28 guide walks through the options and the migration. Check which one you are on first:

cat /etc/os-release | grep PRETTY_NAME
# Amazon Linux 2023.x...  -> this page applies
# Amazon Linux 2          -> migrate first

Install Node.js at launch with user data

To have new instances arrive ready, put the install in the launch template's user data. User data runs once, as root, at first boot, so use the dnf packages here, not nvm:

#!/bin/bash
set -euxo pipefail
dnf install -y nodejs24 nodejs24-npm git
node -v
# then fetch your app and start its service, for example:
# git clone https://example.com/myapp.git /home/ec2-user/myapp
# chown -R ec2-user:ec2-user /home/ec2-user/myapp
# cd /home/ec2-user/myapp && sudo -u ec2-user npm-24 ci --omit=dev
# systemctl enable --now myapp

If Node.js is missing after launch, read /var/log/cloud-init-output.log; the set -e line stops the script at the first failing command, so the last lines show what broke. Our user data guide covers the other reasons a script never runs. For fleets, a better long-term habit is to bake Node.js and your app into an AMI or a container image, so a new instance starts in seconds instead of installing at boot.

Two details make boot-time installs dependable. First, run the app's npm ci as ec2-user, as in the commented lines, so its files are not owned by root. Second, put the version in a variable at the top of the script, for example NODE_MAJOR=24, and use nodejs${NODE_MAJOR} in the install line and node-${NODE_MAJOR} in the service file. The next upgrade then becomes a one-character change to the launch template.

In Docker and on Lambda

Docker. If your container is based on the Amazon Linux 2023 image, the same packages work inside it:

FROM public.ecr.aws/amazonlinux/amazonlinux:2023
RUN dnf install -y nodejs24 nodejs24-npm && dnf clean all
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "server.js"]

Many teams use the official Node.js images instead, which are smaller to start from and come in exact versions; both are fine. What matters is that the image, not the host, decides the Node.js version, so the host only needs Docker. Our Docker on Amazon Linux 2023 guide covers that part.

Lambda. Lambda needs no Node.js install from you: you choose a managed Node.js runtime in the function settings, and AWS keeps it patched. What you package is your code and its node_modules. If a function cannot find a package you put in a layer, the folder layout is usually the cause; see our Lambda layer "Cannot find module" guide.

Upgrading from Node.js 20 or 22 to 24

With versioned packages, an upgrade is low-risk because the old version stays installed until you remove it:

  1. Install 24 next to the current version: sudo dnf install -y nodejs24 nodejs24-npm.
  2. Test with the fixed-name command: from the app folder, npm-24 ci then node-24 server.js, and run your tests the same way. Native modules must be rebuilt for the new version, which npm ci does.
  3. Switch the service: change ExecStart to /usr/bin/node-24, then sudo systemctl daemon-reload and sudo systemctl restart myapp.
  4. Switch the default for interactive use: sudo alternatives --set node /usr/bin/node-24.
  5. Remove the old version after a quiet week: sudo dnf remove -y nodejs20 nodejs20-npm.

Rolling back is step 3 in reverse, which is the whole point of keeping both for a while.

Troubleshooting by symptom

SymptomCauseFix
sudo: node: command not foundNode.js installed with nvm; sudo uses its own PATHRun without sudo behind nginx, or use the dnf packages
npm: command not found, node worksOnly nodejs24 installed, not nodejs24-npmsudo dnf install -y nodejs24-npm
node -v shows 22 after installing 24First installed version stays activesudo alternatives --set node /usr/bin/node-24
EACCES: permission denied on npm install -gGlobal folder belongs to rootsudo for system tools, or a personal prefix
Error: listen EACCES: permission denied 0.0.0.0:80Ports below 1024 need rootApp on 3000, nginx or a load balancer on 80
gyp ERR! or make: not foundNo compiler for native modulessudo dnf install -y gcc-c++ make python3
App works on the instance, browser times outSecurity group closed, or app listening on 127.0.0.1 onlyOpen the port; listen on 0.0.0.0 or use nginx
App dies when you log outStarted from the SSH sessionsystemd service or pm2 with startup
Service fails: node: No such file or directoryExecStart points at an nvm path or wrong binaryUse /usr/bin/node-24
GLIBC_2.28 not foundYou are on Amazon Linux 2, not 2023Check cat /etc/os-release; move to AL2023

When in doubt, three commands answer most questions: which -a node lists every node on your PATH, alternatives --display node shows which dnf version is active, and cat /etc/os-release confirms you are on Amazon Linux 2023 at all.

"It runs, but I can't reach it": check each layer in order

The most common message after a successful install is that the app runs but the browser cannot load it. Work from the inside out, and you will find the broken layer in a few minutes:

  1. Is the process running? systemctl status myapp should say active (running). If not, journalctl -u myapp -n 50 shows why it stopped.
  2. Is it listening, and on which address? sudo ss -tlnp | grep node shows the port. If it says 127.0.0.1:3000, only the server itself can reach it, which is right behind nginx and wrong without it. 0.0.0.0:3000 or *:3000 means it accepts outside connections.
  3. Does it answer locally? curl -i http://127.0.0.1:3000/ on the server. An answer here means Node.js is fine and the problem is outside it.
  4. Does nginx answer? curl -i http://127.0.0.1/. A "502 Bad Gateway" means nginx cannot reach the app: wrong port in proxy_pass, app stopped, or SELinux enforcing as described above.
  5. Is the security group open? Inbound rule for port 80 or 443 (or 3000 while testing) from your IP or from anywhere for a public site.
  6. Is the instance reachable at all? It needs a public IP or an Elastic IP in a public subnet with a route to an internet gateway, or a load balancer in front. Network ACLs, if your team uses them, must allow the traffic both ways.

Add a tiny health route to every app, such as /health returning "ok", and you have a test for steps 3 and 4 that no other code can break, and the path a load balancer health check will use later. Jake's own "can't reach it" moment ended at step 2: his app was listening on 127.0.0.1 because of a host setting copied from a tutorial.

Other ways to run Node.js on AWS

Installing Node.js on an EC2 instance gives you the most control, and it is the right way to learn. It also makes you responsible for patching, scaling and restarting. Depending on your app, one of these may save you work:

OptionYou manageGood for
EC2 with Amazon Linux 2023 (this page)OS, Node.js, process, scalingLearning, full control, steady long-running apps
Elastic Beanstalk, Node.js platformYour code and settingsWeb apps where you want EC2 underneath but not the setup work
ECS on Fargate with a containerThe image and task settingsTeams already using containers, multiple services
AWS Lambda, Node.js runtimeYour function codeAPIs and jobs with uneven traffic; pay per request

Elastic Beanstalk's Node.js platform runs on Amazon Linux 2023 and does most of this page for you: it installs Node.js, runs your app behind nginx, and handles deployments and scaling. Lambda removes servers entirely, but changes how you write the app, because each request runs as a function call with a time limit. Many teams start on EC2, as Jake did, and move once they know what their traffic looks like. Nothing on this page is wasted if you move later: the habits of pinning the version, running as a service, and keeping secrets out of the code carry over to every option in the table.

For IT admins: Node.js across a fleet

  • Standardize on the dnf packages for servers so Node.js is patched with every dnf upgrade and visible to inventory tools.
  • Pin services to fixed-name binaries (node-24) so a default switch on a shared host leaves running apps where they are.
  • Track end-of-life dates: Node.js 22 ends April 30, 2027 and 24 ends April 30, 2028. Put the next upgrade in the calendar now.
  • Find stragglers with Systems Manager Inventory or a Run Command that lists installed nodejs packages, and flag any nodejs20.
  • Prefer images to boot-time installs: AMIs or containers with Node.js baked in start faster and behave the same every time.

A fleet where every server answers "which node?" the same way is a fleet you can upgrade in an afternoon.

Node.js on Amazon Linux 2023: frequently asked questions

How do I install Node.js on Amazon Linux 2023?

Run sudo dnf install -y nodejs24 nodejs24-npm, then check with node -v. Use nodejs22 and nodejs22-npm for Node.js 22.

Which Node.js versions does Amazon Linux 2023 support?

It packages Node.js 20, 22 and 24 as separate versioned packages. Node.js 20 reached end of life on April 30, 2026, so use 22 or 24.

How do I install Node 22 on Amazon Linux 2023?

sudo dnf install -y nodejs22 nodejs22-npm. If another version is already active, switch with sudo alternatives --set node /usr/bin/node-22.

Why is npm not found after installing Node.js?

npm is a separate package. Install nodejs24-npm (or the one matching your version).

How do I switch Node.js versions on Amazon Linux 2023?

Use sudo alternatives --config node to pick from a list, or call a fixed-name command such as node-22 or node-24 directly.

Should I use nvm or dnf on Amazon Linux 2023?

Use dnf for servers, because sudo, systemd and every user can see it and it is patched with the system. Use nvm for versions Amazon Linux does not package or for per-user development setups.

Why does sudo node say command not found?

Node.js was installed with nvm into your home folder, and sudo uses its own PATH that does not include it. Run the app without sudo, or install with dnf.

Can I install Node.js 26 on Amazon Linux 2023?

Not from the Amazon Linux repository. Use nvm with nvm install 26, or a container image with Node.js 26.

How do I run a Node.js app on port 80 on EC2?

Run the app on port 3000 as ec2-user and put nginx or an Application Load Balancer in front on port 80. Ports below 1024 need root.

How do I keep a Node.js app running after I log out?

Create a systemd service, or use pm2 with pm2 startup systemd and pm2 save.

How do I fix EACCES when installing npm packages globally?

Use sudo for system-wide tools, set a personal prefix with npm config set prefix ~/.npm-global, or run tools with npx. Leave the permissions on system folders as they are.

What did dnf install nodejs install on Amazon Linux 2023?

At launch it installed Node.js 18, which is now end of life. Name the version instead, such as nodejs24.

Does Node.js work on Graviton (arm64) instances?

Yes. The same packages and commands work on arm64 Amazon Linux 2023 instances.

How do I install Node.js with EC2 user data?

Add dnf install -y nodejs24 nodejs24-npm to a bash user data script. Use dnf rather than nvm there, because user data runs as root.

How do I uninstall a Node.js version?

sudo dnf remove -y nodejs20 nodejs20-npm, changing the number to the version you want gone.

Why does Node.js fail with GLIBC_2.28 not found?

That happens on Amazon Linux 2, whose glibc is too old for Node.js 18 and later. Amazon Linux 2023 does not have this problem.

How do I install yarn or pnpm on Amazon Linux 2023?

After installing Node.js and npm, run sudo npm install -g pnpm or the same for yarn, or follow your project's pinned package manager setup.

Why does npm install say Killed on EC2?

The instance ran out of memory and Linux stopped the process. Add a swap file, build elsewhere, or use an instance with more memory.

How do I fix JavaScript heap out of memory?

Set NODE_OPTIONS=--max-old-space-size with a value below the instance's memory, and look for leaks if it keeps happening.

How should a Node.js app on EC2 get AWS credentials?

Attach an IAM role to the instance. The AWS SDK for JavaScript finds its temporary credentials automatically, with no access keys on disk.

How do I send Node.js logs to CloudWatch?

Install the CloudWatch agent with dnf, configure it to collect your logs or the journal, and give the instance role the CloudWatchAgentServerPolicy policy.

How do I update Node.js on Amazon Linux 2023?

Run sudo dnf upgrade, or sudo dnf upgrade --releasever=latest to move to the newest release, then restart your service so it uses the new binary.

How long is Node.js 24 supported?

Until April 30, 2028. Node.js 22 is supported until April 30, 2027.

For readers preparing for an AWS certification

We have been covering AWS certifications alongside our fixes, so here is a short extra for readers studying for one. If you only came for the fix, you already have it; feel free to skip this part.

Exams that test this topic: Developer – Associate (DVA-C03 from December 1, 2026) • CloudOps Engineer – Associate (SOA-C03) • Solutions Architect – Associate (SAA-C03).

Here are the exam-style questions this topic tends to raise, with the reasoning you need to answer them:

1. New EC2 instances must have Node.js and the application installed automatically at first boot. What is the simplest option?

A bash script in the launch template's user data, which runs once as root at first boot.

2. A user data script did not install a package. Where do you look first?

The cloud-init output log on the instance, /var/log/cloud-init-output.log.

3. An Auto Scaling group takes too long to launch instances because user data installs software at boot. What reduces launch time?

Bake the software into a custom AMI (for example with EC2 Image Builder) or a container image.

4. A web app on EC2 is running but browsers time out. The app listens on port 3000. What is the most likely cause?

The instance's security group does not allow inbound traffic on that port.

5. A Node.js application must run on EC2 behind HTTPS without the app handling certificates. Which design fits?

An Application Load Balancer with an ACM certificate on an HTTPS listener, forwarding to the instances.

6. Which service lets you run a command such as a package inventory across hundreds of instances without SSH?

AWS Systems Manager Run Command (and Systems Manager Inventory for installed software).

7. How do you run Node.js code on Lambda without installing Node.js?

Choose a managed Node.js runtime for the function; AWS patches the runtime, and you package only your code and dependencies.

Exam codes and dates change often. Our AWS certification changes page keeps track of what is current.

πŸ“š ALSO READ

The rest of the Amazon Linux 2023 install series, and the problems you meet next:

📌 Bookmark this; the install line and the systemd unit are the parts you will copy again.

Jake still keeps nvm on his laptop. On servers he types one line he no longer has to look up, and when someone asks him which Node.js a server runs, he answers with the package name instead of a shrug.

📌 If you keep one line from this page

sudo dnf install -y nodejs24 nodejs24-npm on Amazon Linux 2023, switch versions with alternatives, pin services to /usr/bin/node-24, and keep nvm and sudo apart.

Node 24 to April 2028 · Node 22 to April 2027 · Node 20 is finished · app on 3000, nginx on 80.

Revision note. Written October 18, 2026, two days before Node.js 24 moves to maintenance and ten days before Node.js 26 becomes the new long-term support release. "Measure twice, cut once," carpenters say; on servers, name the version once and you never have to guess it again.

Related