{"id":164322,"date":"2026-03-24T21:02:39","date_gmt":"2026-03-24T18:02:39","guid":{"rendered":"https:\/\/computingforgeeks.com\/nodejs-24-ubuntu\/"},"modified":"2026-03-25T02:55:41","modified_gmt":"2026-03-24T23:55:41","slug":"nodejs-24-ubuntu","status":"publish","type":"post","link":"https:\/\/computingforgeeks.com\/nodejs-24-ubuntu\/","title":{"rendered":"Install Node.js 24 LTS on Ubuntu 24.04 \/ 22.04"},"content":{"rendered":"\n<p>Node.js 24 shipped with a handful of changes that actually matter in practice. The permission model graduated from experimental (no more <code>--experimental-permission<\/code>, just <code>--permission<\/code>), built-in SQLite works with transactions and aggregates, URLPattern is globally available without an import, and npm 11 installs packages noticeably faster. V8 13.6 brings Float16Array, RegExp.escape(), and Error.isError(). It entered Active LTS as &#8220;Krypton&#8221; in October 2025 with security patches through April 2028.<\/p>\n\n\n\n<p>This guide covers three ways to install Node.js 24 on Ubuntu 24.04 and 22.04. We tested every method on a fresh VM, built a working Express 5 API, exercised the built-in test runner with describe blocks and async tests, demonstrated the new permission model and SQLite module, and configured a <a href=\"https:\/\/computingforgeeks.com\/systemctl-commands-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">systemd service<\/a> for production (including a gotcha with NVM that catches people off guard).<\/p>\n\n\n\n<p><em>Last verified: <strong>March 2026<\/strong> | Tested on Ubuntu 24.04 LTS with Node.js 24.14.0, npm 11.9.0, V8 13.6.233.17-node.41<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What You Need<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ubuntu 24.04 LTS or 22.04 LTS with sudo access<\/li>\n\n<li>About 80 MB disk space for Node.js and npm<\/li>\n\n<li>Port 3000\/tcp open if running web applications behind a firewall<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Check Your Current Node.js Version<\/h2>\n\n\n\n<p>Before installing, check whether Node.js is already on the system:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -v 2>\/dev\/null || echo \"Node.js not installed\"\nnpm -v 2>\/dev\/null || echo \"npm not installed\"<\/code><\/pre>\n\n\n\n<p>Ubuntu 24.04 ships Node.js 22 in its default repositories, and Ubuntu 22.04 ships Node.js 18. Neither includes Node.js 24, so you need one of the install methods below.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install Node.js 24 on Ubuntu<\/h2>\n\n\n\n<p>Three methods are available. Pick one based on your use case: NodeSource for production servers with automatic apt updates, NVM for development machines that need multiple versions, or the binary tarball for air-gapped or custom setups.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Method 1: NodeSource Repository (Recommended for Production)<\/h3>\n\n\n\n<p>NodeSource tracks upstream Node.js releases and packages them as .deb files that integrate with apt. Updates arrive within hours of each Node.js release.<\/p>\n\n\n\n<p>Add the NodeSource repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsSL https:\/\/deb.nodesource.com\/setup_24.x | sudo bash -<\/code><\/pre>\n\n\n\n<p>Install Node.js (npm and npx are bundled):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y nodejs<\/code><\/pre>\n\n\n\n<p>Confirm the version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -v\nnpm -v<\/code><\/pre>\n\n\n\n<p>Output from our Ubuntu 24.04 VM:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>v24.14.0\n11.9.0<\/code><\/pre>\n\n\n\n<p>Check the V8 engine, OpenSSL version, and module ABI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -e \"console.log('Platform:', process.platform, process.arch); console.log('V8:', process.versions.v8); console.log('OpenSSL:', process.versions.openssl); console.log('Modules:', process.versions.modules)\"<\/code><\/pre>\n\n\n\n<p>Real output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Platform: linux x64\nV8: 13.6.233.17-node.41\nOpenSSL: 3.5.5\nModules: 137<\/code><\/pre>\n\n\n\n<p>The module ABI version (137) matters when you upgrade from Node.js 22 (which uses 134), because native addons compiled for 22 won&#8217;t load on 24 without a rebuild.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Method 2: NVM (Best for Development)<\/h3>\n\n\n\n<p>NVM installs Node.js in your home directory and lets you <a href=\"https:\/\/computingforgeeks.com\/manage-nodejs-versions-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">switch between multiple Node.js versions<\/a> per project. No sudo required for npm global installs.<\/p>\n\n\n\n<p>Install NVM (auto-detects the latest release from GitHub):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NVM_VER=$(curl -s https:\/\/api.github.com\/repos\/nvm-sh\/nvm\/releases\/latest | grep tag_name | cut -d \\\" -f4)\ncurl -o- https:\/\/raw.githubusercontent.com\/nvm-sh\/nvm\/${NVM_VER}\/install.sh | bash<\/code><\/pre>\n\n\n\n<p>Reload your shell:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>source ~\/.bashrc<\/code><\/pre>\n\n\n\n<p>Install Node.js 24 and set it as the default:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nvm install 24\nnvm alias default 24<\/code><\/pre>\n\n\n\n<p>NVM downloaded and activated v24.14.0 on our test VM:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Downloading and installing node v24.14.0...\nNow using node v24.14.0 (npm v11.9.0)\nCreating default alias: default -> 24 (-> v24.14.0 *)<\/code><\/pre>\n\n\n\n<p>You can install multiple versions side by side. Here we have both 24 and 22:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nvm install 22\nnvm ls<\/code><\/pre>\n\n\n\n<p>The version list shows both with their LTS codenames:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>       v22.22.1\n->     v24.14.0\ndefault -> 24 (-> v24.14.0 *)\nlts\/jod -> v22.22.1\nlts\/krypton -> v24.14.0<\/code><\/pre>\n\n\n\n<p>Switch between them with <code>nvm use 22<\/code> or <code>nvm use 24<\/code>. Each version gets its own isolated set of global npm packages. A package you install globally on Node.js 24 is not visible when you switch to 22.<\/p>\n\n\n\n<p>One thing to keep in mind: NVM installs Node.js in <code>~\/.nvm\/versions\/<\/code>, which means only your user account can access it. If you need a systemd service or another user to run Node.js, NVM is the wrong choice. Use NodeSource instead (more on this in the systemd section below).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Method 3: Official Binary Tarball<\/h3>\n\n\n\n<p>Download the prebuilt binary directly from nodejs.org. This works on any Linux system regardless of package manager:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NODE_VER=$(curl -s https:\/\/nodejs.org\/dist\/latest-v24.x\/ | grep -oP 'node-v\\K[0-9.]+' | head -1)\ncurl -sLO https:\/\/nodejs.org\/dist\/v${NODE_VER}\/node-v${NODE_VER}-linux-x64.tar.xz\nsudo tar xJf node-v${NODE_VER}-linux-x64.tar.xz -C \/usr\/local --strip-components=1\nrm node-v${NODE_VER}-linux-x64.tar.xz<\/code><\/pre>\n\n\n\n<p>Verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -v\nnpm -v<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Install Build Tools for Native Modules<\/h2>\n\n\n\n<p>Some npm packages (<code>bcrypt<\/code>, <code>sharp<\/code>, <code>canvas<\/code>, <code>sqlite3<\/code>) compile native C\/C++ addons during install. If you see <code>gyp ERR! build error<\/code>, the fix is the build toolchain:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y build-essential<\/code><\/pre>\n\n\n\n<p>Many popular packages now ship prebuilt binaries for common platforms, so you might not hit this. But when you do, <code>build-essential<\/code> is the answer 100% of the time on Ubuntu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Build an Express 5 API<\/h2>\n\n\n\n<p>Express 5 is now the default when you <code>npm install express<\/code> (it shipped as 5.0 in late 2024 after years in beta). Let&#8217;s build a quick API to confirm everything works end to end.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p ~\/node-demo && cd ~\/node-demo\nnpm init -y\nnpm install express<\/code><\/pre>\n\n\n\n<p>npm pulls in Express 5.2.1 with 22 packages:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>added 22 packages, and audited 23 packages in 3s\nfound 0 vulnerabilities<\/code><\/pre>\n\n\n\n<p>Create the server file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi ~\/node-demo\/server.js<\/code><\/pre>\n\n\n\n<p>Add the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const express = require(\"express\");\nconst os = require(\"os\");\nconst app = express();\nconst PORT = 3000;\n\napp.get(\"\/\", (req, res) => {\n  res.json({\n    message: \"Node.js 24 LTS on Ubuntu 24.04\",\n    nodeVersion: process.version,\n    v8Version: process.versions.v8,\n    platform: process.platform,\n    arch: process.arch,\n    hostname: os.hostname(),\n    uptime: Math.round(process.uptime()) + \"s\",\n    memoryUsage: Math.round(process.memoryUsage().rss \/ 1024 \/ 1024) + \" MB\"\n  });\n});\n\napp.get(\"\/health\", (req, res) => {\n  res.json({ status: \"ok\", timestamp: new Date().toISOString() });\n});\n\napp.listen(PORT, () => console.log(\"Server running on port \" + PORT));<\/code><\/pre>\n\n\n\n<p>Start the server and hit both endpoints:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node ~\/node-demo\/server.js &\ncurl -s http:\/\/localhost:3000\/ | python3 -m json.tool<\/code><\/pre>\n\n\n\n<p>Real JSON response from our test VM:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"message\": \"Node.js 24 LTS on Ubuntu 24.04\",\n    \"nodeVersion\": \"v24.14.0\",\n    \"v8Version\": \"13.6.233.17-node.41\",\n    \"platform\": \"linux\",\n    \"arch\": \"x64\",\n    \"hostname\": \"test-ubuntu-24-computingforgeeks-com\",\n    \"uptime\": \"2s\",\n    \"memoryUsage\": \"63 MB\"\n}<\/code><\/pre>\n\n\n\n<p>The health endpoint returns a simple status check:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -s http:\/\/localhost:3000\/health | python3 -m json.tool<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"status\": \"ok\",\n    \"timestamp\": \"2026-03-24T17:55:44.632Z\"\n}<\/code><\/pre>\n\n\n\n<p>Stop the background server with <code>kill %1<\/code> when you&#8217;re done testing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use the Built-in Test Runner<\/h2>\n\n\n\n<p>Node.js 24 ships a production-ready test runner in <code>node:test<\/code>. It supports <code>describe<\/code>\/<code>test<\/code> blocks, async tests, setup\/teardown hooks, and multiple reporters without installing anything. For smaller projects, it replaces Jest or Mocha entirely.<\/p>\n\n\n\n<p>Create a test file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi ~\/node-demo\/test.mjs<\/code><\/pre>\n\n\n\n<p>Add a mix of sync and async tests organized in describe blocks:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { test, describe } from \"node:test\";\nimport assert from \"node:assert\";\n\ndescribe(\"Math operations\", () => {\n  test(\"addition\", () => {\n    assert.strictEqual(1 + 1, 2);\n  });\n\n  test(\"multiplication\", () => {\n    assert.strictEqual(3 * 7, 21);\n  });\n});\n\ndescribe(\"String operations\", () => {\n  test(\"includes\", () => {\n    assert.ok(\"Node.js 24 LTS\".includes(\"24\"));\n  });\n\n  test(\"template literals\", () => {\n    const version = 24;\n    assert.strictEqual(`Node.js ${version}`, \"Node.js 24\");\n  });\n});\n\ndescribe(\"Array operations\", () => {\n  const data = [10, 20, 30, 40, 50];\n\n  test(\"filter\", () => {\n    assert.strictEqual(data.filter(n => n > 25).length, 3);\n  });\n\n  test(\"reduce\", () => {\n    assert.strictEqual(data.reduce((a, b) => a + b, 0), 150);\n  });\n\n  test(\"find\", () => {\n    assert.strictEqual(data.find(n => n > 35), 40);\n  });\n});\n\ndescribe(\"Async operations\", () => {\n  test(\"setTimeout resolves\", async () => {\n    const result = await new Promise(resolve =>\n      setTimeout(() => resolve(\"done\"), 50)\n    );\n    assert.strictEqual(result, \"done\");\n  });\n\n  test(\"fetch is available globally\", async () => {\n    assert.ok(typeof fetch === \"function\");\n  });\n});<\/code><\/pre>\n\n\n\n<p>Run the tests:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node --test test.mjs<\/code><\/pre>\n\n\n\n<p>All 9 tests across 4 suites pass in about 125ms:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\u25b6 Math operations\n  \u2714 addition (0.814961ms)\n  \u2714 multiplication (0.220879ms)\n\u2714 Math operations (2.268367ms)\n\u25b6 String operations\n  \u2714 includes (0.303307ms)\n  \u2714 template literals (0.2107ms)\n\u2714 String operations (1.618383ms)\n\u25b6 Array operations\n  \u2714 filter (0.265355ms)\n  \u2714 reduce (0.191031ms)\n  \u2714 find (0.226293ms)\n\u2714 Array operations (1.052684ms)\n\u25b6 Async operations\n  \u2714 setTimeout resolves (50.389199ms)\n  \u2714 fetch is available globally (0.293877ms)\n\u2714 Async operations (50.986477ms)\n\u2139 tests 9\n\u2139 suites 4\n\u2139 pass 9\n\u2139 fail 0\n\u2139 duration_ms 125.107826<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Node.js 24 Features Worth Testing<\/h2>\n\n\n\n<p>A few of the new APIs are worth trying hands-on to see how they work in practice.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">URLPattern (no import needed)<\/h3>\n\n\n\n<p>URLPattern is now a global, similar to <code>URL<\/code> and <code>URLSearchParams<\/code>. No import required:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -e \"\nconst pattern = new URLPattern({ pathname: '\/users\/:id' });\nconst result = pattern.exec({ pathname: '\/users\/42' });\nconsole.log('Match:', result.pathname.groups);\n\"<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Match: { id: '42' }<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Permission Model (&#8211;permission flag)<\/h3>\n\n\n\n<p>The permission model restricts what a Node.js process can access. Without the flag, everything works normally. With <code>--permission<\/code>, file system and network access are denied unless explicitly allowed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo 'const fs = require(\"fs\"); console.log(fs.readFileSync(\"\/etc\/hostname\", \"utf8\").trim());' > \/tmp\/perm-test.js\nnode \/tmp\/perm-test.js\nnode --permission \/tmp\/perm-test.js<\/code><\/pre>\n\n\n\n<p>The first run prints the hostname. The second throws an error because file system reads are blocked:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node:fs:440\n    return binding.readFileUtf8(path, stringToFlags(options.flag));\n                   ^\nError: Access to this API has been restricted<\/code><\/pre>\n\n\n\n<p>Grant specific access with <code>--allow-fs-read<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node --permission --allow-fs-read=\/etc \/tmp\/perm-test.js<\/code><\/pre>\n\n\n\n<p>Now the read succeeds because <code>\/etc<\/code> is in the allow list. This is useful for sandboxing untrusted scripts or tightening production deployments.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Built-in SQLite<\/h3>\n\n\n\n<p>Node.js 24 includes SQLite through the <code>node:sqlite<\/code> module. It works with in-memory and file-based databases:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -e \"\nconst { DatabaseSync } = require('node:sqlite');\nconst db = new DatabaseSync(':memory:');\ndb.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');\ndb.exec(\\\"INSERT INTO users VALUES (1, 'Alice', 'alice@example.com')\\\");\ndb.exec(\\\"INSERT INTO users VALUES (2, 'Bob', 'bob@example.com')\\\");\nconst rows = db.prepare('SELECT * FROM users').all();\nconsole.log(JSON.stringify(rows, null, 2));\ndb.close();\n\"<\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[\n  {\n    \"id\": 1,\n    \"name\": \"Alice\",\n    \"email\": \"alice@example.com\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"Bob\",\n    \"email\": \"bob@example.com\"\n  }\n]<\/code><\/pre>\n\n\n\n<p>Note: as of v24.14.0, the SQLite module still prints an <code>ExperimentalWarning<\/code>. It works, but the API could change before it&#8217;s fully stable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Run Node.js as a systemd Service<\/h2>\n\n\n\n<p>For production, configure systemd to manage your Node.js app. This gives you automatic startup on boot, crash recovery, and log management through journald.<\/p>\n\n\n\n<p><strong>Important<\/strong>: if you installed Node.js via NVM, systemd services will fail with &#8220;Permission denied&#8221; because NVM installs to your home directory (<code>~\/.nvm\/versions\/<\/code>) and the service user cannot access it. Use NodeSource or the tarball method for production services. We hit this exact error during testing.<\/p>\n\n\n\n<p>Create a dedicated user for the application:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo useradd -r -s \/sbin\/nologin nodeapp<\/code><\/pre>\n\n\n\n<p>Copy your app to a system directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/opt\/myapp\nsudo cp ~\/node-demo\/server.js \/opt\/myapp\/\nsudo cp -r ~\/node-demo\/node_modules \/opt\/myapp\/\nsudo cp ~\/node-demo\/package.json \/opt\/myapp\/\nsudo chown -R nodeapp:nodeapp \/opt\/myapp<\/code><\/pre>\n\n\n\n<p>Create the service unit file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/etc\/systemd\/system\/nodeapp.service<\/code><\/pre>\n\n\n\n<p>Add the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[Unit]\nDescription=Node.js Express Application\nAfter=network.target\n\n[Service]\nType=simple\nUser=nodeapp\nWorkingDirectory=\/opt\/myapp\nExecStart=\/usr\/bin\/node server.js\nRestart=on-failure\nRestartSec=5\nEnvironment=NODE_ENV=production\nStandardOutput=journal\nStandardError=journal\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n<p>Enable and start:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl daemon-reload\nsudo systemctl enable --now nodeapp<\/code><\/pre>\n\n\n\n<p>The service status confirms it&#8217;s running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl status nodeapp<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\u25cf nodeapp.service - Node.js Express Application\n     Loaded: loaded (\/etc\/systemd\/system\/nodeapp.service; enabled; preset: enabled)\n     Active: active (running)\n   Main PID: 10803 (MainThread)\n     Memory: 17.9M\n        CPU: 135ms\n     CGroup: \/system.slice\/nodeapp.service\n             \u2514\u250010803 \/usr\/bin\/node \/opt\/myapp\/server.js<\/code><\/pre>\n\n\n\n<p>The <code>Restart=on-failure<\/code> directive means systemd will automatically restart the app after a 5-second delay if it crashes. View logs with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo journalctl -u nodeapp -f<\/code><\/pre>\n\n\n\n<p>For more advanced process management with cluster mode, log rotation, and zero-downtime reloads, look at <a href=\"https:\/\/computingforgeeks.com\/install-pm2-node-js-process-manager-on-rhel-centos-rocky\/\" target=\"_blank\" rel=\"noreferrer noopener\">PM2 process manager<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Upgrade from Node.js 22<\/h2>\n\n\n\n<p>If you are running Node.js 22 from NodeSource, swap the repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt remove -y nodejs\ncurl -fsSL https:\/\/deb.nodesource.com\/setup_24.x | sudo bash -\nsudo apt install -y nodejs<\/code><\/pre>\n\n\n\n<p>Rebuild native modules in every project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/path\/to\/your\/project\nnpm rebuild<\/code><\/pre>\n\n\n\n<p>The NODE_MODULE_VERSION changed from 134 (Node.js 22) to 137 (Node.js 24), so all native addons need recompilation. If you still hit <code>MODULE_NOT_FOUND<\/code> errors after the rebuild, delete <code>node_modules<\/code> entirely and reinstall: <code>rm -rf node_modules package-lock.json && npm install<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Node.js 22 vs Node.js 24<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Component<\/th><th>Node.js 22 (Jod)<\/th><th>Node.js 24 (Krypton)<\/th><\/tr><\/thead><tbody><tr><td>Status<\/td><td>Maintenance LTS (until Apr 2027)<\/td><td>Active LTS (until Apr 2028)<\/td><\/tr><tr><td>V8 Engine<\/td><td>12.4<\/td><td>13.6 (Float16Array, RegExp.escape(), Error.isError())<\/td><\/tr><tr><td>npm<\/td><td>10.x<\/td><td>11.9 (faster installs, improved security)<\/td><\/tr><tr><td>Test runner<\/td><td>Stable (basic)<\/td><td>Stable (describe blocks, global setup\/teardown)<\/td><\/tr><tr><td>Permission model<\/td><td><code>--experimental-permission<\/code><\/td><td><code>--permission<\/code> (promoted from experimental)<\/td><\/tr><tr><td><code>using<\/code> keyword<\/td><td>Not available<\/td><td>Explicit resource management<\/td><\/tr><tr><td>URLPattern<\/td><td>Requires import<\/td><td>Globally available<\/td><\/tr><tr><td>SQLite<\/td><td>Experimental<\/td><td>Works but still shows ExperimentalWarning<\/td><\/tr><tr><td>Undici<\/td><td>6.x<\/td><td>7.x with proxy support via <code>NODE_USE_ENV_PROXY<\/code><\/td><\/tr><tr><td>Express (default)<\/td><td>4.x<\/td><td>5.x (npm install express now gets Express 5)<\/td><\/tr><tr><td>NODE_MODULE_VERSION<\/td><td>134<\/td><td>137<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>If your project is stable on Node.js 22 and you don&#8217;t need these features, staying on 22 through April 2027 is fine. Upgrade when you need npm 11, the V8 13.6 improvements, or when Node.js 22 enters end-of-life.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install Yarn<\/h2>\n\n\n\n<p>Yarn Classic (1.x):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo npm install -g yarn\nyarn --version<\/code><\/pre>\n\n\n\n<p>This installs Yarn 1.22.22 globally. For Yarn 4.x (Berry), enable Corepack and set the version inside your project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo corepack enable\ncd \/path\/to\/your\/project\ncorepack use yarn@stable<\/code><\/pre>\n\n\n\n<p>Note the <code>sudo<\/code> on <code>corepack enable<\/code> when using NodeSource. Without it, the symlink creation fails with EACCES because <code>\/usr\/bin<\/code> requires root.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Uninstall Node.js<\/h2>\n\n\n\n<p>NodeSource:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt remove --purge -y nodejs\nsudo rm -f \/etc\/apt\/sources.list.d\/nodesource.list\nsudo apt update<\/code><\/pre>\n\n\n\n<p>NVM:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nvm uninstall 24\nrm -rf ~\/.nvm<\/code><\/pre>\n\n\n\n<p>Node.js 24 on Ubuntu is straightforward regardless of which install method you pick. For the same guide on <a href=\"https:\/\/computingforgeeks.com\/nodejs-24-debian\/\" target=\"_blank\" rel=\"noreferrer noopener\">Debian 13\/12<\/a> or <a href=\"https:\/\/computingforgeeks.com\/nodejs-24-rocky-almalinux\/\" target=\"_blank\" rel=\"noreferrer noopener\">Rocky Linux \/ AlmaLinux<\/a>, the NodeSource and NVM methods are identical. The <a href=\"https:\/\/nodejs.org\/en\/blog\/release\/v24.0.0\" target=\"_blank\" rel=\"noreferrer noopener\">official Node.js 24 changelog<\/a> has the full list of breaking changes if you&#8217;re upgrading a complex project.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Node.js 24 shipped with a handful of changes that actually matter in practice. The permission model graduated from experimental (no more &#8211;experimental-permission, just &#8211;permission), built-in SQLite works with transactions and aggregates, URLPattern is globally available without an import, and npm 11 installs packages noticeably faster. V8 13.6 brings Float16Array, RegExp.escape(), and Error.isError(). It entered Active &#8230; <a title=\"Install Node.js 24 LTS on Ubuntu 24.04 \/ 22.04\" class=\"read-more\" href=\"https:\/\/computingforgeeks.com\/nodejs-24-ubuntu\/\" aria-label=\"Read more about Install Node.js 24 LTS on Ubuntu 24.04 \/ 22.04\">Read more<\/a><\/p>\n","protected":false},"author":3,"featured_media":164325,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[690,299,50,81],"tags":[],"class_list":["post-164322","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","category-how-to","category-linux-tutorials","category-ubuntu"],"_links":{"self":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/164322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/comments?post=164322"}],"version-history":[{"count":7,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/164322\/revisions"}],"predecessor-version":[{"id":164403,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/164322\/revisions\/164403"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media\/164325"}],"wp:attachment":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media?parent=164322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/categories?post=164322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/tags?post=164322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}