Introduction
Node.js is the most widely used JavaScript runtime for server-side development, powering everything from REST APIs and real-time applications to command-line tools and full-stack frameworks like Next.js and Express. By installing Node.js on your Raff VM, you get a production-ready JavaScript environment with npm — the world's largest software registry — for managing packages and dependencies.
There are three reliable ways to install Node.js on Ubuntu 24.04. The Ubuntu default repository provides the simplest installation but may ship an older version. The NodeSource repository lets you install a specific LTS or Current release with APT. And nvm (Node Version Manager) lets you install and switch between multiple Node.js versions per user — the preferred method for developers working on multiple projects.
In this tutorial, you will install Node.js using the NodeSource repository (the recommended approach for production servers), learn the nvm method as an alternative for development environments, verify the installation, and build a simple HTTP server to confirm everything works. On our Raff Tier 2 VM, installing Node.js via NodeSource takes under two minutes.
Step 1 — Install Node.js from the NodeSource Repository
The NodeSource repository provides up-to-date, officially maintained Node.js packages for Ubuntu. This method is recommended when you need a specific LTS version and want APT to handle updates alongside your other system packages.
First, update your package index and install the prerequisites for adding external repositories:
bashsudo apt update
sudo apt install -y ca-certificates curl gnupg
Download and import the NodeSource GPG key:
bashcurl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/nodesource.gpg
Add the NodeSource repository for Node.js 24 (the current LTS release). Replace 24 with 22 if you need the previous LTS:
bashNODE_MAJOR=24
echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
Update the package index to include NodeSource packages, then install Node.js:
bashsudo apt update
sudo apt install -y nodejs
This installs both the Node.js runtime and npm in a single package. Verify the installed versions:
bashnode --version
Expected output:
v24.14.1
bashnpm --version
Expected output:
v11.11.0
Note
The exact version numbers may differ depending on when you install. The important thing is that node returns a v24.x version and npm is available.
Step 2 — Alternative: Install Node.js with nvm
If you work on multiple projects that require different Node.js versions, nvm (Node Version Manager) is the better choice. It installs Node.js in your home directory and lets you switch versions with a single command — no sudo required.
Tip
Choose either the NodeSource method (Step 1) OR the nvm method (Step 2), not both. If you already completed Step 1, you can skip to Step 3. If you prefer nvm, remove the NodeSource installation first with sudo apt remove nodejs before proceeding.
Download and run the nvm installer:
bashcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
The script clones the nvm repository to ~/.nvm and adds initialization lines to your shell profile. Load nvm into your current session:
bashexport NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
Note
Running source ~/.bashrc should also work, but on some systems (especially when logged in as root), Ubuntu's default .bashrc exits early for non-interactive detection and never reaches the nvm lines. The export and source commands above load nvm directly and work in every case. Future terminal sessions will load nvm automatically from .bashrc.
Verify nvm is available:
bashnvm --version
You should see 0.40.1 or the version you installed.
Install the latest LTS version of Node.js:
bashnvm install --lts
nvm downloads, compiles if necessary, and activates the LTS version. Verify:
bashnode --version
npm --version
You can install additional versions and switch between them:
bashnvm install 22
nvm use 24
List all installed versions:
bashnvm ls
The arrow (->) indicates the currently active version. To set a default version that loads automatically in new terminal sessions:
bashnvm alias default 24
One important difference: nvm installs Node.js per user, not system-wide. If you need Node.js available to other users or system services (like systemd), the NodeSource method is more appropriate.
To uninstall a version you no longer need:
bashnvm uninstall 22
This removes the specified version from your system while leaving other installed versions untouched.
Step 3 — Install Build Tools for Native Modules
Some npm packages include native C/C++ addons that must be compiled during installation. The build-essential package provides the GCC compiler and make tool required for this compilation:
bashsudo apt install -y build-essential
Without these tools, you may encounter errors like gyp ERR! build error or node-gyp rebuild failed when installing packages such as bcrypt, sharp, or sqlite3. A common mistake is skipping this step and only discovering the issue when deploying an application — installing build-essential upfront avoids that surprise entirely.
Verify the compiler is available:
bashgcc --version
You should see GCC version 13.x or later on Ubuntu 24.04.
Step 4 — Verify the Installation with a Test Application
Create a simple HTTP server to confirm Node.js is working correctly. Create a project directory and a test file:
bashmkdir ~/hello-node
cd ~/hello-node
Create the server file:
bashnano server.js
Add the following code:
javascriptconst http = require('http');
const hostname = '0.0.0.0';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello from Node.js on Raff!\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Save and close the file. Run the server:
bashnode server.js
You should see:
Server running at http://0.0.0.0:3000/
Open a second terminal and test the server:
bashcurl http://localhost:3000
Expected output:
Hello from Node.js on Raff!
If UFW is enabled and you want to access the server from your browser, allow port 3000:
bashsudo ufw allow 3000/tcp
Then visit http://your_server_ip:3000 in your browser. You should see the "Hello from Node.js on Raff!" message.
Press Ctrl+C in the first terminal to stop the server. When you are done testing, remove the firewall rule:
bashsudo ufw delete allow 3000/tcp
Step 5 — Initialize a Project with npm
Most real-world Node.js applications use npm to manage dependencies. Initialize a new project in your test directory:
bashcd ~/hello-node
npm init -y
This creates a package.json file with default values. Install a popular package as a test — express, the most widely used Node.js web framework:
bashnpm install express
npm downloads Express and its dependencies into the node_modules directory and records the dependency in package.json.
Create a simple Express application to verify the installation:
bashnano app.js
Add the following code:
javascriptconst express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Express is running on Node.js!');
});
app.listen(port, '0.0.0.0', () => {
console.log(`Express app listening at http://0.0.0.0:${port}`);
});
Run the application:
bashnode app.js
Test it:
bashcurl http://localhost:3000
You should see Express is running on Node.js!. Press Ctrl+C to stop the server.
Step 6 — Configure npm Global Directory (NodeSource Only)
If you installed Node.js via NodeSource (Step 1), global npm packages require sudo by default because they install to /usr/lib/node_modules/. You can avoid this by configuring a user-level global directory:
bashmkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
Add the new directory to your PATH. Open your shell profile:
bashnano ~/.bashrc
Add this line at the end of the file:
bashexport PATH=~/.npm-global/bin:$PATH
Save and close the file. Load the new PATH into your current session:
bashexport PATH=~/.npm-global/bin:$PATH
Note
The export command applies the change immediately in your current terminal. The line in .bashrc ensures it persists in future sessions. Running source ~/.bashrc as an alternative may not work on all systems — the direct export is more reliable.
Now you can install global packages without sudo:
bashnpm install -g pm2
Note
If you installed Node.js with nvm, this step is unnecessary. nvm already installs everything in your home directory.
pm2 is a production process manager that keeps Node.js applications running, restarts them on crash, and manages logs. Verify the installation:
bashpm2 --version
Conclusion
You have installed Node.js and npm on your Raff Ubuntu 24.04 VM, configured build tools for native modules, verified the installation with a test HTTP server, and set up npm for global package management. Your server is ready for Node.js application development and deployment.
From here, you can:
- Install a process manager like pm2 to run Node.js applications as background services with automatic restarts
- Set up Nginx as a reverse proxy in front of your Node.js application for production traffic
- Deploy Docker containers to isolate Node.js applications from your system environment
- Build and deploy full-stack frameworks like Next.js, Express, or Fastify
- Explore our OpenClaw AI agent tutorial which uses Node.js 24 as its runtime
For production deployments, use a process manager like pm2 to keep your application running after you disconnect from SSH. A common pattern on Raff is to run Node.js behind Nginx as a reverse proxy — Nginx handles TLS termination and static files while Node.js processes dynamic requests.
Raff VMs use AMD EPYC processors with consistent single-thread performance, which directly benefits Node.js since it runs JavaScript on a single thread by default. On our Tier 2 VM, a basic Express application handles over 3,000 requests per second — plenty for most web applications and APIs.
This tutorial was tested by our systems engineering team on a Raff CPU-Optimized Tier 2 VM with Node.js 24 LTS.
