← Back to Unitech/pm2

How to Deploy & Use Unitech/pm2

# PM2 Deployment & Usage Guide

Production Process Manager for Node.js/Bun applications with built-in load balancing.

## Prerequisites

- **Runtime**: Node.js 12.X+ or Bun 1.1.25+
- **Package Manager**: NPM (included with Node.js) or Bun
- **OS**: Linux (recommended), macOS, or Windows
- **Optional**: NVM or FNM for Node.js version management

## Installation

### Global Installation (Recommended)

**Via NPM:**
```bash
npm install pm2@latest -g

Via Bun:

bun install pm2 -g

Note for Bun users: If using Bun exclusively, symlink it to node:

sudo ln -s /home/$USER/.bun/bin/bun /usr/bin/node

Verify Installation

pm2 --version
pm2 list

Configuration

1. Ecosystem File (Recommended)

Create ecosystem.config.js for production-grade configuration:

module.exports = {
  apps: [{
    name: 'app-name',
    script: './app.js',
    instances: 'max',        // or -1 (all CPUs minus 1) or specific number
    exec_mode: 'cluster',    // enables load balancing
    watch: false,            // enable for development only
    max_memory_restart: '1G',
    env: {
      NODE_ENV: 'development'
    },
    env_production: {
      NODE_ENV: 'production'
    },
    log_date_format: 'YYYY-MM-DD HH:mm Z',
    error_file: './logs/err.log',
    out_file: './logs/out.log',
    merge_logs: true,
    // PM2+ monitoring (optional)
    public_key: process.env.KEYMETRICS_PUBLIC,
    secret_key: process.env.KEYMETRICS_SECRET,
    machine_name: process.env.INSTANCE_NAME
  }]
};

2. Environment Variables

  • PM2_HOME: Custom directory for PM2 logs, pids, and socket files
  • PM2_SILENT: Set to true to suppress output
  • KEYMETRICS_PUBLIC / KEYMETRICS_SECRET: For PM2+ monitoring integration
  • INSTANCE_NAME: Machine name for PM2+ dashboard

3. Generate Startup Script

Configure PM2 to start on boot:

# Detect init system and generate startup script
pm2 startup

# Save current process list
pm2 save

# Remove startup script (if needed)
pm2 unstartup

Supported init systems: systemd, upstart, launchd, rc.d

Build & Run

Basic Operations

Start an application:

# Single instance (fork mode)
pm2 start app.js

# Named process
pm2 start app.js --name "api-server"

# Cluster mode (utilize all CPUs)
pm2 start app.js -i max

# Specific instances
pm2 start app.js -i 4

# Via ecosystem file
pm2 start ecosystem.config.js

Process Management:

pm2 list                    # List all processes
pm2 stop <app_name|id|all>  # Stop process(es)
pm2 restart <app_name|id|all>
pm2 delete <app_name|id|all>
pm2 describe <id|app_name>  # Detailed metrics

Development vs Production

Development:

# Watch mode (auto-restart on file changes)
pm2 start app.js --watch --ignore-watch="node_modules"

# Tail logs
pm2 logs

Production:

# Start with production env
pm2 start ecosystem.config.js --env production

# Zero-downtime reload (for cluster mode)
pm2 reload all
pm2 reload <app_name>

# Enable host monitoring
pm2 set pm2:sysmonit true
pm2 update

Monitoring & Logs

Real-time monitoring:

pm2 monit                   # Interactive dashboard
pm2 logs                    # Stream logs
pm2 logs --json             # JSON formatted logs
pm2 logs --format           # Formatted output
pm2 logs app-name           # Specific app logs

Log Management:

pm2 flush                   # Clear all logs
pm2 reloadLogs              # Reload log files (for logrotation)

# Install log rotation module
pm2 install pm2-logrotate

Deployment

1. Docker Deployment

Use pm2-runtime as a drop-in replacement for node:

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
RUN npm install pm2 -g
COPY . .
EXPOSE 3000
CMD ["pm2-runtime", "app.js", "-i", "max"]

Or with npm scripts:

CMD ["pm2-runtime", "npm", "--", "start"]

2. Bare Metal/VM Deployment

Initial Setup:

# On server
npm install pm2 -g
pm2 startup systemd
pm2 start ecosystem.config.js --env production
pm2 save

Update Deployment:

# Zero-downtime deployment script
npm install pm2@latest -g
pm2 update
pm2 reload ecosystem.config.js --env production

3. PM2+ (Multi-Server Monitoring)

For monitoring across multiple servers:

  1. Create account at https://app.pm2.io/
  2. Link your PM2 instance:
pm2 link <secret_key> <public_key> [machine_name]

Troubleshooting

Common Issues

1. Bun Compatibility

  • Error: PM2 cannot run on Bun version < 1.1.25
  • Solution: Upgrade Bun to v1.1.25 or higher for cluster support

2. Port Already in Use

  • Error: EADDRINUSE when starting multiple instances
  • Solution: Ensure your app uses process.env.PORT or let PM2 handle port assignment in cluster mode

3. Silent Mode Not Working

  • Issue: PM2 still outputs logs despite -s or --silent
  • Solution: Place silent flags before the -- separator:
    pm2 -s start app.js -- --arg1
    

4. Environment Variables Not Updating

  • Issue: Old env vars persist after changes
  • Solution: Use --update-env flag:
    pm2 restart app --update-env
    

5. Permission Denied on Startup

  • Issue: pm2 startup fails with permission errors
  • Solution: Run the exact command provided by pm2 startup output (usually requires sudo)

6. Log Files Growing Too Large

  • Solution: Install logrotate module immediately:
    pm2 install pm2-logrotate
    

7. Process Not Starting

  • Check:
    pm2 logs <app-name>
    pm2 describe <app-name>
    
  • Verify: Interpreter path if using non-Node.js binaries (Python, Ruby, etc.)
    pm2 start script.py --interpreter python3
    

Update PM2 Safely

npm install pm2@latest -g
pm2 save          # Backup process list
pm2 update        # Seamless update (preserves running processes)

Reset Statistics

pm2 reset <app_name>        # Reset counters for specific app
pm2 reset all               # Reset all counters