How Do I Deploy My Node.js App to a Server? (No PM2 or Nginx Setup, with Plesk and Git)
· 6 min read
Running a Node.js app on your own computer with node server.js is easy; the hard part is keeping the same app running on a server reliably, securely and in a way that's easy to update. On a bare Linux server, that means a long setup made up of SSH access, a process manager, a reverse proxy and SSL configuration. In this guide we first look at the parts of the classic approach, then show you step by step how to reach the same result with the Plesk Obsidian panel and your GitHub repository, without opening a terminal.
The 4 Components That Keep a Node.js App Online
On a classic Linux server (unmanaged VPS), you install and maintain each of these parts yourself:
- Node.js runtime: Installing the right Node.js version on the server (usually with
nvm) and keeping up with security updates. - Process manager: The tool that brings the app back up when it crashes or when the server reboots. Classic setups use PM2 for this; if you forget the
pm2 startupandpm2 savesteps, your app stays down after a server reboot. - Reverse proxy: The web server that forwards requests on ports 80 and 443 to the port your app listens on (e.g.
3000). A single wrong port in Nginx'sproxy_passline shows up for visitors as a 502 Bad Gateway page. - SSL certificate: Obtaining a certificate for HTTPS and renewing it before it expires.
In Plesk Obsidian, all four components are handled in the panel: you pick the Node.js version from a list, Phusion Passenger runs your app and connects it to the web server, and the Let's Encrypt certificate is issued from the panel and renewed automatically. That's why you don't need to install PM2 or write an Nginx configuration file.
Comparing Ways to Deploy Node.js
| Method | Setup and maintenance | Knowledge required | Best suited for |
|---|---|---|---|
| Unmanaged VPS (SSH + PM2 + Nginx) | Node.js, PM2, Nginx, SSL and the firewall are set up by hand; operating system updates are your job | Linux server administration | Teams that want full control over the server |
| Open-source PaaS panel such as Coolify | Docker-based builds and deploys on git push; server maintenance is your job | Docker basics | Teams running several services in containers |
| Developer Hosting with Plesk Obsidian (zuwinasa cloud) | Node.js version, npm, environment variables and SSL are managed in the panel; the provider maintains the server | Git and npm basics | Developers who want to run an Express or NestJS app alongside their website, database and email in one panel |
Deploying a Node.js App with Plesk and Git in 5 Steps
1. Prepare Your Project for Production
Check the following in your repository so the app runs smoothly on the server:
- Port: Because Plesk runs your app through Passenger, you don't set a fixed port. Read the port from an environment variable:
app.listen(process.env.PORT || 3000). - Startup file: Note the name of the file that starts your app (
app.js,server.jsor, for TypeScript projects, the compileddist/main.js). - Secrets: Don't commit your
.envfile; you'll define the database URL and API keys as environment variables in the panel in step 4. - Dependencies:
package.jsonandpackage-lock.jsonmust be in the repository; thenode_modulesfolder is not committed but installed on the server.
2. Connect Your GitHub Repository to Plesk
- In Plesk, open Websites & Domains, go to your domain's Git menu and add a new repository.
- Choose the remote Git hosting option (GitHub, Bitbucket, etc.) as the source and enter the repository address.
- For a private repository, enter the address in SSH format (
[email protected]:username/project.git). Copy the SSH public key Plesk generates and add it under Settings > Deploy keys in your GitHub repository; by default, this key only grants read access to that repository. - Choose the target folder (
/httpdocsby default) and confirm. Plesk clones the repository and places the files in that folder.
3. Turn On Automatic Deployment for Every Push
- In the repository's Repository Settings, leave the deployment mode set to automatic.
- Copy the webhook URL from the same screen, add it as a new webhook under Settings > Webhooks in GitHub and select the push event as the trigger. From now on, Plesk pulls and deploys the changes every time you push.
- Enable additional deployment actions and enter the commands to run after each deployment, one per line:
npm cifor dependencies,npm run buildfor the build, andmkdir -p tmp && touch tmp/restart.txtso the app restarts with the new code (Passenger restarts the app when the timestamp of this file in the application root changes). - If a command fails with
npm: command not found, use npm's full path in Plesk:/opt/plesk/node/<version>/bin/npm.
4. Configure the Node.js Settings
Fill in these fields in your domain's Node.js menu:
- Node.js Version: Select the LTS version your project supports from the list.
- Application Root: The folder the repository is deployed to, e.g.
/httpdocs. - Document Root: Must be a subfolder of the application root, e.g.
/httpdocs/public; static files are served from here. - Application Mode:
production; this value is written to theNODE_ENVvariable. - Application Startup File: The file you noted in step 1; the default is
app.js. - Custom environment variables:
DATABASE_URL, API keys and other secrets.
5. Install Dependencies and Start the App
- Install the dependencies from
package.jsonwith the NPM install button; if your project needs a build, run thebuildscript with Run script. - Click Enable Node.js; your app goes live on your domain. After changing settings, restart it with Restart App.
- For HTTPS, get a free Let's Encrypt certificate under SSL/TLS Certificates. If the app throws an error, check the Node.js entries in your domain's Logs.
Note: If your startup file uses
importsyntax (an ES module), Passenger may fail to start the app with arequire() of ES Module is not supportederror. In that case, create apassenger.cjsfile in the application root containing only the lineimport('./app.js');and select it as the startup file.
Which Plan Supports It?
At zuwinasa cloud, Node.js support is included in the Developer Hosting plans (Full Stack and Dev-Box); both come with Git integration and /bin/bash SSH access as standard. If you prefer the terminal, you can run npm commands directly over SSH in the same subscription. If your app runs on Docker, a Coolify server is a better fit, and if you need full control at the operating system level, a Cloud VPS with root access is the right choice. For general go-live steps such as your domain and DNS, see our guide on how to publish your app online.