
You can host and run a Node.js app in cPanel by creating it in the panel's Node.js app tool, choosing a Node.js version, an application root, a URL and a startup file, then installing dependencies with Run NPM Install. The web server starts and stops the app for you through Phusion Passenger, so you don't run node app.js yourself or pick a port. This guide covers the setup step by step, Next.js with standalone output, where to find logs, and when a VPS is the better fit.
Key takeaways
- cPanel servers use one of two Node.js tools: CloudLinux's Setup Node.js App or cPanel's own Application Manager. Both run apps through Passenger. The menu name depends on your host.
- Your startup file must be a CommonJS file. CloudLinux's docs say Passenger "cannot load ECMAScript modules," and give a one-line wrapper if your app uses
import. - Install dependencies with Run NPM Install, or over SSH after activating the app's environment.
- After every code or variable change, restart the app with the Restart button or by touching
tmp/restart.txt. - Next.js runs from the
server.jsfile thatoutput: 'standalone'creates.
How Node.js works on cPanel hosting
On a VPS you'd start Node yourself and keep it alive with a process manager. On cPanel hosting, the web server does that job. CloudLinux's documentation says its Node.js Selector "uses mod_passenger to host Node.js," and cPanel's Application Manager also deploys apps "with the Phusion Passenger® application server," which works as a process manager and reverse proxy (CloudLinux docs: Node.js Selector; cPanel docs: Application Manager).
Which tool you see depends on the server:
| CloudLinux Node.js Selector | cPanel Application Manager | |
|---|---|---|
| Where in cPanel | Software » Setup Node.js App | Software » Application Manager |
| Pick a Node.js version per app | Yes, from a drop-down | Uses the version your host installed |
| Install dependencies | Run NPM Install button | Enable Dependencies action |
| Environment variables | Add Variable | Add Variable (needs mod_env on the server) |
| Startup file | Any NAME.js you enter | app.js unless the host adds a config file |
Your host may label the menu differently or offer only one of them. This guide follows the CloudLinux steps because that interface exposes every setting in the panel. Where cPanel's tool differs, the table above is your map.
If your host runs LiteSpeed Web Server, the same apps work there: LiteSpeed's docs say it "supports the Apache mod_passenger configuration generated through CloudLinux selectors" (LiteSpeed docs: CloudLinux).
Before you start: two things to check in your code
1. The port setting is ignored. Passenger hands your app its own socket. cPanel calls this reverse port binding, and LiteSpeed's docs say "any port specifications in the listen function are ignored." Keep your listen() call as it is; just don't depend on a fixed port.
2. The startup file must be CommonJS. If Node throws ERR_REQUIRE_ESM on start, CloudLinux suggests a small wrapper file, app_wrapper.cjs, and using it as the startup file:
(() => import('app.js'))();A minimal app that works as a startup file looks like the example in cPanel's Node.js install guide:
const http = require('http')
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World! NodeJS\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});Step 1: Create the Node.js application
- In cPanel, open Software » Setup Node.js App and start a new application.
- Fill in the settings described in CloudLinux's Node.js Selector UI docs:
- Node.js version: pick the version your app needs. Next.js, for example, needs at least Node.js 20.9.
- Application mode: Production or Development.
- Application root: the folder that holds your code, relative to your home directory, such as
nodeapp. - Application URL: the domain or subdomain (and optional path) where the app should answer.
- Application startup file: the entry file, such as
app.jsorserver.js. - Passenger log file (optional): a path where Passenger writes the app's log.
- Save it. The app appears in the Web Applications list with its URI, root directory, mode and status.
These are the same settings CloudLinux's command-line tool takes when it creates an app (--app-root, --app-uri, --version, --app-mode, --startup-file), per the CloudLinux CLI docs.
Step 2: Upload your code
Put your project files in the application root. Two easy ways:
- Git: in cPanel » Files » Git Version Control, click Create, paste the clone URL, and set Repository Path to the application root (cPanel docs: Git Version Control).
- File Manager: upload a zip of the project and extract it in the application root.
Don't upload your local node_modules folder. Install dependencies on the server in the next step instead.
Step 3: Install dependencies (npm install)
The simplest route is in the panel: open the app with the Pencil (edit) icon and click Run NPM Install. CloudLinux's docs describe it as installing "the package(s) described in the package.json file."
To do it over SSH or in cPanel » Advanced » Terminal, CloudLinux says to "activate the Selector environment with the command shown by the panel," go to the application directory, and run npm install. The CLI docs give the activation command's format:
source /home/USER/nodevenv/APP_ROOT/NODE_VERSION/bin/activate
cd ~/APP_ROOT
npm installCopy the exact line from the panel rather than typing it, since it contains your username, app folder and Node.js version. After activation, CloudLinux notes, you "can use npm and node from a virtual environment without full paths."
If npm fails with an ENOMEM error, the server's memory setting for cPanel processes is too low. CloudLinux documents the fix as a WHM setting, so ask your host to raise it.
Step 4: Add environment variables
On the app's edit page, click Add Variable, enter a name and value, and save. Your code reads them from process.env:
const apiKey = process.env.API_KEY;Use this for API keys, database URLs and NODE_ENV, rather than committing a .env file to Git. In cPanel's Application Manager, the same Add Variable button exists, but cPanel notes that your host "must install the ea-apache24-mod_env Apache module" for it to work.
Step 5: Restart the app after every change
Passenger keeps the running copy of your app in memory, so new code or new variables only take effect after a restart. You have two options:
- Click Restart in the Web Applications list or on the app's edit page.
- Create or touch
tmp/restart.txtinside the application root:
mkdir -p ~/nodeapp/tmp
touch ~/nodeapp/tmp/restart.txtcPanel's docs say this file "directs mod_passenger to restart the application," and that you must touch it each time (cPanel docs). LiteSpeed documents the same tmp/restart.txt method.
Next.js hosting on cPanel (standalone output)
Next.js supports all of its features when it runs as a Node.js server (Next.js docs: Deploying). In cPanel, use standalone output. LiteSpeed's docs say that to run Next.js through the Node.js Selector you "first must compile the NextJS project as a standalone," which "will create a server.js script that you can use as a startup script."
1. Turn on standalone output
In next.config.js (Next.js docs: output):
module.exports = {
output: 'standalone',
}2. Build and copy the static folders
Run the build, then copy public and .next/static into the standalone folder. The Next.js docs explain that the minimal server "does not copy the public or .next/static folders by default":
npm run build
cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/You can build on your own computer or in CI. If your app uses packages with native binaries, the Next.js docs show how to include them with outputFileTracingIncludes (they use sharp as the example).
3. Upload and point the startup file at server.js
Upload the contents of .next/standalone to your application root, so server.js sits at the top of it. Then set:
| Setting | Value |
|---|---|
| Node.js version | 20.9 or newer (Next.js minimum) |
| Application root | the folder holding server.js |
| Application URL | your domain or subdomain |
| Application startup file | server.js |
The standalone folder already contains the node_modules it needs, so Next.js says it "can then be deployed on its own without installing node_modules." Skip Run NPM Install for this setup and click Restart.
To test the same bundle locally first, Next.js gives this command:
node .next/standalone/server.jsLogs and troubleshooting
Start with the log, because the browser usually shows only a generic error page.
| Where | What you'll find |
|---|---|
stderr.log in the application root | The app's error output on LiteSpeed (LiteSpeed docs) |
| The Passenger log file path you set in Step 1 | Passenger's log for the app (CloudLinux Node.js Selector) |
logs/ inside the app folder | Node.js logs when you use cPanel's Application Manager |
console.log output on LiteSpeed | Add SetEnv LSNODE_CONSOLE_LOG console.log to .htaccess to write it to console.log in the app root |
Common problems:
ERR_REQUIRE_ESMon start: your startup file is an ES module. Use theapp_wrapper.cjswrapper shown above.Cannot find module ...: dependencies aren't installed for this Node.js version. Click Run NPM Install, then restart.- Your changes don't show up: restart the app. Passenger is still running the old code.
- Next.js pages load without styles or images: the
publicand.next/staticfolders weren't copied into the standalone build. - No Node.js menu in cPanel: your host hasn't enabled a Node.js tool for your account, so ask them which one they offer.
When to move your Node.js app to a VPS
cPanel hosting suits websites, APIs and Next.js sites that respond to requests. It's a weaker fit when the app has to run work on its own:
- Long-running workers and background jobs. Passenger manages the process for you. In Passenger's own configuration reference, an idle process "will be shutdown in order to conserve memory" after
PassengerPoolIdleTime(300 seconds by default), and processes are spawned when the app is first accessed (Passenger docs). Timers, queue consumers and cron-like loops inside your app can't rely on staying up. - Heavy WebSocket use. LiteSpeed proxies WebSocket upgrades to apps run through the Node.js Selector automatically, so small real-time features can work. Busy chat, game or streaming servers that hold many open connections need resources and tuning that a shared account isn't built for.
- Custom ports, system packages or your own process manager. A shared account runs inside the host's limits. On CloudLinux servers, cPanel's resource usage page shows your account's CPU, memory and process limits and any times you hit them.
If any of these describe your app, a VPS or dedicated server gives you full control. For request-driven Node.js apps, WaseerHost runs Node.js apps in cPanel, including Next.js, on LiteSpeed. See Node.js hosting for current plans.
Frequently asked questions
Yes, if the host has installed a Node.js tool in cPanel, such as CloudLinux's Setup Node.js App or cPanel's Application Manager. Both run your app through Phusion Passenger. You don't get a process manager of your own, so the app should be request-driven rather than a long-running worker.

Written by
Web & AI Systems Lead
Web and AI Systems Lead at Wasevo, the company behind WaseerHost. He builds web applications and AI systems.

