Deploy a Node.js Application on DirectAdmin or cPanel Shared Hosting
Evaluate shared-hosting Node.js support and deploy through cPanel Passenger or DirectAdmin Nginx Unit with realistic platform limits.
On this page
A control-panel login does not guarantee that a shared-hosting plan can run Node.js. The provider must enable an application runner, offer a compatible Node.js version, allow dependency installation and build steps, and expose logs and environment configuration. Confirm those capabilities before uploading the project.
Features vary between providers, server operating systems, control-panel versions, and plans. The menu names below describe current official cPanel Passenger and DirectAdmin Nginx Unit options; a host may disable them or provide a different wrapper.
Ask the provider these questions
- Is Node.js enabled for this plan, and which exact versions are selectable?
- Does the panel use Passenger, Nginx Unit, CloudLinux Setup Node.js App, or another runner?
- Can the user run
npm ciand the required production build over SSH or the panel? - Which application root, public URL, and startup-file rules apply?
- How are environment variables, restarts, and logs managed?
- Are outbound database connections allowed, and must IPs be allowlisted?
- Are WebSockets, cron jobs, queues, and persistent background workers supported?
- What CPU, memory, process, request-timeout, disk, and inode limits apply?
- Can native packages compile, and which system libraries are installed?
If support cannot answer these, deploy a minimal health application before committing to the platform.
Prepare the application
The startup file must launch the production server without a development watcher. It must use the port or listener provided by the runner rather than assuming a public fixed port:
const http = require("node:http");
const port = Number(process.env.PORT || 3000);
const server = http.createServer((request, response) => {
if (request.url === "/health") {
response.writeHead(200, { "content-type": "application/json" });
response.end(JSON.stringify({ status: "ok" }));
return;
}
response.writeHead(404);
response.end();
});
server.listen(port);Passenger can use reverse port binding, so follow the provider's startup example instead of opening or advertising port 3000. Framework adapters may have additional requirements. Export a standalone production build if the framework supports it, and do not upload development caches or a local node_modules directory built for another operating system.
Set scripts that make the deployment repeatable:
{
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node dist/server.js"
}
}Run npm ci when the provider supports it, then npm run build. If build memory exceeds the plan, build in CI for the same OS/CPU/runtime and deploy a reviewed artifact—but only when dependencies do not require installation-time native binaries for the target.
Deploy through cPanel Application Manager
Current cPanel documentation describes Application Manager as a Passenger interface whose availability depends on the provider enabling the feature and installing the required packages.
A typical flow is:
- Upload or clone the repository into an application root under the account home directory, not into an unrelated site's public files.
- Open Software → Application Manager and register the application.
- Choose the domain/path and production deployment environment.
- Confirm the Node.js runtime and startup file expected by the host.
- Add production environment variables through the panel when its environment module is enabled.
- Enable/install npm dependencies or run the provider's documented SSH command.
- Build the application and deploy/restart it.
cPanel's low-level Passenger documentation uses app.js as the default startup file. A different entry point may require server-level configuration that shared-hosting users cannot edit, so ask the provider or add a small app.js adapter rather than modifying Apache files you do not own.
On applicable cPanel Passenger setups, touching tmp/restart.txt tells Passenger to restart the application:
mkdir -p tmp
touch tmp/restart.txtThe panel may expose a restart button instead. Use its supported method and confirm the new process actually loaded the current build.
Deploy through DirectAdmin Nginx Unit
DirectAdmin's official Nginx Unit integration appears at User level → Advanced Features → Nginx Unit when the server administrator has enabled it.
A typical flow is:
- Create the application directory under the domain/account and upload the built project.
- Ensure the entry script exists, has correct ownership, and is executable if the server requires that.
- In Nginx Unit, create a Node.js application with the application root and entry script.
- Create a route mapping the intended domain or path to the application.
- Add environment variables through the provider-supported Unit or panel configuration.
- Save/reload the application and request its health endpoint.
The DirectAdmin guide's Node.js example expects an app.js file to exist before the panel creates the application. Templates and available Node.js modules depend on the server's Unit build, so confirm the runtime version rather than assuming the local version is installed.
Configure secrets and database access
Put environment values in the panel or provider's protected configuration mechanism. Do not commit .env, paste secrets into tickets, or publish screenshots containing values. After changing variables, restart the runner because an existing process may keep its old environment.
For a remote database, verify DNS, port, TLS requirements, credentials, and any source-IP allowlist from the hosting account. Shared outbound IPs can change or be unsuitable for allowlisting; ask the provider. Use a bounded connection pool because every application process consumes part of the database connection budget. See PostgreSQL direct connections versus poolers and PostgreSQL Connection URL Explained.
Understand shared-hosting limits
Shared accounts normally do not have sudo, so they cannot install operating-system packages such as Tesseract, Chromium libraries, or custom database servers. Native npm modules may fail when a compiler, headers, compatible libc, or build permission is missing.
Other common constraints are provider-specific:
- the runner may stop idle processes and start them on the next request;
- local disk may be quota-limited, ephemeral in parts, or unsuitable for uploads;
- long-running queues, schedulers, and workers may not be supported;
- request duration, process count, memory, and CPU may be tightly limited;
- WebSockets and custom ports may be unavailable;
- deploys may restart all requests rather than provide zero-downtime rollout.
Store durable uploads in approved persistent or object storage, not an assumed application directory. Use the control panel's cron feature only for bounded jobs and prevent overlapping runs. Never disguise a permanent worker as a cron loop when the plan prohibits it.
Find useful logs
Check the panel's application log, Passenger or Unit error output, domain web-server error log, and build command output. Locations differ, and some hosts expose logs only through the UI. Add structured application logs to stdout/stderr without tokens, cookies, database URLs, or customer payloads.
Common causes of a blank page or 503 include a missing startup file, wrong application root, unsupported Node.js syntax, failed dependency install, missing build output, missing environment variable, or process limit. Reproduce the exact start command with the panel-selected Node binary when SSH access permits it.
When to move to a VPS or container platform
Move when the application requires system packages, reliable workers or queues, custom networking, predictable CPU/memory, long requests, multiple cooperating services, controlled rolling deployments, or observability the plan cannot provide. A VPS adds patching, firewall, backup, and incident-response responsibility; PM2 with Nginx describes one self-managed server option.
This is a capability decision, not a claim that every Node.js application needs a VPS. A small HTTP application can fit shared hosting well when the provider explicitly supports its runtime and workload.
Verification checklist
- The plan exposes a documented Node.js runner and compatible runtime version.
- Application root, startup file, URL mapping, and port behavior match the runner.
- Locked dependencies install and the production build output exists on the target.
- Secrets live in protected environment configuration and survive restart.
- Health, static assets, uploads, database TLS, and representative routes work publicly.
- Application, runner, web-server, and build logs are accessible and sanitized.
- Storage, workers, WebSockets, native dependencies, and resource limits fit the workload.
References
Documentation checked on 2026-08-12:
Related writing
- Deploy a Node.js Application with PM2 and NginxBuild and run a Node.js application with PM2, proxy it through Nginx, preserve client headers, and verify the deployment safely.
- Store and Serve User-Uploaded Images in Node.jsAccept, validate, store, serve, replace, and back up public images without exposing private documents or trusting upload metadata.
- Deploy a FastAPI OCR Service with Docker and TesseractPackage a FastAPI OCR endpoint with Tesseract, safe upload handling, health checks, limits, and production verification.