← Back to Knowledge Base
Tutorials · July 17, 2026 · 11 min read

How to Install Node.js Applications in Plesk: A Complete Setup Guide

Linux server rack with Node.js logo connected to a Plesk-style dashboard via glowing deployment pipeline lines

Node.js apps are just part of the furniture on Plesk boxes these days — sitting right next to the PHP sites and static pages we’ve always run. The good part is Plesk actually treats Node.js like a first-class citizen rather than bolting it on: the Node.js extension, which has shipped since Onyx and gotten steadily better through the Obsidian line, gives you a real interpreter version manager, Passenger integration, and a UI that covers most of what used to mean hand-writing systemd units and reverse proxy blocks.

None of that means it runs itself, though. There’s a strict order you need to follow — domain setup, then document root, then package.json checks, then dependencies, then picking the right startup file — and skipping a step is exactly how you end up staring at a 503 with zero clues in the browser. What follows is the process I actually use on production servers, plus the mistakes that generate the most support tickets in my experience.

What You Need Before You Start

Server and License Requirements

You want Plesk Obsidian for this (Onyx still limps along, but it’s EOL — don’t put new work on it). You’ll also need the Node.js extension installed, which you can check under Tools & Settings > Updates and Upgrades > Add/Remove Components, or just open a domain and see if “Node.js” shows up in the sidebar. Most license tiers include it, but a few of the stripped-down hosting-only SKUs leave it out, so verify this before you tell a client it’ll just work.

Enabling the Node.js Extension in Plesk

If it’s missing, head to Extensions, search “Node.js,” and install it. That extension is doing all the heavy lifting here — version manager, Passenger hooks, per-app config panel. Resist the urge to compile Node from source or run your own nvm setup on the shell; Plesk expects to own the interpreter binary paths, and going around it just creates conflicts you’ll be debugging later.

Preparing Your Application Files

Before you even open the Plesk UI, get your app itself into a deployable state:

  • A valid package.json with a proper start script, or at minimum a clearly named entry file like app.js or server.js.
  • A .gitignore or upload package that leaves out node_modules — Plesk runs its own npm install anyway, and shipping a local node_modules folder just bloats the upload and can conflict with platform-specific native builds.
  • Config values like API keys, DB connection strings, and ports pulled from process.env instead of hardcoded — you’ll wire these in through Plesk in a minute.

Understanding Plesk’s Node.js Architecture

The Node.js Extension and Version Manager

Plesk’s version manager keeps multiple Node runtimes installed side by side — 16.x, 18.x, 20.x, whatever your apps need — without touching the system’s own Node binary or disturbing anything else on the box. Each app picks its version independently, which is exactly what you want on a shared server where one client’s legacy app sits next to something built against a current LTS.

How Passenger Integrates with Node.js Apps

This is where most confusion comes from. Plesk doesn’t launch your app as a bare process bound to some random port managed by PM2 or forever — it hands the whole thing to Phusion Passenger. Passenger owns the process lifecycle: starting it, killing it, restarting it after a crash, recycling idle workers. It talks to your app over a local socket and does the supervision work you’d otherwise be configuring by hand with systemd or PM2.

Nginx and Apache’s Role in Request Handling

The web server layer — Nginx, sometimes with Apache sitting in front depending on how the server’s configured — takes the incoming connection and proxies it into Passenger, which then hands it to your app. That’s why things like WebSocket support or upload size limits get configured through Plesk’s Nginx directive panel rather than inside your app’s own routing — there’s more happening at the web server layer here than you’d get from a plain Node dev server.

Step 1: Creating a Domain or Subdomain for Your App

Setting Document Root vs. Application Root

More deployments go sideways here than anywhere else. The document root is where the web server pulls static assets from — usually a public, dist, or build folder if you’ve got a compiled React front end sitting in front of an Express backend, for example. The application root is a different thing entirely — it’s the base folder holding package.json, and it’s where Passenger actually starts your app. Mix these two up and you’ll either be serving raw source code to the world or watching every static asset 404.

Choosing Between a Domain, Subdomain, or Subdirectory

A standalone domain or subdomain is the cleanest setup for a Node app — you get a dedicated document root, its own SSL cert, and its own Node.js config panel. You can run Node under a subdirectory of an existing PHP domain, but it adds real friction since you’re now managing two stacks under one vhost. Unless you’re spinning up a quick proof of concept, just give the app its own subdomain and save yourself the headache.

Step 2: Uploading and Configuring the Application

Uploading Files via File Manager, Git, or FTP

You’ve got three realistic options: File Manager for a quick drag-and-drop, FTP for bulk transfers, or — what I’d recommend for anything that’s going to keep getting updated — the Git extension. With Git, you push to a remote, Plesk pulls the changes, runs npm install, and restarts the app through deployment actions. It’s essentially free CI/CD without bringing in a separate pipeline tool.

Verifying package.json and Start Script

Open the Node.js tab on the domain and confirm Plesk actually picked up package.json correctly. If your start script does something out of the ordinary — a build step before launch, say, rather than a plain node server.js — make sure that’s properly defined in scripts.start. Plesk’s “Run Script” dropdown reads straight from that field, so if it’s wrong there, it’s wrong everywhere.

Selecting the Node.js Version per Application

