> ## Documentation Index
> Fetch the complete documentation index at: https://help.noxity.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js

> Run Node.js apps on cPanel via the Node.js Selector. Pick a version, set up the application root, manage with NPM Install and Run JS Script.

The cPanel **Setup Node.js App** tool registers a Node app under your account, builds an isolated `node_modules` directory, and hands the running process to Phusion Passenger.

Each app picks its own Node version. You can run several apps under the same account on different paths or versions.

## Available versions

Available versions vary by host. Typical rotation:

* **Node 22.** Current LTS.
* **Node 20.** Older LTS, still maintained.
* **Node 18.** EOL upstream, kept for legacy apps.

## Set up an app

<Steps>
  <Step title="Open Setup Node.js App">
    From cPanel home, scroll to **Software** and click **Setup Node.js App**.

    <Frame caption="cPanel home → Software → Setup Node.js App">
      <img src="https://mintlify.s3.us-west-1.amazonaws.com/noxity/images/web-hosting/virtual-containers/nodejs/open-light.png" alt="Setup Node.js App tool icon" className="block dark:hidden" />

      <img src="https://mintlify.s3.us-west-1.amazonaws.com/noxity/images/web-hosting/virtual-containers/nodejs/open-dark.png" alt="Setup Node.js App tool icon" className="hidden dark:block" />
    </Frame>
  </Step>

  <Step title="Click Create Application">
    On an empty account, you land on a list page with a **+ Create Application** button.
  </Step>

  <Step title="Fill in the form">
    * **Node.js version**: pick from the dropdown.
    * **Application mode**: Production or Development. Development sets `NODE_ENV=development` and prints fuller errors.
    * **Application root**: directory under your home, e.g. `myapp`. Created if it doesn't exist.
    * **Application URL**: domain dropdown plus optional path. Use `/` for the root or `/api` for a sub-path.
    * **Application startup file**: defaults to `app.js`. Set this to whatever file exports your handler.
    * **Passenger log file**: optional. Useful for catching boot errors.
  </Step>

  <Step title="Save">
    Click **Create**. Passenger starts the app in the background.
  </Step>
</Steps>

## Manage an app

The management page opens after creation and is reachable from the app list.

| Button              | What it does                                                                          |
| ------------------- | ------------------------------------------------------------------------------------- |
| **Run NPM Install** | Reads `package.json` and installs dependencies into the per-app `node_modules`.       |
| **Run JS Script**   | Runs a `package.json` script (e.g. `build`, `prestart`) under the activated Node env. |
| **Stop App**        | Halts Passenger for this app. The URL returns 503.                                    |
| **Restart**         | Equivalent to `touch tmp/restart.txt`. Reloads the running app.                       |
| **Edit**            | Reopens the form. Saving overwrites the `.htaccess`.                                  |
| **Destroy**         | Removes Passenger registration and the per-app `node_modules` directory.              |

The **Environment variables** editor sits below the buttons. Names allow letters, numbers, underscores, and dashes (max 256 chars). Values are ASCII, max 1024 chars.

## The Passenger contract

Passenger runs your code. Your code does not start an HTTP server.

```js app.js theme={}
const http = require('http');

module.exports = http.createServer((req, res) => {
  res.end('Hello from Passenger\n');
});
```

For Express:

```js app.js theme={}
const express = require('express');
const app = express();

app.get('/', (_req, res) => res.send('hi'));

module.exports = app;
```

A working example never calls `app.listen()`. If you copied a tutorial that does, delete that line.

<Warning>
  Calling `app.listen(PORT)` from inside a Passenger-managed app produces a 503 on every request and an `EADDRINUSE` or `Cannot find module` line in the Passenger log. Remove the call.
</Warning>

## Reference: where things live

| What                     | Path                                           |
| ------------------------ | ---------------------------------------------- |
| Activated env script     | `~/nodevenv/<app-root>/<version>/bin/activate` |
| Installed node\_modules  | `~/<app-root>/node_modules/`                   |
| Restart trigger          | `~/<app-root>/tmp/restart.txt`                 |
| Passenger config         | `~/<app-root>/.htaccess` (Selector-managed)    |
| Boot log (if configured) | path you set in **Passenger log file**         |

The activate script is what **Run NPM Install** sources before running `npm install`. From SSH:

```bash theme={}
source ~/nodevenv/myapp/22/bin/activate && cd ~/myapp
npm install
```

## Common issues

<AccordionGroup>
  <Accordion title="App returns 503 on every request">
    Most often: `app.listen(PORT)` is in the startup file. Remove it, swap to `module.exports = app`, then touch `tmp/restart.txt` to reload.
  </Accordion>

  <Accordion title="Cannot find module 'X' after deploying">
    `package.json` is in the application root, but `node_modules` was built on a different machine or against a different Node version. Click **Run NPM Install** so it installs against the per-app env.
  </Accordion>

  <Accordion title="Boot times out after 60 seconds">
    Default Passenger startup timeout. Add to `.htaccess` above the Selector-managed block:

    ```apache theme={}
    PassengerStartTimeout 120
    ```

    Common cause: the app loads a large dataset on boot, or a synchronous DNS lookup blocks startup.
  </Accordion>

  <Accordion title="WebSockets close after a few seconds">
    Passenger forwards `Upgrade:` headers, but the LVE entry-process cap throttles long-lived connections. Plan around 20 to 30 simultaneous WS clients on a shared plan, or move to a Power plan.
  </Accordion>

  <Accordion title="`npm install` runs out of memory">
    PMEM is \~1 GB. Large dependency trees (Next.js, Strapi) can OOM during install. Run install over SSH with `--prefer-offline --no-audit`, or build on a dev machine and rsync `node_modules` and code over.
  </Accordion>
</AccordionGroup>

## Recipes

<CardGroup cols={2}>
  <Card title="Deploy Next.js" icon="react" href="/how-to/virtual-containers/nodejs/nextjs">Server-rendered Next.js with a custom server.</Card>
  <Card title="Deploy Express" icon="diagram-project" href="/how-to/virtual-containers/nodejs/express">REST API behind Passenger.</Card>
</CardGroup>

## Need a hand?

<CardGroup cols={2}>
  <Card title="Open a ticket" icon="life-ring" href="https://members.noxity.io/submitticket.php">
    Best for anything that needs an account check or a config change on our end.
  </Card>

  <Card title="Live chat" icon="messages" href="https://noxity.io/contact">
    Faster for quick questions during business hours.
  </Card>
</CardGroup>

<div className="mt-8">
  <Accordion title="Sources" icon="book-bookmark">
    * [Virtual Containers overview](/web-hosting/virtual-containers/overview)
    * [Setup Node.js App ↗](https://docs.cpanel.net/cpanel/software/setup-nodejs-app/)
    * [CloudLinux Node.js Selector ↗](https://docs.cloudlinux.com/cloudlinuxos/cloudlinux_os_components/#nodejs-selector)
    * [Phusion Passenger Node.js ↗](https://www.phusionpassenger.com/library/walkthroughs/start/nodejs.html)
  </Accordion>
</div>
