Updated: May 17, 2026

By Matic BončinaFounder
Review pending
Before you begin
- A Node.js project on your machine with a
package.jsonand an entry file (commonlyapp.jsorserver.js). - cPanel access on a plan that exposes Setup Node.js App.
- A domain or subdomain already pointed at the account.
Deploy Express
REST API on Express.
Deploy Next.js
SSR Next.js with a custom server.
Create the container
1
Open Setup Node.js App
From cPanel home, scroll to Software and click Setup Node.js App.
2
Click Create application
On an empty account the Web applications tab reads “No applications found”, with a Create application button beside it.
3
Fill in the form
- Node.js version: pick the highest LTS your code supports. The dropdown defaults to 20, which is EOL, so change it to 24 unless a dependency holds you back.
- Application mode:
Production. It starts on Development, which is worth keeping only while you chase a boot error. - Application root: a folder under your home directory, e.g.
myapp. Created for you if it doesn’t exist. - Application URL: the domain dropdown plus an optional path. Use
/for the root or/apito mount the app on a sub-path. - Application startup file: the file that exports your handler. The field starts empty, so fill it in yourself.
- Environment variables: add them one at a time with Add variable.
4
Click Create
The management page opens. The Selector scaffolds the application root for you, including a working starter
app.js, a public/ directory, and tmp/restart.txt.Upload your code
Three workflows. Pick whichever fits how your project lives today.- File Manager
- SFTP
- Git
Zip your project locally (skip
node_modules and .git), then:- cPanel home → File Manager.
- Navigate to the application root you created (e.g.
~/myapp). - Upload the zip, then right-click it and Extract in place.
- Delete the zip once the contents are extracted.
Install dependencies
Back on Setup Node.js App, find your app in the list and open it. Click Run NPM Install. cPanel sources the per-app virtualenv, then runsnpm install against the package.json in your application root.
Big dependency trees (Next.js, Nuxt, Strapi, anything that pulls in sharp) can OOM during install. Run it over SSH instead, with flags that keep the resident set smaller:
node_modules on a dev machine and rsync the tree up.
Set environment variables
The Environment variables editor sits below the buttons on the management page. Click Add variable, fill in Name and Value, then Done. Restart for new values to reach the running process. Common ones to set:Don’t set
PORT. Passenger ignores it. It drives the runtime over a Unix socket, not a TCP port. If your code reads process.env.PORT, that’s fine, but the value is irrelevant.Make the entry file Passenger-compatible
Passenger starts your process and hands it each request. It hooks the firsthttp.Server that calls listen() and moves it onto a Unix socket, so an ordinary Express app deploys unchanged:
app.js
app.js
Guides written for VPS deployment sometimes tell you to delete the
listen() call first. Skip that step. The port argument is discarded, and the line does no harm.Start and verify
1
Restart from the management page
Click Restart. Equivalent to
touch ~/myapp/tmp/restart.txt from SSH.2
Hit the URL
Open the Application URL in a browser. Your app should respond.
3
If it's a 503, the process didn't start
A 503 means the app crashed on boot or never came up. Confirm the Application startup file points at a file that exists, run Run NPM Install, then Restart.
Common issues
503 on every request
503 on every request
The process isn’t running. Check the startup file path, then Run NPM Install and Restart.
app.listen() is not the cause: Passenger ignores the port you pass it.Cannot find module 'X' after deploying
Cannot find module 'X' after deploying
package.json is in the right place, but node_modules was built on a different machine or Node version. Click Run NPM Install so it builds against the per-app env.Boot times out
Boot times out
Passenger allows 90 seconds for an app to start, then kills the process. Loading a large dataset or running a synchronous DNS lookup on boot is the usual cause.Move that work out of the startup path. The Selector doesn’t write an
.htaccess into the application root, so there’s no per-app file to raise the limit in; open a ticket if your app genuinely needs longer.App URL returns the cPanel default page, not your app
App URL returns the cPanel default page, not your app
The application URL is set to a sub-path (
/api) but you’re hitting /. Either change the URL in the form, or move your routes so they match the configured path.`npm install` runs out of memory
`npm install` runs out of memory
PMEM is ~1 GB on shared plans. Run install over SSH with
--prefer-offline --no-audit, or build node_modules locally and rsync the directory up.Env var change doesn't take effect
Env var change doesn't take effect
Saving the editor stores the value but doesn’t reload the process. Hit Restart after every change.
Next
Deploy Express
Wire up an Express API.
Deploy Next.js
Run SSR Next.js behind Passenger.
Need a hand?
Open a ticket
Best for anything that needs an account check or a config change on our end.
Live chat
Faster for quick questions during business hours.

