# PM2 Management Guide Complete guide for managing the Redmine-Gitea Sync Server with PM2. ## Quick Start ### Install PM2 ```bash npm install -g pm2 ``` ### Start Application ```bash pm2 start ecosystem.config.cjs pm2 save pm2 startup ``` ## Essential Commands ### Process Management ```bash # Start the application pm2 start ecosystem.config.cjs # Start in development mode pm2 start ecosystem.config.cjs --env development # Stop the application pm2 stop redmine-gitea-sync # Restart the application pm2 restart redmine-gitea-sync # Reload with zero downtime (cluster mode) pm2 reload redmine-gitea-sync # Delete from PM2 pm2 delete redmine-gitea-sync # Update environment variables and restart pm2 restart redmine-gitea-sync --update-env ``` ### Monitoring ```bash # List all processes pm2 list pm2 ls # Show detailed information pm2 show redmine-gitea-sync # Monitor in real-time pm2 monit # View resource usage pm2 status ``` ### Log Management ```bash # View logs in real-time pm2 logs redmine-gitea-sync # View last 100 lines pm2 logs redmine-gitea-sync --lines 100 # View only errors pm2 logs redmine-gitea-sync --err # View only output pm2 logs redmine-gitea-sync --out # Clear logs pm2 flush # Follow logs with grep pm2 logs redmine-gitea-sync | grep ERROR ``` ### Save and Restore ```bash # Save current process list pm2 save # Resurrect saved process list pm2 resurrect # Clear saved process list pm2 cleardump ``` ## Configuration ### Ecosystem File The `ecosystem.config.cjs` file contains all configuration: ```javascript module.exports = { apps: [{ name: 'redmine-gitea-sync', script: './server.mjs', env: { // Your environment variables }, instances: 1, exec_mode: 'fork', max_memory_restart: '300M', // ... other settings }] }; ``` ### Update Configuration 1. Edit `ecosystem.config.cjs` 2. Restart with updated environment: ```bash pm2 restart redmine-gitea-sync --update-env ``` ### Multiple Environments ```javascript // ecosystem.config.cjs module.exports = { apps: [{ name: 'redmine-gitea-sync', script: './server.mjs', env: { NODE_ENV: 'production', PORT: 3002, }, env_development: { NODE_ENV: 'development', PORT: 3002, LOG_LEVEL: 'debug', }, env_staging: { NODE_ENV: 'staging', PORT: 3003, } }] }; ``` Start with specific environment: ```bash pm2 start ecosystem.config.cjs --env development pm2 start ecosystem.config.cjs --env staging ``` ## Auto-Start on Boot ### Setup Startup Script ```bash # Generate startup script for your system pm2 startup # This will output a command like: # sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u yourusername --hp /home/yourusername # Run the command it outputs sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u yourusername --hp /home/yourusername # Save your process list pm2 save ``` ### Disable Startup ```bash pm2 unstartup ``` ## Clustering For high-traffic scenarios, use cluster mode: ### Update ecosystem.config.cjs ```javascript module.exports = { apps: [{ name: 'redmine-gitea-sync', script: './server.mjs', instances: 'max', // or specific number like 4 exec_mode: 'cluster', // ... other settings }] }; ``` ### Commands ```bash # Start in cluster mode pm2 start ecosystem.config.cjs # Scale up/down pm2 scale redmine-gitea-sync +2 # Add 2 instances pm2 scale redmine-gitea-sync 4 # Set to 4 instances # Reload with zero downtime pm2 reload redmine-gitea-sync ``` ## Log Rotation ### Install PM2 Log Rotate Module ```bash pm2 install pm2-logrotate ``` ### Configure Log Rotation ```bash # Set max file size (default: 10MB) pm2 set pm2-logrotate:max_size 10M # Set number of files to keep (default: 10) pm2 set pm2-logrotate:retain 7 # Enable compression pm2 set pm2-logrotate:compress true # Set rotation interval (daily/hourly) pm2 set pm2-logrotate:rotateInterval '0 0 * * *' # Daily at midnight # View configuration pm2 conf pm2-logrotate ``` ## Monitoring and Metrics ### PM2 Plus (Optional) PM2 Plus provides advanced monitoring: ```bash # Link to PM2 Plus pm2 link # Unlink pm2 unlink ``` ### Custom Metrics Add to your application: ```javascript const pmx = require('pmx'); // Custom metric const metric = pmx.probe().metric({ name: 'Sync Operations', value: 0 }); // Increment metric.set(metric.val() + 1); ``` ### System Monitoring ```bash # Install system monitoring module pm2 install pm2-server-monit # View dashboard # Access via http://localhost:9615 ``` ## Troubleshooting ### Process Keeps Restarting ```bash # Check error logs pm2 logs redmine-gitea-sync --err # View restart count pm2 list # Increase restart delay in ecosystem.config.cjs restart_delay: 5000, max_restarts: 5, ``` ### High Memory Usage ```bash # Check memory pm2 list pm2 monit # View detailed info pm2 show redmine-gitea-sync # Adjust memory limit in ecosystem.config.cjs max_memory_restart: '500M', ``` ### Application Not Starting ```bash # Check if port is in use sudo lsof -i :3002 # Check logs for errors pm2 logs redmine-gitea-sync --err --lines 50 # Try starting manually to see errors node server.js ``` ### PM2 Not Starting on Boot ```bash # Verify startup is configured pm2 startup # Check systemd status systemctl status pm2-yourusername # Regenerate startup script pm2 unstartup pm2 startup pm2 save ``` ### Logs Not Appearing ```bash # Check log file locations pm2 show redmine-gitea-sync # Verify log directory exists and is writable ls -la ./logs/ # Create logs directory if missing mkdir -p ./logs # Restart application pm2 restart redmine-gitea-sync ``` ## Advanced Usage ### Watch Mode Monitor file changes and auto-restart: ```javascript // ecosystem.config.cjs watch: true, watch_delay: 1000, ignore_watch: ['node_modules', 'logs', '.git'], ``` Or from command line: ```bash pm2 start ecosystem.config.cjs --watch ``` ### Cron Restart Restart at specific intervals: ```javascript // ecosystem.config.cjs cron_restart: '0 3 * * *', // Every day at 3 AM ``` ### Max Restarts Limit restart attempts: ```javascript // ecosystem.config.cjs max_restarts: 10, min_uptime: '10s', ``` ### Environment-Specific Commands ```bash # Production pm2 start ecosystem.config.cjs --env production # Development pm2 start ecosystem.config.cjs --env development # Staging pm2 start ecosystem.config.cjs --env staging ``` ## PM2 Runtime Configuration ### Update PM2 ```bash # Update PM2 to latest version npm install -g pm2@latest # Update in-memory PM2 pm2 update ``` ### PM2 Home Directory By default: `~/.pm2` Change location: ```bash export PM2_HOME=/path/to/custom/location ``` ### Reset PM2 ```bash # Kill PM2 daemon pm2 kill # Clear everything rm -rf ~/.pm2 # Restart PM2 pm2 start ecosystem.config.cjs ``` ## Integration with CI/CD ### Deploy Script Example ```bash #!/bin/bash # Pull latest code git pull origin main # Install dependencies npm install --production # Restart with zero downtime pm2 reload ecosystem.config.cjs # Check if running pm2 list ``` ### GitHub Actions Example ```yaml name: Deploy on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Deploy to server uses: appleboy/ssh-action@master with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} key: ${{ secrets.SSH_KEY }} script: | cd /opt/redmine-gitea-sync git pull npm install --production pm2 reload ecosystem.config.cjs ``` ## Performance Tuning ### Node.js Options ```javascript // ecosystem.config.cjs node_args: '--max-old-space-size=2048', ``` ### Increase File Descriptors ```bash # Check current limit ulimit -n # Increase limit (temporary) ulimit -n 10000 # Permanent: Edit /etc/security/limits.conf * soft nofile 10000 * hard nofile 10000 ``` ### Process Priority ```bash # Start with higher priority (lower nice value) pm2 start ecosystem.config.cjs --node-args="--nice=-10" ``` ## Backup and Restore ### Backup PM2 Configuration ```bash # Backup process list pm2 save # Backup ecosystem file cp ecosystem.config.cjs ecosystem.config.cjs.backup # Backup PM2 directory tar -czf pm2-backup.tar.gz ~/.pm2 ``` ### Restore ```bash # Restore PM2 directory tar -xzf pm2-backup.tar.gz -C ~/ # Resurrect processes pm2 resurrect ``` ## Security Best Practices ### Run as Dedicated User ```bash # Create user sudo useradd -r -s /bin/false pm2user # Set ownership sudo chown -R pm2user:pm2user /opt/redmine-gitea-sync # Run PM2 as user sudo su - pm2user -s /bin/bash -c "pm2 start /opt/redmine-gitea-sync/ecosystem.config.cjs" sudo su - pm2user -s /bin/bash -c "pm2 save" # Setup startup as that user sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u pm2user --hp /home/pm2user ``` ### Secure Environment Variables Never commit sensitive data to version control: ```bash # Protect ecosystem file chmod 600 ecosystem.config.cjs # Use external .env file # In ecosystem.config.cjs: require('dotenv').config(); env: { REDMINE_API_KEY: process.env.REDMINE_API_KEY, GITEA_TOKEN: process.env.GITEA_TOKEN, } ``` ## Quick Reference ### Most Common Commands ```bash # Start pm2 start ecosystem.config.cjs # Status pm2 list # Logs pm2 logs # Restart pm2 restart redmine-gitea-sync # Stop pm2 stop redmine-gitea-sync # Monitor pm2 monit # Save pm2 save ``` ### Useful Aliases Add to `~/.bashrc`: ```bash alias pm2-status='pm2 list' alias pm2-logs='pm2 logs redmine-gitea-sync' alias pm2-restart='pm2 restart redmine-gitea-sync' alias pm2-sync='cd /opt/redmine-gitea-sync && pm2 logs redmine-gitea-sync' ``` ## Additional Resources - [PM2 Official Documentation](https://pm2.keymetrics.io/) - [PM2 GitHub Repository](https://github.com/Unitech/pm2) - [PM2 Plus (Monitoring)](https://pm2.io/) - [PM2 Cheat Sheet](https://pm2.keymetrics.io/docs/usage/quick-start/) ## Support For PM2-specific issues: - Check PM2 logs: `pm2 logs` - Consult PM2 documentation - Search PM2 GitHub issues For application issues: - Check application logs: `pm2 logs redmine-gitea-sync` - Review main documentation - Check server health: `curl http://localhost:3002/health`