Same panel — pick your interpreter version from the dropdown. This setting is per-app, not server-wide, so a new app can run Node 20 while a legacy one sits on Node 16, both on the same box, with zero interference between them.

Step 3: Installing Dependencies and Starting the App

Running npm install Through Plesk

Use the “NPM Install” button in the panel instead of SSHing in and doing it yourself. Plesk logs the full output right there in the UI, and it runs the install in the same environment Passenger will actually use to serve the app — which matters more than it sounds like. When an install fails, that log is usually the quickest way to spot a missing native build dependency or a bad private registry credential.

Setting the Application Startup File

Double-check the “Application Startup File” field points at the right entry point — app.js, index.js, server.js, whatever it is for your app. Set Application Mode to production — this isn’t just a label, it changes real behavior in Express and most other frameworks: error verbosity, caching, how performance-sensitive middleware behaves. Put your environment variables — NODE_ENV, DB connection strings, API keys — into Plesk’s “Custom Environment Variables” section, not into a .env file that’s sitting in your Git repo.

Switching Application

Once everything’s set, hit “Restart App.” Plesk restarts just the Passenger process without taking down the rest of the domain’s web service. Going forward, any code change needs a restart triggered one of three ways — this button, a Git deployment hook, or the API — because Passenger deliberately won’t pick up file changes on its own in production mode.

Best Practices

  • Run Application Mode as production on anything live — never development. The gap in performance and security isn’t subtle.
  • Keep secrets in Plesk’s environment variable panel. Never hardcode them, and never commit them to Git.
  • Use the Git extension with a post-deploy hook (npm install && restart) rather than manual FTP uploads for anything actively being developed.
  • Keep document root and application root explicitly separate — don’t trust Plesk to guess right, because it won’t always.
  • Pin the Node.js version per app instead of trusting “latest” — otherwise a server-wide update can break something you weren’t even thinking about.
  • Handle WebSocket support and upload limits through “Additional nginx directives” — don’t hand-edit the vhost config, since Plesk will happily overwrite it on the next update.
  • Check logs periodically even when nothing looks broken — memory leaks and slow degradation show up in the Passenger logs long before you get an actual outage.

Troubleshooting

Almost every Node.js problem I’ve seen on Plesk boils down to one of these:

SymptomLikely CauseFix
502/503 error on app URLApp crashed or never startedCheck Passenger log in Plesk’s log viewer or /var/www/vhosts/system/<domain>/logs; verify startup file path
Static assets 404Document root pointed at app root instead of build folderUpdate document root to public/dist directory in domain hosting settings
npm install failsMissing native build tools or wrong Node versionSwitch Node.js version in extension panel; check install log for missing headers/deps
Environment variables not appliedValues set in local .env but not in Plesk panelAdd variables via “Custom Environment Variables” and restart app
Changes not reflecting after deployPassenger cached old processManually click “Restart App,” or trigger restart via Git deployment action
WebSocket connections droppingMissing proxy headers/timeouts in NginxAdd required directives via “Additional nginx directives,” not raw config edits

Conclusion

Deploying Node.js under Plesk isn’t a fundamentally different job than deploying it anywhere else — you’re still dealing with npm, a start script, and a supervised process underneath it all. What’s different is where the supervision and routing actually happen: Passenger owns your app’s lifecycle, and the Node.js extension gives you a UI over the version manager, environment config, and restart hooks instead of a pile of hand-built systemd units. Get the document root and application root split correct, keep secrets out of your codebase, and lean on Git deployment instead of manual uploads for anything ongoing — do those three things and Nginx, Passenger, and the version manager will mostly just stay out of your way.

Frequently Asked Questions

Do I need to install Node.js manually on the server before using Plesk?

No — the Node.js extension comes with its own version manager, so you install and switch between Node versions per application without ever touching the system-wide Node install. That keeps apps isolated and stops different sites’ Node versions from stepping on each other.

What is the difference between the document root and application root in Plesk Node.js hosting?

The application root is where your package.json and source code live — it’s the folder Passenger launches the app from. The document root is the public-facing directory, often public or build, that Nginx/Apache serves static files out of. Get both set correctly and Passenger finds your app while static assets still get served efficiently.

Can I run multiple Node.js applications with different versions on the same Plesk server?

Yes — the built-in version manager lets each domain or subdomain run its own Node version independently. It doesn’t touch other sites or the server’s system Node install, which is exactly what you want in a multi-tenant hosting setup.

How does Plesk start and manage my Node.js application?

Passenger acts as the application server — it runs whatever startup file your package.json points to (usually via the start script) and takes care of process lifecycle, restarts, and scaling from there. All of that gets configured through the Plesk interface instead of you manually running node or pm2 commands yourself.

How do I set environment variables like NODE_ENV or API keys in Plesk?

There’s a dedicated environment variables section inside the Node.js app settings panel where you define NODE_ENV, database credentials, API keys, and so on. That keeps sensitive values out of your codebase entirely, rather than baked into a file that could end up committed somewhere it shouldn’t be.

How can I automatically redeploy my app when I push new code?

Hook up the Git extension to your repo and enable a deployment action that runs npm install and restarts the app on every push. If you’d rather not automate it, the “Restart App” button works fine as a manual trigger too, or you can call it via the API as part of your own CI/CD setup.

Related reading