elearning/.agent/workflows/deployment.md
JakkrapartXD f7330a7b27 feat: add recommended courses and quiz multiple attempts
- Add is_recommended field to Course model
- Add allow_multiple_attempts field to Quiz model
- Create RecommendedCoursesController for admin management
  - List all approved courses
  - Get course by ID
  - Toggle recommendation status
- Add is_recommended filter to CoursesService.ListCourses
- Add allow_multiple_attempts to quiz update and response types
- Update ChaptersLessonService.updateQuiz to support allow_multiple_attempts
2026-02-11 15:01:58 +07:00

6.8 KiB

description
How to deploy the backend to production

Deployment Workflow

Follow these steps to deploy the E-Learning Platform backend to production.


Prerequisites

  • Production server with Node.js 18+
  • PostgreSQL database
  • MinIO/S3 storage
  • Domain name and SSL certificate

Step 1: Prepare Production Server

# Update system
sudo apt update && sudo apt upgrade -y

# Install Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# Install PM2
sudo npm install -g pm2

# Install nginx
sudo apt install -y nginx

# Install certbot for SSL
sudo apt install -y certbot python3-certbot-nginx

Step 2: Clone Repository

# Create app directory
sudo mkdir -p /var/www/elearning-backend
sudo chown $USER:$USER /var/www/elearning-backend

# Clone repository
cd /var/www/elearning-backend
git clone <repository-url> .

Step 3: Install Dependencies

npm ci --production

Step 4: Setup Environment Variables

Create .env file:

# Application
NODE_ENV=production
PORT=4000
APP_URL=https://api.elearning.com

# Database
DATABASE_URL=postgresql://user:password@db-host:5432/elearning_prod

# MinIO/S3
S3_ENDPOINT=https://s3.elearning.com
S3_ACCESS_KEY=<access-key>
S3_SECRET_KEY=<secret-key>
S3_BUCKET_COURSES=courses
S3_BUCKET_VIDEOS=videos
S3_BUCKET_DOCUMENTS=documents
S3_BUCKET_IMAGES=images
S3_BUCKET_ATTACHMENTS=attachments

# JWT
JWT_SECRET=<strong-random-secret>
JWT_EXPIRES_IN=24h

# Email
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=<email>
SMTP_PASSWORD=<password>
SMTP_FROM=noreply@elearning.com

# CORS
CORS_ORIGIN=https://elearning.com,https://admin.elearning.com

# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100

Step 5: Run Database Migrations

npx prisma migrate deploy

Step 6: Setup PM2

Create ecosystem.config.js:

module.exports = {
  apps: [{
    name: 'elearning-backend',
    script: './src/server.js',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production'
    },
    error_file: './logs/err.log',
    out_file: './logs/out.log',
    log_file: './logs/combined.log',
    time: true
  }]
};

Start application:

pm2 start ecosystem.config.js
pm2 save
pm2 startup

Step 7: Configure Nginx

Create /etc/nginx/sites-available/elearning-backend:

upstream backend {
    server localhost:4000;
}

server {
    listen 80;
    server_name api.elearning.com;

    # Redirect to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name api.elearning.com;

    # SSL Configuration
    ssl_certificate /etc/letsencrypt/live/api.elearning.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.elearning.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # 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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Logging
    access_log /var/log/nginx/elearning-backend-access.log;
    error_log /var/log/nginx/elearning-backend-error.log;

    # File Upload Size
    client_max_body_size 500M;

    location / {
        proxy_pass http://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;
        
        # Timeouts
        proxy_connect_timeout 600s;
        proxy_send_timeout 600s;
        proxy_read_timeout 600s;
    }
}

Enable site:

sudo ln -s /etc/nginx/sites-available/elearning-backend /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Step 8: Setup SSL Certificate

sudo certbot --nginx -d api.elearning.com

Step 9: Setup Monitoring

PM2 Monitoring

pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 30

Health Check Endpoint

Add to your app:

app.get('/health', (req, res) => {
  res.status(200).json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime()
  });
});

Step 10: Setup Backup

Create backup script /opt/scripts/backup-db.sh:

#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backups/elearning"
DB_NAME="elearning_prod"

mkdir -p $BACKUP_DIR

# Backup database
pg_dump $DB_NAME | gzip > $BACKUP_DIR/db_$DATE.sql.gz

# Keep only last 7 days
find $BACKUP_DIR -name "db_*.sql.gz" -mtime +7 -delete

echo "Backup completed: db_$DATE.sql.gz"

Add to crontab:

# Daily backup at 2 AM
0 2 * * * /opt/scripts/backup-db.sh

Step 11: Verify Deployment

# Check PM2 status
pm2 status

# Check logs
pm2 logs elearning-backend --lines 50

# Test health endpoint
curl https://api.elearning.com/health

# Test API
curl https://api.elearning.com/api/courses

Update Deployment

# Pull latest code
cd /var/www/elearning-backend
git pull origin main

# Install dependencies
npm ci --production

# Run migrations
npx prisma migrate deploy

# Restart application
pm2 restart elearning-backend

# Check status
pm2 status

Rollback

# Revert to previous commit
git reset --hard HEAD~1

# Reinstall dependencies
npm ci --production

# Rollback migration (if needed)
npx prisma migrate resolve --rolled-back <migration-name>

# Restart
pm2 restart elearning-backend

Checklist

  • Production server setup
  • Repository cloned
  • Dependencies installed
  • Environment variables configured
  • Database migrated
  • PM2 configured and running
  • Nginx configured
  • SSL certificate installed
  • Monitoring setup
  • Backup script configured
  • Health check working
  • API endpoints tested

Security Checklist

  • Strong JWT secret
  • Database credentials secured
  • CORS configured correctly
  • Rate limiting enabled
  • SSL/TLS enabled
  • Security headers configured
  • File upload limits set
  • Environment variables not in git
  • Firewall configured
  • SSH key-based authentication

Monitoring

PM2 Commands

# View logs
pm2 logs

# Monitor resources
pm2 monit

# Restart app
pm2 restart elearning-backend

# Stop app
pm2 stop elearning-backend

# Delete app
pm2 delete elearning-backend

Check System Resources

# CPU and Memory
htop

# Disk usage
df -h

# Network connections
netstat -tulpn