How to Deploy a Node.js App on a VPS
nodejsvpsdeploymentnginxpm2

How to Deploy a Node.js App on a VPS

WWhata Cloud Editorial
2026-06-14
9 min read

A reusable checklist for deploying a Node.js app on a VPS with PM2, Nginx, custom DNS, and SSL.

Deploying a Node.js app on a VPS is one of those jobs that looks simple until small details start breaking things: the app runs but dies after logout, the domain points to the wrong place, HTTPS never finishes, or a reboot brings the site down. This guide gives you a practical, reusable checklist for deploying a Node.js app on a VPS with a sensible baseline: a Linux server, a non-root user, Node.js installed, PM2 for process management, Nginx as a reverse proxy, and SSL enabled for a custom domain. It is written to be revisited whenever you launch a new app, move providers, change DNS, or tighten your deployment workflow.

Overview

If your goal is to host a Node app on a server you control, a VPS is often the clean middle ground between shared hosting and fully managed platforms. You get root access, predictable resources, and the flexibility to run your own stack without overcomplicating things.

For most small to medium Node.js deployments, the repeatable path looks like this:

  1. Provision a VPS with a current Linux distribution.
  2. Create a non-root sudo user and harden SSH access.
  3. Install Node.js and your app dependencies.
  4. Transfer or clone the application code onto the server.
  5. Run the app on an internal port.
  6. Use PM2 to keep the process alive and restart on boot.
  7. Configure Nginx to listen on port 80 and proxy traffic to your app.
  8. Point your domain or subdomain to the VPS with the correct DNS records.
  9. Install an SSL certificate and force HTTPS.
  10. Test reboot behavior, logs, and basic failure cases.

This article assumes a conventional setup where your Node app listens on a local port such as 3000 and Nginx handles public traffic. That pattern is stable, easy to troubleshoot, and suitable for many production deployments.

If you are still deciding whether a VPS is the right fit, see Cloud Hosting vs Shared Hosting vs VPS: Which Is Right for Your Site?. If you are choosing server size, How Much Cloud Hosting Do You Need? CPU, RAM, Storage, and Bandwidth Guide is a useful companion.

Checklist by scenario

Use the checklist below based on where you are in the deployment process. The idea is not to memorize commands. It is to make sure you do not skip the operational pieces that turn a working app into a stable service.

Scenario 1: First-time VPS setup

Before you deploy your app, make the server safe and predictable.

  • Provision the VPS with enough CPU, RAM, and storage for your app and logs.
  • Update packages so the base system is current.
  • Create a non-root sudo user and avoid daily work as root.
  • Set up SSH keys and disable password-based SSH if that fits your environment.
  • Configure a firewall to allow SSH, HTTP, and HTTPS.
  • Set the correct timezone if you want logs and scheduled jobs to be easier to read.
  • Install Node.js using a method you can maintain consistently across servers.
  • Install Git if you plan to pull code directly from a repository.
  • Create an app directory with clear ownership under your deployment user.

At this stage, aim for a server that can survive a reboot and that you can access safely without workarounds.

Scenario 2: Uploading and running the Node.js app

Once the server is ready, deploy the code in the simplest way you can maintain.

  • Copy or clone the application code to the server.
  • Install dependencies in the app directory.
  • Create a production environment file for values such as PORT, database URLs, API keys, and session secrets.
  • Make sure the app binds to a local port like 3000 rather than exposing itself directly on port 80 or 443.
  • Test the app locally on the server with curl or by hitting http://127.0.0.1:3000.
  • Confirm production mode settings so the app is not running in a development configuration.
  • Check build steps if your app uses TypeScript, bundling, or asset compilation.

A common pattern is to keep the Node process private on localhost and let Nginx handle public traffic. That separates application concerns from web server concerns and makes SSL much easier.

Scenario 3: Process management with PM2

A Node process started in a terminal session is not a deployment. It is a test. Use a process manager so the app restarts after crashes and reboots.

  • Install PM2 globally for the deployment user.
  • Start the app with PM2 using a clear process name.
  • Save the PM2 process list so it can be restored automatically.
  • Enable PM2 startup on boot so the app returns after a reboot.
  • Verify logs through PM2 to catch startup errors quickly.
  • Set a memory restart threshold if your app may leak memory over time.

If you run multiple Node apps on one VPS, PM2 naming matters. Use names that reflect the environment and app, such as api-production or frontend-staging.

Scenario 4: Nginx reverse proxy setup

Nginx gives your Node app a public endpoint, handles incoming requests on standard ports, and can terminate SSL.

  • Install Nginx from the system package manager.
  • Create a server block for your domain or subdomain.
  • Proxy requests to the local Node port, usually 127.0.0.1:3000.
  • Pass standard proxy headers so the app sees the original host and client information.
  • Test the Nginx configuration before reloading.
  • Reload Nginx only after the configuration passes syntax checks.
  • Confirm the site loads over plain HTTP before introducing SSL.

This is the stage where many deployments fail because the app is working internally but the reverse proxy points to the wrong port, wrong socket, or wrong server name.

Scenario 5: Connect the domain and enable HTTPS

After the app is reachable from Nginx, connect your domain and secure it.

  • Create an A record pointing the domain or subdomain to the VPS IPv4 address.
  • Add an AAAA record only if your server is configured for IPv6 and you intend to support it.
  • Wait for DNS propagation and confirm resolution before troubleshooting Nginx.
  • Check nameservers so you are editing DNS in the right place.
  • Install an SSL certificate for the exact hostname you plan to use.
  • Enable HTTP to HTTPS redirect once the certificate is working.
  • Renew and retest to avoid silent certificate expiry later.

