Staging Environment Setup with PM2¶
Complete guide for deploying the MMR SaaS Platform to a staging server using PM2 process manager (without Docker).
Table of Contents¶
- Overview
- Server Prerequisites
- Installing Dependencies
- Application Setup
- PM2 Process Management
- NGINX Configuration
- Database Configuration
- Security Hardening
- Monitoring
- Backup Strategies
- Deployment Workflow
- Troubleshooting
Overview¶
This guide covers deploying to a staging environment using: - PM2: Process manager for Node.js applications - NGINX: Reverse proxy and web server - MySQL: Database server - Redis: Caching and session storage - Let's Encrypt: Free SSL certificates
Target Environment: Ubuntu 22.04 LTS (also works on 20.04, Debian 11+)
Server Prerequisites¶
Minimum Specifications¶
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 4 GB | 8 GB |
| Storage | 40 GB SSD | 80 GB SSD |
| Bandwidth | 100 Mbps | 1 Gbps |
Required Access¶
- Root or sudo access
- SSH key authentication (recommended)
- Firewall control (UFW or similar)
- Domain name with DNS control
Supported OS¶
- Ubuntu 22.04 LTS (recommended)
- Ubuntu 20.04 LTS
- Debian 11+
Installing Dependencies¶
1. Update System Packages¶
# Connect to server
ssh user@your-server-ip
# Update package lists
sudo apt update
# Upgrade installed packages
sudo apt upgrade -y
# Install essential tools
sudo apt install -y curl wget git build-essential
2. Install Node.js 18.x¶
# Add NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
# Install Node.js
sudo apt install -y nodejs
# Verify installation
node --version # Should show v18.x.x
npm --version # Should show 9.x.x or higher
3. Install PNPM¶
# Install PNPM globally
npm install -g pnpm
# Verify installation
pnpm --version # Should show 8.x.x or higher
4. Install PM2¶
# Install PM2 globally
npm install -g pm2
# Verify installation
pm2 --version
# Setup PM2 startup script (runs on server reboot)
pm2 startup
# Follow the command it outputs (sudo env PATH=...)
# Save PM2 process list
pm2 save
5. Install MySQL 8.x¶
# Install MySQL Server
sudo apt install -y mysql-server
# Secure MySQL installation
sudo mysql_secure_installation
# Follow prompts:
# - Set root password
# - Remove anonymous users: Yes
# - Disallow root login remotely: Yes
# - Remove test database: Yes
# - Reload privilege tables: Yes
# Verify installation
sudo systemctl status mysql
mysql --version # Should show 8.0.x
6. Install Redis 7.x¶
# Install Redis
sudo apt install -y redis-server
# Enable Redis to start on boot
sudo systemctl enable redis-server
# Start Redis
sudo systemctl start redis-server
# Verify installation
redis-cli ping # Should return "PONG"
7. Install NGINX¶
# Install NGINX
sudo apt install -y nginx
# Enable NGINX to start on boot
sudo systemctl enable nginx
# Start NGINX
sudo systemctl start nginx
# Verify installation
sudo systemctl status nginx
nginx -v # Should show nginx version
# Test NGINX
curl http://localhost # Should show NGINX welcome page
Application Setup¶
1. Create Application User¶
# Create user without login shell (security)
sudo useradd -r -s /bin/false mmr-app
# Or create user with bash (for debugging)
sudo useradd -m -s /bin/bash mmr-app
# Switch to application user
sudo su - mmr-app
2. Clone Repository¶
# Navigate to home directory
cd ~
# Clone repository (use HTTPS or SSH)
git clone <repository-url> mmr-saas
cd mmr-saas
# Checkout specific branch/tag
git checkout main # or develop for staging
3. Install Dependencies¶
4. Configure Environment Variables¶
Backend Environment¶
# Create .env file from example
cp apps/backend/.env.example apps/backend/.env
# Edit environment file
nano apps/backend/.env
Backend .env Configuration:
# Server Configuration
NODE_ENV=staging
PORT=3001
API_PREFIX=api
# Database
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=mmr_user
DB_PASSWORD=your-secure-database-password
DB_NAME=mmr_saas_staging
DB_SYNCHRONIZE=false # Always false in production/staging
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD= # Leave empty if no password
# JWT Secrets (generate strong secrets)
# Generate with: node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
JWT_SECRET=your-super-secret-jwt-key-64-characters-or-more
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=your-super-secret-refresh-key-64-characters-or-more
JWT_REFRESH_EXPIRY=7d
# CORS
CORS_ORIGIN=https://staging.yourdomain.com
# Rate Limiting
RATE_LIMIT_LOGIN_ATTEMPTS=5
RATE_LIMIT_LOCKOUT_MINUTES=15
# Logging
LOG_LEVEL=info # debug | info | warn | error
Frontend Environment¶
# Create .env.local file
cp apps/web/.env.example apps/web/.env.local
# Edit environment file
nano apps/web/.env.local
Frontend .env.local Configuration:
# Backend API URL
NEXT_PUBLIC_API_URL=https://api.staging.yourdomain.com
# Environment
NEXT_PUBLIC_ENV=staging
# Analytics (optional)
NEXT_PUBLIC_GA_ID= # Google Analytics ID
5. Setup Database¶
# Login to MySQL
mysql -u root -p
# Create database
CREATE DATABASE mmr_saas_staging CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# Create user with strong password
CREATE USER 'mmr_user'@'localhost' IDENTIFIED BY 'your-secure-database-password';
# Grant privileges
GRANT ALL PRIVILEGES ON mmr_saas_staging.* TO 'mmr_user'@'localhost';
FLUSH PRIVILEGES;
# Exit MySQL
EXIT;
# Test connection
mysql -u mmr_user -p mmr_saas_staging
6. Run Database Migrations¶
# Navigate to project directory
cd ~/mmr-saas
# Run migrations
pnpm db:migrate
# Verify migrations
pnpm migration:show
# (Optional) Seed test data for staging
pnpm db:seed
7. Build Applications¶
# Build both frontend and backend
pnpm build
# Or build separately
pnpm build:back # Backend only
pnpm build:web # Frontend only
# Verify build output
ls -la apps/backend/dist
ls -la apps/web/.next
PM2 Process Management¶
1. Create PM2 Ecosystem Config¶
Create ecosystem.config.js in project root:
ecosystem.config.js:
module.exports = {
apps: [
{
name: 'mmr-backend',
cwd: '/home/mmr-app/mmr-saas/apps/backend',
script: 'dist/main.js',
instances: 2, // Number of instances (CPU cores)
exec_mode: 'cluster',
env: {
NODE_ENV: 'staging',
PORT: 3001,
},
error_file: '/home/mmr-app/logs/backend-error.log',
out_file: '/home/mmr-app/logs/backend-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
autorestart: true,
max_memory_restart: '1G',
watch: false,
},
{
name: 'mmr-frontend',
cwd: '/home/mmr-app/mmr-saas/apps/web',
script: 'node_modules/next/dist/bin/next',
args: 'start -p 3000',
instances: 1,
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000,
},
error_file: '/home/mmr-app/logs/frontend-error.log',
out_file: '/home/mmr-app/logs/frontend-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
autorestart: true,
max_memory_restart: '1G',
watch: false,
},
],
};
2. Create Log Directory¶
3. Start Applications with PM2¶
# Start all applications
pm2 start ecosystem.config.js
# Or start individually
pm2 start ecosystem.config.js --only mmr-backend
pm2 start ecosystem.config.js --only mmr-frontend
# View running processes
pm2 list
# View logs
pm2 logs
# View logs for specific app
pm2 logs mmr-backend
pm2 logs mmr-frontend --lines 100
# Monitor processes
pm2 monit
4. PM2 Commands Reference¶
# Process Management
pm2 start ecosystem.config.js # Start all apps
pm2 stop all # Stop all apps
pm2 restart all # Restart all apps
pm2 reload all # Graceful reload (zero downtime)
pm2 delete all # Delete all apps
# Individual App Control
pm2 stop mmr-backend
pm2 restart mmr-backend
pm2 reload mmr-backend
# Logs
pm2 logs # All logs (live tail)
pm2 logs mmr-backend --lines 200 # Last 200 lines
pm2 logs --err # Error logs only
pm2 flush # Clear logs
# Monitoring
pm2 monit # Real-time monitoring
pm2 status # Process status
pm2 describe mmr-backend # Detailed info
# Startup
pm2 startup # Generate startup script
pm2 save # Save current process list
pm2 resurrect # Restore saved processes
# Updates
pm2 update # Update PM2 daemon
NGINX Configuration¶
1. Create NGINX Configuration File¶
NGINX Configuration:
# Upstream definitions
upstream mmr_backend {
least_conn; # Load balancing method
server localhost:3001;
# Add more backend instances if using multiple servers
# server localhost:3002;
}
upstream mmr_frontend {
server localhost:3000;
}
# Redirect HTTP to HTTPS (will be uncommented after SSL setup)
# server {
# listen 80;
# listen [::]:80;
# server_name staging.yourdomain.com api.staging.yourdomain.com;
# return 301 https://$server_name$request_uri;
# }
# Frontend Server (HTTPS)
server {
listen 80;
# listen 443 ssl http2; # Uncomment after SSL setup
# listen [::]:443 ssl http2;
server_name staging.yourdomain.com;
# SSL Configuration (uncomment after certbot)
# ssl_certificate /etc/letsencrypt/live/staging.yourdomain.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/staging.yourdomain.com/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Logging
access_log /var/log/nginx/mmr-frontend-access.log;
error_log /var/log/nginx/mmr-frontend-error.log;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;
# Proxy to Next.js
location / {
proxy_pass http://mmr_frontend;
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;
proxy_connect_timeout 60s;
}
# Static files caching
location /_next/static {
proxy_pass http://mmr_frontend;
proxy_cache_valid 200 60m;
add_header Cache-Control "public, max-age=3600, immutable";
}
}
# Backend API Server (HTTPS)
server {
listen 80;
# listen 443 ssl http2; # Uncomment after SSL setup
# listen [::]:443 ssl http2;
server_name api.staging.yourdomain.com;
# SSL Configuration (uncomment after certbot)
# ssl_certificate /etc/letsencrypt/live/api.staging.yourdomain.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/api.staging.yourdomain.com/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# 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;
# Logging
access_log /var/log/nginx/mmr-backend-access.log;
error_log /var/log/nginx/mmr-backend-error.log;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_types application/json text/plain;
# Proxy to NestJS Backend
location / {
proxy_pass http://mmr_backend;
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 300s;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
# CORS headers (if needed)
# add_header 'Access-Control-Allow-Origin' 'https://staging.yourdomain.com' always;
# add_header 'Access-Control-Allow-Credentials' 'true' always;
# add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;
}
# Health check endpoint (public)
location /health {
proxy_pass http://mmr_backend/api/health;
access_log off;
}
}
2. Enable Site and Test Configuration¶
# Create symbolic link to enable site
sudo ln -s /etc/nginx/sites-available/mmr-saas /etc/nginx/sites-enabled/
# Remove default site (optional)
sudo rm /etc/nginx/sites-enabled/default
# Test NGINX configuration
sudo nginx -t
# If test passes, reload NGINX
sudo systemctl reload nginx
3. Configure DNS¶
Point your domain to the server:
A Record: staging.yourdomain.com → your-server-ip
A Record: api.staging.yourdomain.com → your-server-ip
Wait for DNS propagation (5-30 minutes).
4. Install SSL Certificate (Let's Encrypt)¶
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
# Obtain SSL certificates
sudo certbot --nginx -d staging.yourdomain.com -d api.staging.yourdomain.com
# Follow prompts:
# - Enter email address
# - Agree to terms
# - Choose: Redirect HTTP to HTTPS (option 2)
# Certbot will automatically update NGINX config
# Test auto-renewal
sudo certbot renew --dry-run
# Auto-renewal is already configured via systemd timer
sudo systemctl status certbot.timer
5. Verify SSL¶
# Test HTTPS
curl https://staging.yourdomain.com
curl https://api.staging.yourdomain.com/api/health
# Check SSL certificate
openssl s_client -connect staging.yourdomain.com:443 -showcerts
Database Configuration¶
1. MySQL Performance Tuning¶
Add/Update:
[mysqld]
# Performance tuning
max_connections = 200
innodb_buffer_pool_size = 2G # 50-70% of RAM
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
query_cache_size = 0
query_cache_type = 0
# Logging
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2
2. Database Backups¶
Create backup script:
backup-db.sh:
#!/bin/bash
BACKUP_DIR="/home/mmr-app/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mmr_saas_staging"
DB_USER="mmr_user"
DB_PASS="your-secure-database-password"
# Create backup directory
mkdir -p $BACKUP_DIR
# Dump database
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/mmr_saas_$DATE.sql.gz
# Keep only last 7 days of backups
find $BACKUP_DIR -name "*.sql.gz" -type f -mtime +7 -delete
echo "Backup completed: $BACKUP_DIR/mmr_saas_$DATE.sql.gz"
# Make executable
chmod +x ~/backup-db.sh
# Test backup
./backup-db.sh
# Schedule daily backups (cron)
crontab -e
# Add line:
0 2 * * * /home/mmr-app/backup-db.sh >> /home/mmr-app/logs/backup.log 2>&1
Security Hardening¶
1. Firewall (UFW)¶
# Install UFW
sudo apt install -y ufw
# Allow SSH (IMPORTANT: Do this first!)
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable firewall
sudo ufw enable
# Check status
sudo ufw status verbose
# Application will be accessible only via NGINX (ports 80/443)
# PM2 apps (3000, 3001) are not exposed directly
2. Fail2Ban (Brute Force Protection)¶
# Install Fail2Ban
sudo apt install -y fail2ban
# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Edit configuration
sudo nano /etc/fail2ban/jail.local
Add NGINX protection:
[nginx-http-auth]
enabled = true
[nginx-limit-req]
enabled = true
port = http,https
logpath = /var/log/nginx/*error.log
[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/*access.log
3. SSH Hardening¶
Recommended changes:
# Disable root login
PermitRootLogin no
# Use SSH keys only (disable password auth)
PasswordAuthentication no
ChallengeResponseAuthentication no
# Change default port (optional)
Port 2222
# Allow specific users only
AllowUsers mmr-app yourusername
# Restart SSH
sudo systemctl restart sshd
# IMPORTANT: Test new SSH connection in another terminal before closing current session!
4. Automatic Security Updates¶
# Install unattended-upgrades
sudo apt install -y unattended-upgrades
# Enable automatic updates
sudo dpkg-reconfigure -plow unattended-upgrades
# Select "Yes" to enable
Monitoring¶
1. PM2 Monitoring¶
# Real-time monitoring
pm2 monit
# Process status
pm2 status
# Detailed app info
pm2 describe mmr-backend
# System info
pm2 info
# View logs
pm2 logs --lines 100
2. Application Logs¶
# Backend logs
tail -f /home/mmr-app/logs/backend-out.log
tail -f /home/mmr-app/logs/backend-error.log
# Frontend logs
tail -f /home/mmr-app/logs/frontend-out.log
# NGINX logs
sudo tail -f /var/log/nginx/mmr-backend-access.log
sudo tail -f /var/log/nginx/mmr-frontend-error.log
3. System Monitoring¶
# Install htop (better than top)
sudo apt install -y htop
# Monitor system resources
htop
# Disk usage
df -h
# Memory usage
free -h
# Process tree
pstree -p
# Network connections
netstat -tulpn
# Or use ss
ss -tulpn
4. Health Checks¶
Create health check script:
health-check.sh:
#!/bin/bash
# Check backend health
BACKEND=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3001/api/health)
if [ "$BACKEND" -eq 200 ]; then
echo "Backend: OK"
else
echo "Backend: FAILED (HTTP $BACKEND)"
# Restart backend
pm2 restart mmr-backend
fi
# Check frontend
FRONTEND=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000)
if [ "$FRONTEND" -eq 200 ] || [ "$FRONTEND" -eq 304 ]; then
echo "Frontend: OK"
else
echo "Frontend: FAILED (HTTP $FRONTEND)"
# Restart frontend
pm2 restart mmr-frontend
fi
# Check MySQL
if mysqladmin ping -u mmr_user -pyour-password &> /dev/null; then
echo "MySQL: OK"
else
echo "MySQL: FAILED"
sudo systemctl restart mysql
fi
# Check Redis
if redis-cli ping &> /dev/null; then
echo "Redis: OK"
else
echo "Redis: FAILED"
sudo systemctl restart redis-server
fi
# Make executable
chmod +x ~/health-check.sh
# Schedule every 5 minutes (cron)
crontab -e
# Add line:
*/5 * * * * /home/mmr-app/health-check.sh >> /home/mmr-app/logs/health.log 2>&1
Backup Strategies¶
1. Database Backups¶
Already configured in Database Configuration section.
2. Application File Backups¶
# Create backup directory
mkdir -p ~/backups/files
# Backup entire application (excluding node_modules)
tar --exclude='node_modules' --exclude='.git' \
-czf ~/backups/files/mmr-saas-$(date +%Y%m%d).tar.gz \
~/mmr-saas
# Automate (add to cron)
crontab -e
# Add line (daily at 3 AM):
0 3 * * * tar --exclude='node_modules' --exclude='.git' -czf ~/backups/files/mmr-saas-$(date +\%Y\%m\%d).tar.gz ~/mmr-saas
3. Off-Site Backups¶
# Install rclone for cloud backups
curl https://rclone.org/install.sh | sudo bash
# Configure rclone (AWS S3, Google Drive, etc.)
rclone config
# Sync backups to cloud
rclone sync ~/backups remote:mmr-backups
# Automate (add to cron)
0 4 * * * rclone sync ~/backups remote:mmr-backups
Deployment Workflow¶
Deploying Updates¶
# 1. SSH to server
ssh mmr-app@your-server-ip
# 2. Navigate to project
cd ~/mmr-saas
# 3. Pull latest code
git pull origin main # or develop for staging
# 4. Install new dependencies (if any)
pnpm install
# 5. Run database migrations (if any)
pnpm db:migrate
# 6. Build applications
pnpm build
# 7. Reload PM2 processes (zero downtime)
pm2 reload all
# 8. Verify deployment
curl http://localhost:3001/api/health
curl http://localhost:3000
# 9. Check logs
pm2 logs --lines 50
Rollback Procedure¶
# 1. Find previous commit
git log --oneline -5
# 2. Revert to previous commit
git reset --hard <previous-commit-hash>
# 3. Rebuild
pnpm build
# 4. Reload PM2
pm2 reload all
# Or use git revert for safer rollback
git revert <bad-commit-hash>
pnpm build
pm2 reload all
Troubleshooting¶
PM2 Process Not Starting¶
# Check PM2 logs
pm2 logs mmr-backend --err --lines 100
# Check if port is in use
sudo lsof -i :3001
sudo lsof -i :3000
# Kill process using port
sudo kill -9 <PID>
# Restart PM2
pm2 delete all
pm2 start ecosystem.config.js
Database Connection Errors¶
# Check MySQL is running
sudo systemctl status mysql
# Check connection
mysql -u mmr_user -p mmr_saas_staging
# Check credentials in .env
cat apps/backend/.env | grep DB_
# Check MySQL logs
sudo tail -f /var/log/mysql/error.log
NGINX Configuration Errors¶
# Test configuration
sudo nginx -t
# Check syntax errors
sudo nginx -T
# Reload NGINX
sudo systemctl reload nginx
# Check NGINX logs
sudo tail -f /var/log/nginx/error.log
SSL Certificate Issues¶
# Test certificate renewal
sudo certbot renew --dry-run
# Force renewal
sudo certbot renew --force-renewal
# Check certificate expiry
sudo certbot certificates
# NGINX reload after renewal
sudo systemctl reload nginx
Out of Memory Errors¶
# Check memory usage
free -h
# Check PM2 memory limits
pm2 list
# Adjust PM2 memory limit in ecosystem.config.js
max_memory_restart: '2G' # Increase from 1G
# Add swap space (if needed)
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Make swap permanent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
High CPU Usage¶
# Check processes
htop
# Check PM2 CPU usage
pm2 monit
# Reduce PM2 instances
# Edit ecosystem.config.js: instances: 1
# Optimize Node.js
# Add to ecosystem.config.js:
node_args: '--max-old-space-size=2048'
Redis Connection Errors¶
# Check Redis is running
sudo systemctl status redis-server
# Test connection
redis-cli ping
# Check Redis logs
sudo tail -f /var/log/redis/redis-server.log
# Restart Redis
sudo systemctl restart redis-server
Quick Reference¶
Common PM2 Commands¶
pm2 start ecosystem.config.js # Start all apps
pm2 reload all # Zero-downtime reload
pm2 restart all # Hard restart
pm2 stop all # Stop all apps
pm2 logs # View logs
pm2 monit # Monitor
pm2 save # Save process list
Common NGINX Commands¶
sudo nginx -t # Test config
sudo systemctl reload nginx # Reload config
sudo systemctl restart nginx # Restart NGINX
sudo tail -f /var/log/nginx/error.log # View logs
Common MySQL Commands¶
sudo systemctl status mysql # Check status
mysql -u mmr_user -p # Login
sudo tail -f /var/log/mysql/error.log # View logs
Version: 2.0.0 | Last Updated: 2026-06-20