Learn how to deploy Node.js apps using PM2 and Nginx on a Linux server.
Introduction
Running a Node.js application in production requires more than simply starting a server with node app.js. Production environments require process management, automatic restarts, logging, and a reliable web server to handle traffic efficiently.
In this guide, we deploy a Node.js application using PM2 for process management and Nginx as a reverse proxy. This approach is widely used in production environments because it ensures reliability, scalability, and efficient resource usage.
The steps below cover the complete process from server preparation to advanced production practices.
Prerequisites
Before we begin, ensure we have the following:
- An Ubuntu 24.04 on dedicated server or KVM VPS.
- Basic Linux Command Line Knowledge.
- A domain name pointing A DNS record to server IP.
Learn how to deploy Node.js apps using PM2 and Nginx on a Linux server.
Prepare the Server Environment
We begin by updating the server packages. Keeping the system updated ensures compatibility and security.
sudo apt update
sudo apt upgrade -y
Install essential tools that will help with development and deployment.
sudo apt install curl git build-essential -y
These utilities are commonly required when compiling packages or cloning application repositories.
Install the Latest Node.js
The NodeSource repository provides the most stable Node.js builds for production systems.
Add the repository:
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
Install Node.js:
sudo apt install nodejs -y
Verify the installation:
node -v
npm -v
Using the LTS (Long Term Support) version ensures long-term stability for production workloads.
Install PM2 Process Manager
PM2 is a powerful process manager designed for Node.js applications. It keeps applications running, automatically restarts them if they crash, and provides monitoring and logging features.
Install PM2 globally:
sudo npm install pm2 -g
Verify installation:
pm2 -v
PM2 will now manage Node.js processes in the background and ensure they stay online.
Create or Deploy the Node.js Application
Applications may be deployed by cloning a repository or uploading project files to the server.
Example project setup:
mkdir my-node-app
cd my-node-app
npm init -y
Install Express:
npm install express
Create the application file.
nano app.js
Example application:
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("Node.js application running with PM2 and Nginx");
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});
Start the application for testing:
node app.js
Once the application runs successfully, it is ready to be managed by PM2.
Start the Application with PM2
Instead of running the application directly with Node.js, we run it through PM2.
pm2 start app.js --name my-node-app
Check running processes:
pm2 list
View logs:
pm2 logs my-node-app
Restart the application:
pm2 restart my-node-app
Stop the application:
pm2 stop my-node-app
PM2 ensures the application continues running even if the process crashes.
Enable PM2 Auto Start on Server Boot
Production servers should automatically restore running applications after a reboot.
Generate startup configuration:
pm2 startup
Run the command displayed by PM2.
Then save the current process list:
pm2 save
Now the Node.js application will automatically restart whenever the server reboots.
Install and Configure Nginx
Nginx acts as a reverse proxy, allowing external traffic on ports 80 and 443 to be forwarded to the Node.js application running on port 3000.
Install Nginx:
sudo apt install nginx -y
Start the service:
sudo systemctl enable nginx
sudo systemctl start nginx
Verify status:
sudo systemctl status nginx
Firewall Configuration
Allow only required ports.
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Configure Nginx Reverse Proxy
Create a new configuration file for the Node.js application.
sudo nano /etc/nginx/sites-available/node-app
Add the following configuration:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Enable the configuration:
sudo ln -s /etc/nginx/sites-available/node-app /etc/nginx/sites-enabled/
Test the configuration:
sudo nginx -t
Reload Nginx:
sudo systemctl reload nginx
Nginx will now route incoming traffic to the Node.js application.
Secure the Application with SSL (Recommended)
For production environments, HTTPS should always be enabled.
Install Certbot:
sudo apt install certbot python3-certbot-nginx -y
Generate SSL certificates:
sudo certbot --nginx -d example.com
Certbot automatically configures HTTPS and sets up renewal.
Test renewal process:
sudo certbot renew --dry-run
Enable PM2 Cluster Mode for High Traffic
PM2 supports cluster mode, which allows the application to use multiple CPU cores.
Start the application using all available CPU cores:
pm2 start app.js -i max --name my-node-app
This significantly improves performance for high-traffic applications.
Monitor Application Performance
PM2 provides real-time monitoring tools.
Open the monitoring dashboard:
pm2 monit
This view displays CPU usage, memory consumption, and application status.
For advanced monitoring environments, PM2 can integrate with external monitoring platforms.
Manage Application Logs
Logs are essential for debugging and performance monitoring.
View logs:
pm2 logs
Clear logs when necessary:
pm2 flush
Logs are stored in:
~/.pm2/logs
Maintaining clean logs helps prevent unnecessary disk usage.
Best Practices for Production Deployments
Reliable production deployments usually follow several important practices:
Environment Variables
Sensitive configuration values should not be stored in application code.
Example:
export NODE_ENV=production
PM2 can also load environment variables from configuration files.
Use a Deployment Directory
Organizing projects improves long-term maintainability.
Example structure:
/var/www/
node-app
Zero-Downtime Reloads
PM2 allows seamless application reloads.
pm2 reload my-node-app
This restarts the application without interrupting active connections.
Final Thoughts
Deploying Node.js with PM2 and Nginx creates a stable production environment capable of handling real-world workloads. PM2 ensures applications remain online and recover automatically, while Nginx efficiently manages incoming traffic and provides an additional security layer.
By combining these tools, teams can run Node.js applications with high reliability, improved performance, and simplified operational management.
This deployment method has become a widely adopted standard across modern hosting environments and cloud platforms.