If DNS is the confusing part, Managed DNS vs Registrar DNS: Which Should You Use? and Nameserver Change Guide: How to Switch DNS Providers Safely can help clarify where records should live.

Scenario 6: Basic production hardening

Once the site is live, do a final pass that makes the deployment less fragile.

  • Store secrets outside the codebase and lock down file permissions.
  • Set log rotation for both app and Nginx logs.
  • Back up application data if the app writes local files.
  • Use a separate database service or managed database if reliability matters more than simplicity.
  • Disable unused services on the VPS.
  • Document the deployment steps for your future self or your team.

If you also manage staging and production environments, How to Set Up Staging and Production Domains for a Website is worth bookmarking.

What to double-check

These are the details that cause the most wasted time during a Node.js VPS deployment. They are worth verifying in order, every time.

  • The app is actually running. Before blaming DNS or SSL, confirm the Node process is live and listening on the expected port.
  • The app binds to localhost or the intended interface. Some apps default to a different host or port than you expect.
  • The environment file is loaded in production. Missing secrets, wrong database credentials, or development values can make the app start incorrectly or fail silently.
  • Nginx points to the same port the app uses. One mismatch here can make a healthy app look offline.
  • The domain resolves to the correct server. If you recently moved hosting, stale records or old nameservers may still be sending traffic elsewhere.
  • Ports 80 and 443 are open. A firewall can block otherwise correct Nginx and SSL configurations.
  • PM2 is configured to start on boot. Restart the VPS once before calling the deployment complete.
  • HTTPS is terminating at Nginx, not fighting with the app. In many setups, the app should speak HTTP internally while Nginx handles TLS.
  • Static assets and upload paths are correct. File path assumptions often differ between local development and a Linux server.
  • Logs are readable and located where you expect. When something breaks, quick access to PM2 and Nginx logs matters more than clever tooling.

If you are launching on a new hostname and also use business email, be careful not to overwrite unrelated DNS records. How to Launch a Website on a New Domain Without Breaking Email covers that risk well, especially for MX, TXT, SPF, and DKIM records.

Common mistakes

The same deployment mistakes come up repeatedly because they are easy to make and hard to notice until traffic hits the server.

Running the app directly on port 80 or 443

It can work, but it usually creates more problems than it solves. A reverse proxy gives you cleaner SSL handling, easier redirects, and better control over public traffic.

Using root for routine deployment

It feels faster at first, but it increases risk and often leaves file ownership in a messy state. A dedicated deployment user is safer and easier to maintain.

Skipping process management

If the app only runs after you SSH in and type a command, it is not truly deployed. PM2 or a similar process manager closes that gap.

Editing DNS in the wrong provider panel

This is especially common after a transfer or nameserver change. Always verify who is authoritative for DNS before changing records.

Requesting SSL before DNS is correct

Certificate issuance and validation often depend on the hostname resolving properly. Get the domain pointed correctly first, then install the certificate.

Forgetting production environment differences

Local development may rely on hot reloaders, permissive CORS settings, local file paths, or default ports. Production should be deliberate, not inherited from development habits.

Not testing a reboot

A deployment that survives only until the next maintenance restart is incomplete. Reboot once, then confirm the app, PM2, and Nginx all recover cleanly.

Combining application, database, and backups without a plan

For small projects, an all-in-one VPS may be acceptable. But if the app becomes important, separate concerns and make sure backups exist before you need them.

If you are moving an existing app from another server, Website Migration Checklist: Move Hosting Providers With Minimal Downtime can help you avoid DNS and cutover mistakes.

When to revisit

This deployment checklist is worth revisiting whenever one of the underlying inputs changes. Node.js hosting on a VPS is stable, but the surrounding details change more often than most teams expect.

Review your setup when:

  • You change VPS providers or resize the server. IP addresses, firewall defaults, storage layouts, and package baselines may change.
  • You switch DNS providers or update nameservers. Reconfirm records, TTL expectations, and SSL assumptions.
  • You add staging, preview, or production subdomains. Each hostname needs its own DNS and web server review.
  • You upgrade major Node.js versions. Recheck dependencies, build behavior, and PM2 startup configuration.
  • You introduce a database, queue, or background workers. The app may no longer be a single-process deployment.
  • You add team members. Access control, deployment scripts, and documentation should become more explicit.
  • You prepare for a campaign, launch, or seasonal traffic spike. This is the right time to test reboots, renewals, logs, and rollback steps.
  • Your deployment workflow changes. If you move from manual SSH deploys to Git-based or CI-driven releases, revalidate the entire flow rather than assuming the old server state still applies.

Here is a simple action plan to keep handy before each new deployment:

  1. Confirm the VPS is updated and reachable by SSH key.
  2. Verify Node.js, PM2, and Nginx versions are where you expect them to be.
  3. Deploy the app and test it locally on the server.
  4. Check PM2 status and logs.
  5. Confirm Nginx proxies traffic correctly.
  6. Verify DNS resolution for the intended hostname.
  7. Install or renew SSL and test HTTPS.
  8. Reboot once and test again.
  9. Document any one-off fixes so they do not stay one-off.

That final step matters more than it seems. Good VPS deployment habits are mostly about reducing surprises. The more your setup is written down and repeated the same way, the less likely a routine Node app release turns into a late-night debugging session.

For related workflows, you may also want to read SSL Certificate Setup Guide for Domains and Subdomains, Best VPS Hosting for Developers: Updated Comparison by Price and Specs, and How to Deploy a Static Site With a Custom Domain if your stack includes both static and server-rendered properties.

Related Topics

#nodejs#vps#deployment#nginx#pm2
W

Whata Cloud Editorial

Senior SEO Editor

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.

2026-06-14T06:17:31.896Z