Advanced PM2 Deployment - Production-Grade Setup
This is the ADVANCED guide for PM2 deployment. For basic PM2 setup, see DEPLOYMENT-MIKRUS.md.
🎯 When to Use This Guide
Section titled “🎯 When to Use This Guide”Use this guide if you need:
- ✅ Cluster mode (multi-core CPU utilization)
- ✅ Zero-downtime deployments
- ✅ Advanced monitoring (PM2+, Keymetrics)
- ✅ Auto-scaling based on load
- ✅ Log rotation and management
- ✅ Memory/CPU limits per process
- ✅ Load balancing across instances
- ✅ Custom deployment scripts
Prerequisites:
- You’re comfortable with Node.js and process management
- You understand PM2 basics (ecosystem files, pm2 commands)
- You’ve read the basic PM2 setup in DEPLOYMENT-MIKRUS.md
📋 System Requirements
Section titled “📋 System Requirements”- OS: Ubuntu 24.04 LTS (or similar)
- Node.js: v24.x LTS
- PM2: v5.3+ (
npm install -g pm2@latest) - CPU: 2+ cores (for cluster mode)
- RAM: 4GB+ (2GB+ available for app)
🚀 Advanced Ecosystem Configuration
Section titled “🚀 Advanced Ecosystem Configuration”Production-Grade ecosystem.config.js
Section titled “Production-Grade ecosystem.config.js”module.exports = { apps: [ { name: "sellf-admin", cwd: "./admin-panel", script: "npm", args: "start",
// CLUSTER MODE - Utilize all CPU cores instances: "max", // or specific number: 2, 4, etc. exec_mode: "cluster",
// ENVIRONMENT env: { NODE_ENV: "production", PORT: 3000, },
// RESOURCE LIMITS max_memory_restart: "1G", // Restart if memory exceeds 1GB max_restarts: 10, // Max restarts in min_uptime window min_uptime: "10s", // Minimum uptime to consider restart loop
// AUTO-RESTART autorestart: true, watch: false, // Don't use watch in production (use pm2 reload instead)
// LOGGING error_file: "./logs/pm2-error.log", out_file: "./logs/pm2-out.log", log_date_format: "YYYY-MM-DD HH:mm:ss Z", merge_logs: true,
// ADVANCED kill_timeout: 5000, // Time to wait for graceful shutdown listen_timeout: 10000, // Time to wait for app to listen shutdown_with_message: true,
// CRON RESTART (optional - restart daily at 3am) // cron_restart: "0 3 * * *",
// SOURCE MAP SUPPORT (for better error traces) source_map_support: true,
// INSTANCE VAR (useful for logs) instance_var: "INSTANCE_ID", } ],
// DEPLOYMENT CONFIGURATION deploy: { production: { user: "deploy", host: ["your-vps.mikr.us"], ref: "origin/main", repo: "git@github.com:YOUR_USERNAME/sellf.git", path: "/home/deploy/sellf",
// PRE-DEPLOY HOOKS "pre-deploy-local": "echo 'Starting deployment...'",
// POST-DEPLOY HOOKS "post-deploy": ` cd admin-panel && npm ci && npm run build && pm2 reload ecosystem.config.js --env production && pm2 save `,
// PRE-SETUP "pre-setup": "apt-get install git -y",
// ENV env: { NODE_ENV: "production" } } }};🔧 Advanced PM2 Commands
Section titled “🔧 Advanced PM2 Commands”Cluster Management
Section titled “Cluster Management”# Start in cluster mode (uses all CPU cores)pm2 start ecosystem.config.js
# Scale up/downpm2 scale sellf-admin 4 # Scale to 4 instancespm2 scale sellf-admin +2 # Add 2 more instancespm2 scale sellf-admin -1 # Remove 1 instance
# Zero-downtime reload (cluster mode only)pm2 reload sellf-admin
# Graceful restart (one by one)pm2 gracefulReload sellf-adminMonitoring & Logs
Section titled “Monitoring & Logs”# Real-time monitoringpm2 monit
# CPU/Memory usagepm2 statuspm2 describe sellf-admin
# Logspm2 logs sellf-admin --lines 200pm2 logs sellf-admin --err # Only errorspm2 logs sellf-admin --raw # Raw logs (no formatting)pm2 flush sellf-admin # Clear logs
# Log rotation (install module)pm2 install pm2-logrotatepm2 set pm2-logrotate:max_size 100Mpm2 set pm2-logrotate:retain 7 # Keep 7 dayspm2 set pm2-logrotate:compress trueProcess Management
Section titled “Process Management”# Stop/Start/Restartpm2 stop sellf-adminpm2 start sellf-adminpm2 restart sellf-admin
# Delete process (remove from PM2)pm2 delete sellf-admin
# Reset restart countpm2 reset sellf-admin
# Send signal to processpm2 sendSignal SIGUSR2 sellf-adminStartup Script (Auto-start on reboot)
Section titled “Startup Script (Auto-start on reboot)”# Generate startup scriptpm2 startup
# Follow the instructions (will output a command like):# sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u deploy --hp /home/deploy
# Save current PM2 process listpm2 save
# Test (reboot server)sudo reboot
# After reboot, verifypm2 status # Should show sellf-admin running📊 Advanced Monitoring
Section titled “📊 Advanced Monitoring”Option 1: PM2 Plus (Keymetrics) - Cloud Monitoring
Section titled “Option 1: PM2 Plus (Keymetrics) - Cloud Monitoring”- Sign up at https://app.pm2.io
- Link your server:
Terminal window pm2 link <secret_key> <public_key> - Features:
- Real-time metrics (CPU, Memory, Network)
- Exception tracking
- Custom metrics
- Alerts (email, Slack, webhook)
- Transaction tracing
- Log streaming
Option 2: PM2 Metrics Module (Self-Hosted)
Section titled “Option 2: PM2 Metrics Module (Self-Hosted)”# Install metrics modulepm2 install pm2-metrics
# Install auto-pull (auto-update from git)pm2 install pm2-auto-pull
# Configure auto-pullpm2 set pm2-auto-pull:interval 300000 # Check every 5 minutespm2 set pm2-auto-pull:apps sellf-adminOption 3: Prometheus + Grafana
Section titled “Option 3: Prometheus + Grafana”# Install PM2 Prometheus exporternpm install -g pm2-prometheus-exporter
# Start exporterpm2-prometheus-exporter
# Metrics available at: http://localhost:9209/metricsGrafana Dashboard:
- Import dashboard ID: 10869 (PM2 Metrics)
- Connect to Prometheus datasource
- Visualize: CPU, Memory, Restarts, Errors
🔄 Zero-Downtime Deployments
Section titled “🔄 Zero-Downtime Deployments”Method 1: PM2 Reload
Section titled “Method 1: PM2 Reload”cd /path/to/sellfgit pull origin main
cd admin-panelnpm cinpm run build
# Zero-downtime reload (cluster mode)pm2 reload sellf-adminHow it works:
- PM2 starts new instances with new code
- Waits for them to be ready (listen on port)
- Gracefully shuts down old instances
- No downtime!
Method 2: PM2 Deploy (Automated)
Section titled “Method 2: PM2 Deploy (Automated)”# Initial setup (one-time)pm2 deploy production setup
# Deploypm2 deploy production
# Rollbackpm2 deploy production revert 1
# Execute command on remotepm2 deploy production exec "pm2 reload all"Method 3: Custom Deploy Script
Section titled “Method 3: Custom Deploy Script”Create scripts/deploy.sh:
#!/bin/bashset -e
echo "🚀 Starting deployment..."
# 1. Pull latest codegit pull origin main
# 2. Install dependenciescd admin-panelnpm ci
# 3. Run migrations (if using Supabase CLI)cd ..npx supabase db push --linked
# 4. Build appcd admin-panelnpm run build
# 5. Reload PM2 (zero-downtime)cd ..pm2 reload ecosystem.config.js
# 6. Verifypm2 statuspm2 logs sellf-admin --lines 20 --nostream
echo "✅ Deployment complete!"Make executable:
chmod +x scripts/deploy.sh🛡️ Security & Hardening
Section titled “🛡️ Security & Hardening”1. Run as Non-Root User
Section titled “1. Run as Non-Root User”# Create deploy usersudo adduser deploysudo usermod -aG sudo deploy
# Switch to deploy usersu - deploy
# Install PM2 as deploy usernpm install -g pm2
# Setup PM2 startuppm2 startup # Follow instructions2. Environment Variables
Section titled “2. Environment Variables”Never commit .env.local to git!
# Store secrets in PM2 ecosystemmodule.exports = { apps: [{ name: "sellf-admin", env_production: { STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY, SUPABASE_SERVICE_ROLE_KEY: process.env.SUPABASE_SERVICE_ROLE_KEY, } }]};
# Or use dotenv in ecosystem:module.exports = { apps: [{ name: "sellf-admin", env_file: "./admin-panel/.env.production", }]};3. Firewall
Section titled “3. Firewall”sudo ufw enablesudo ufw allow 22 # SSHsudo ufw allow 80 # HTTPsudo ufw allow 443 # HTTPSsudo ufw deny 3000 # Block direct access to appsudo ufw status4. Rate Limiting (Nginx)
Section titled “4. Rate Limiting (Nginx)”limit_req_zone $binary_remote_addr zone=app:10m rate=10r/s;
server { listen 80; server_name your-domain.com;
location / { limit_req zone=app burst=20 nodelay; 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; }}📈 Performance Optimization
Section titled “📈 Performance Optimization”1. Cluster Mode Tuning
Section titled “1. Cluster Mode Tuning”module.exports = { apps: [{ instances: "max", // Use all CPU cores exec_mode: "cluster",
// OR: Reserve cores for other services // instances: Math.max(require('os').cpus().length - 1, 1), }]};2. Memory Management
Section titled “2. Memory Management”module.exports = { apps: [{ max_memory_restart: "1G", // Restart if memory > 1GB
// Node.js memory options node_args: [ "--max-old-space-size=1024", // 1GB heap "--optimize-for-size", ], }]};3. Log Rotation
Section titled “3. Log Rotation”# Install log rotationpm2 install pm2-logrotate
# Configurepm2 set pm2-logrotate:max_size 100Mpm2 set pm2-logrotate:retain 30pm2 set pm2-logrotate:compress truepm2 set pm2-logrotate:workerInterval 3600 # Rotate hourly4. Build Optimization
Section titled “4. Build Optimization”# Use production modeexport NODE_ENV=production
# Optimize Next.js buildcd admin-panelnpm run build
# Check bundle sizenpm run analyze # If configured in next.config.js🔍 Debugging & Profiling
Section titled “🔍 Debugging & Profiling”CPU Profiling
Section titled “CPU Profiling”# Start app with --prof flagpm2 start ecosystem.config.js --node-args="--prof"
# Run load test# ...
# Stop apppm2 stop sellf-admin
# Process v8 lognode --prof-process isolate-*.log > processed.txt
# Analyze processed.txtMemory Leak Detection
Section titled “Memory Leak Detection”# Start with heap profilingpm2 start ecosystem.config.js --node-args="--inspect"
# Connect Chrome DevTools# chrome://inspect
# Take heap snapshots before/after suspected leak# Compare snapshots to find leaked objectsPM2 Internal Monitoring
Section titled “PM2 Internal Monitoring”# Enable internal monitoringpm2 set pm2:autodump true
# Dump PM2 internal statepm2 dump
# Restore from dumppm2 resurrect🚨 Troubleshooting
Section titled “🚨 Troubleshooting”High Memory Usage
Section titled “High Memory Usage”# Check memory per instancepm2 status
# Reduce instancespm2 scale sellf-admin 2
# Set memory limit# In ecosystem.config.js: max_memory_restart: "512M"pm2 reload sellf-adminHigh CPU Usage
Section titled “High CPU Usage”# Check CPU per instancepm2 monit
# Profile the app (see CPU Profiling above)
# Reduce instances temporarilypm2 scale sellf-admin 1Process Crashes
Section titled “Process Crashes”# Check logspm2 logs sellf-admin --err
# Check restart countpm2 status
# Disable auto-restart temporarily (for debugging)pm2 stop sellf-adminpm2 start sellf-admin --no-autorestart
# Re-enable auto-restartpm2 restart sellf-adminPort Already in Use
Section titled “Port Already in Use”# Find process using port 3000sudo lsof -i :3000
# Kill processsudo kill -9 <PID>
# Or change port in ecosystem.config.js📚 Additional Resources
Section titled “📚 Additional Resources”- PM2 Docs: https://pm2.keymetrics.io/docs/usage/quick-start/
- PM2 Plus: https://app.pm2.io (monitoring)
- Ecosystem File: https://pm2.keymetrics.io/docs/usage/application-declaration/
- Cluster Mode: https://pm2.keymetrics.io/docs/usage/cluster-mode/
- Deployment: https://pm2.keymetrics.io/docs/usage/deployment/
✅ Production Checklist
Section titled “✅ Production Checklist”Before going live:
- Cluster mode enabled (
instances: "max") - Memory limits set (
max_memory_restart) - Log rotation configured
- PM2 startup script created (
pm2 startup) - Non-root user for PM2
- Firewall configured (UFW)
- Reverse proxy (Nginx/Caddy) with SSL
- Environment variables secure
- Monitoring enabled (PM2+ or custom)
- Backup strategy for logs/data
- Zero-downtime deployment tested
- Alert system configured
🆕 Performance Optimization Setup (Jan 2026)
Section titled “🆕 Performance Optimization Setup (Jan 2026)”Using ecosystem.config.js in Root Directory
Section titled “Using ecosystem.config.js in Root Directory”As of January 2026, Sellf includes a production-ready ecosystem.config.js in the root directory with optimized settings for ISR and cluster mode.
Quick Start:
# 1. Build the applicationcd admin-panelnpm installnpm run buildcd ..
# 2. Start PM2 clusterpm2 start ecosystem.config.js
# 3. Save process listpm2 save
# 4. Enable auto-start on bootpm2 startup# Follow the command output instructionsAutomated Deployment with deploy.sh:
# Make script executable (first time only)chmod +x scripts/deploy.sh
# Deploy with zero-downtime reload./scripts/deploy.shThe deploy.sh script automatically:
- Pulls latest code from git
- Installs dependencies
- Builds the application
- Reloads PM2 with zero downtime
Monitoring:
pm2 list # List all processespm2 monit # Real-time monitoringpm2 logs # View logspm2 logs --lines 100Key Configuration Features:
- ✅ Cluster mode with all CPU cores (
instances: 'max') - ✅ 512MB memory limit per instance
- ✅ Graceful shutdown (5s timeout)
- ✅ Automatic crash recovery
- ✅ Centralized logging in
./logs/
Expected Performance:
- Before ISR + Cluster: ~12 req/sec, ~3.8s latency on VPS
- After ISR + Cluster: 100-500+ req/sec, <500ms latency on VPS
Last updated: 2026-01-15 (ISR Optimization + PM2 Cluster)