Home/Blog/software engineering
Back to all articles
software engineering#MERN Stack#DevOps#Nginx

Production MERN Stack Deployment: Nginx Reverse Proxy, PM2 Clustering & SSL Hardening

RB
Rajput BhavinArchitect
Founder, Rajput Bhavin Engineering
24 August 2026•11 min read

Quick Answer: Production MERN Stack Deployment#

⚡ Quick Answer / Executive Summary
Deploying a production MERN stack application on a Linux (Ubuntu) server requires a hardened multi-layer architecture: Nginx acts as the high-performance reverse proxy and SSL termination gateway, PM2 manages Node.js background process clustering and zero-downtime reloads across all CPU cores, MongoDB is locked to localhost or private VPC networks with mandatory authentication, and UFW (Uncomplicated Firewall) restricts open ports strictly to 22 (SSH), 80 (HTTP), and 443 (HTTPS).

Production Deployment Topology#

Architecture Blueprint
System Flow
┌─────────────────────────────────────────────────────────────┐
│                       Public Internet                       │
└─────────────────────────────┬─────────────────────────────┘
                              │ HTTPS (Port 443) / Let's Encrypt SSL
┌─────────────────────────────▼─────────────────────────────┐
│                 Linux VPS (Ubuntu 24.04 LTS)               │
│                                                             │
│  ┌───────────────────────────────────────────────────────┐  │
│  │               Nginx Reverse Proxy & Static CDN        │  │
│  │   • Serves compiled React/Next.js frontend assets     │  │
│  │   • Proxies /api requests to localhost:5000           │  │
│  │   • Gzip/Brotli Compression & Security Headers        │  │
│  └──────────────────────────┬────────────────────────────┘  │
│                             │ Reverse Proxy (HTTP/1.1)      │
│  ┌──────────────────────────▼────────────────────────────┐  │
│  │               PM2 Cluster (Node.js / Express)         │  │
│  │   • Worker 1 (Port 5000)  •  Worker 2 (Port 5000)     │  │
│  │   • Auto-restart on crash & boot startup hook         │  │
│  └──────────────────────────┬────────────────────────────┘  │
│                             │ TCP Socket (127.0.0.1:27017)  │
│  ┌──────────────────────────▼────────────────────────────┐  │
│  │            MongoDB Database (Private Auth Only)       │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

Step 1: Server Hardening & Firewall (UFW) Configuration#

Terminal / Bash
Production Code
# 1. Update OS packages
sudo apt update && sudo apt upgrade -y

# 2. Configure Firewall (Only allow SSH, HTTP, and HTTPS)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Step 2: PM2 Process Management & Zero-Downtime Reloads#

PM2 ensures your Node.js backend restarts automatically if an unhandled exception occurs and leverages all available CPU cores:

#1. PM2 Ecosystem File (ecosystem.config.js)

JavaScript
Production Code
module.exports = {
  apps: [
    {
      name: 'mern-backend-api',
      script: './dist/server.js',
      instances: 'max', // Scale to all CPU cores
      exec_mode: 'cluster',
      env_production: {
        NODE_ENV: 'production',
        PORT: 5000,
      },
      max_memory_restart: '1G',
      listen_timeout: 10000,
      kill_timeout: 5000,
    },
  ],
};

#2. Start & Enable Boot Startup

Terminal / Bash
Production Code
# Start cluster
pm2 start ecosystem.config.js --env production

# Configure systemd startup script so PM2 survives server reboots
pm2 save
pm2 startup

Step 3: Hardened Nginx Reverse Proxy Configuration#

Create /etc/nginx/sites-available/app.conf:

Nginx Config
Production Code
# Rate Limiting Zone: 10 requests/second per IP
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
    listen 80;
    server_name api.rajputbhavin.engineer;

    # Security Headers
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;

    # Gzip Compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

    location / {
        limit_req zone=api_limit burst=20 nodelay;

        proxy_pass http://127.0.0.1:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 60s;
    }
}

Enable the configuration and obtain automated SSL:

Terminal / Bash
Production Code
sudo ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

# Install free Let's Encrypt SSL Certificate
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d api.rajputbhavin.engineer

4 Common Deployment Failures to Prevent#

  1. ✓Exposing MongoDB Port 27017 to the Public Internet: Ensure bindIp: 127.0.0.1 is set in /etc/mongod.conf. Never expose your database port to the open web without VPC peering.
  2. ✓Storing Secrets in .env Files in Git: Add .env to .gitignore. Inject secrets via environment variables or secret managers (AWS Secrets Manager, Doppler).
  3. ✓Hardcoding localhost:5000 in React Bundles: Use environment variables (process.env.NEXT_PUBLIC_API_URL) to dynamically target production URLs during compilation.
  4. ✓Ignoring Log Rotation: Node.js log files will eventually fill the entire server disk. Install pm2-logrotate to compress and rotate logs automatically.

Enterprise DevOps & Deployment with Rajput Bhavin Engineering#

Need help designing bulletproof cloud infrastructure, CI/CD pipelines, or containerized deployments?

Software Engineering Consultation

Need help architecting your modern software stack?

Rajput Bhavin Engineering provides hands-on systems architecture, codebase reviews, and custom cloud software development for technology teams in India and worldwide.

RB

Rajput Bhavin

Systems Architect

Founder and Systems Architect at Rajput Bhavin Engineering in Gota, Ahmedabad. Specializes in high-concurrency cloud software, Next.js web applications, multi-tenant SaaS architecture, and autonomous AI systems.

Connect Now