Files
easystream-main/docs/DEPLOYMENT.md
SamiAhmed7777 0b7e2d0a5b feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory
- Added PROJECT_OVERVIEW.md with feature highlights and getting started guide
- Added ARCHITECTURE.md with system design and technical details
- Added SECURITY.md with comprehensive security implementation guide
- Added DEVELOPMENT.md with development workflows and best practices
- Added DEPLOYMENT.md with production deployment instructions
- Added API.md with complete REST API documentation
- Added CONTRIBUTING.md with contribution guidelines
- Added CHANGELOG.md with version history and migration notes
- Reorganized all documentation files into docs/ directory for better organization
- Updated README.md with proper documentation links and quick navigation
- Enhanced project structure with professional documentation standards
2025-10-21 00:39:45 -07:00

15 KiB

Deployment Guide

This guide covers various deployment scenarios for EasyStream, from development to production environments.

Quick Start (Docker)

Prerequisites

  • Docker 20.10+
  • Docker Compose 2.0+
  • 4GB+ RAM
  • 20GB+ storage

Basic Deployment

# Clone repository
git clone <repository-url>
cd easystream

# Configure environment
cp .env.example .env
# Edit .env with your settings

# Start services
docker-compose up -d --build

# Verify deployment
curl http://localhost:8083

Production Deployment

System Requirements

Minimum Requirements

  • CPU: 2 cores
  • RAM: 4GB
  • Storage: 50GB SSD
  • Network: 100Mbps
  • CPU: 4+ cores
  • RAM: 8GB+
  • Storage: 200GB+ SSD
  • Network: 1Gbps

Environment Configuration

Environment Variables

# Application
MAIN_URL=https://your-domain.com
DEBUG_MODE=false
ENVIRONMENT=production

# Database
DB_HOST=db
DB_NAME=easystream
DB_USER=easystream
DB_PASS=secure_password_here

# Security
SESSION_SECURE=true
CSRF_PROTECTION=enabled
RATE_LIMITING=enabled

# Storage
UPLOAD_MAX_SIZE=2G
STORAGE_DRIVER=local
# For S3: STORAGE_DRIVER=s3
# AWS_ACCESS_KEY_ID=your_key
# AWS_SECRET_ACCESS_KEY=your_secret
# AWS_DEFAULT_REGION=us-east-1
# AWS_BUCKET=your-bucket

# Email
MAIL_DRIVER=smtp
MAIL_HOST=smtp.your-provider.com
MAIL_PORT=587
MAIL_USERNAME=your_email@domain.com
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls

# Live Streaming
SRS_RTMP_PORT=1935
SRS_HTTP_PORT=8080
HLS_SEGMENT_DURATION=10
HLS_WINDOW_SIZE=60

# Monitoring
LOG_LEVEL=warning
LOG_DRIVER=file
# For centralized logging: LOG_DRIVER=syslog

Docker Production Setup

Production Docker Compose

# docker-compose.prod.yml
version: '3.8'

services:
  php:
    build:
      context: .
      dockerfile: Dockerfile.php
      target: production
    environment:
      - ENVIRONMENT=production
      - DEBUG_MODE=false
    volumes:
      - ./f_data:/var/www/html/f_data
      - uploads:/var/www/html/f_data/uploads
      - hls:/var/www/html/hls
    restart: unless-stopped
    depends_on:
      - db
      - redis

  caddy:
    image: caddy:2-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile.prod:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
      - hls:/srv/hls:ro
    restart: unless-stopped
    depends_on:
      - php

  db:
    image: mariadb:10.11
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
    volumes:
      - db_data:/var/lib/mysql
      - ./deploy/mysql.cnf:/etc/mysql/conf.d/custom.cnf
    restart: unless-stopped
    command: --innodb-buffer-pool-size=1G

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    restart: unless-stopped
    command: redis-server --appendonly yes

  srs:
    image: ossrs/srs:5
    ports:
      - "1935:1935"
      - "8080:8080"
    volumes:
      - ./deploy/srs.prod.conf:/usr/local/srs/conf/srs.conf
      - hls:/usr/local/srs/objs/nginx/html/hls
      - recordings:/usr/local/srs/objs/nginx/html/rec
    restart: unless-stopped

  cron:
    build:
      context: .
      dockerfile: Dockerfile.cron
    volumes:
      - ./f_data:/var/www/html/f_data
      - uploads:/var/www/html/f_data/uploads
    restart: unless-stopped
    depends_on:
      - db
      - redis

volumes:
  db_data:
  redis_data:
  caddy_data:
  caddy_config:
  uploads:
  hls:
  recordings:

Production Caddyfile

# Caddyfile.prod
{
    email your-email@domain.com
    admin off
}

your-domain.com {
    # Security headers
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        X-XSS-Protection "1; mode=block"
        Referrer-Policy "strict-origin-when-cross-origin"
        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; media-src 'self' blob:; connect-src 'self' wss:"
    }

    # Rate limiting
    rate_limit {
        zone static {
            key {remote_host}
            events 100
            window 1m
        }
        zone api {
            key {remote_host}
            events 1000
            window 1h
        }
    }

    # HLS streaming
    handle /hls/* {
        root * /srv
        file_server {
            precompressed gzip br
        }
        header Cache-Control "public, max-age=10"
    }

    # Static assets
    handle /f_scripts/* /f_templates/* {
        root * /var/www/html
        file_server {
            precompressed gzip br
        }
        header Cache-Control "public, max-age=31536000"
    }

    # API endpoints
    handle /api/* {
        rate_limit api
        reverse_proxy php:9000 {
            transport fastcgi {
                split .php
            }
        }
    }

    # Main application
    handle {
        root * /var/www/html
        php_fastcgi php:9000
        file_server
    }

    # Logging
    log {
        output file /var/log/caddy/access.log {
            roll_size 100mb
            roll_keep 5
        }
        format json
    }
}

Manual Installation

Server Setup (Ubuntu 22.04)

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

# Install PHP 8.2
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
sudo apt install -y php8.2 php8.2-fpm php8.2-mysql php8.2-gd php8.2-curl \
    php8.2-mbstring php8.2-xml php8.2-zip php8.2-bcmath php8.2-intl

# Install MariaDB
sudo apt install -y mariadb-server
sudo mysql_secure_installation

# Install Nginx
sudo apt install -y nginx

# Install FFmpeg
sudo apt install -y ffmpeg

# Install SRS
wget https://github.com/ossrs/srs/releases/download/v5.0.156/srs-server-5.0.156-ubuntu20-amd64.deb
sudo dpkg -i srs-server-5.0.156-ubuntu20-amd64.deb

Database Setup

-- Create database and user
CREATE DATABASE easystream CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'easystream'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON easystream.* TO 'easystream'@'localhost';
FLUSH PRIVILEGES;

-- Import schema
mysql -u easystream -p easystream < __install/easystream.sql

Nginx Configuration

# /etc/nginx/sites-available/easystream
server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;
    root /var/www/easystream;
    index index.php index.html;

    # SSL Configuration
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
    ssl_prefer_server_ciphers off;

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=general:10m rate=1r/s;

    # HLS streaming
    location /hls/ {
        alias /var/srs/hls/;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Access-Control-Allow-Origin "*";
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
        add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range";
    }

    # API endpoints
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP processing
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Static files
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Security
    location ~ /\. {
        deny all;
    }

    location ~ /(f_data|__install|tests)/ {
        deny all;
    }
}

PHP-FPM Configuration

; /etc/php/8.2/fpm/pool.d/easystream.conf
[easystream]
user = www-data
group = www-data
listen = /var/run/php/php8.2-fpm-easystream.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 1000

; PHP settings
php_admin_value[upload_max_filesize] = 2G
php_admin_value[post_max_size] = 2G
php_admin_value[max_execution_time] = 300
php_admin_value[memory_limit] = 512M

Cloud Deployment

AWS Deployment

# Using AWS ECS with Fargate
aws ecs create-cluster --cluster-name easystream-prod

# Create task definition
aws ecs register-task-definition --cli-input-json file://ecs-task-definition.json

# Create service
aws ecs create-service \
    --cluster easystream-prod \
    --service-name easystream-web \
    --task-definition easystream:1 \
    --desired-count 2 \
    --launch-type FARGATE \
    --network-configuration "awsvpcConfiguration={subnets=[subnet-12345],securityGroups=[sg-12345],assignPublicIp=ENABLED}"

Google Cloud Platform

# Deploy to Cloud Run
gcloud run deploy easystream \
    --image gcr.io/PROJECT_ID/easystream \
    --platform managed \
    --region us-central1 \
    --allow-unauthenticated \
    --memory 2Gi \
    --cpu 2 \
    --max-instances 10

DigitalOcean App Platform

# .do/app.yaml
name: easystream
services:
- name: web
  source_dir: /
  github:
    repo: your-username/easystream
    branch: main
  run_command: php-fpm
  environment_slug: php
  instance_count: 2
  instance_size_slug: professional-xs
  envs:
  - key: ENVIRONMENT
    value: production
  - key: DB_HOST
    value: ${db.HOSTNAME}
  - key: DB_NAME
    value: ${db.DATABASE}
  - key: DB_USER
    value: ${db.USERNAME}
  - key: DB_PASS
    value: ${db.PASSWORD}

databases:
- name: db
  engine: MYSQL
  version: "8"
  size: db-s-1vcpu-1gb

SSL/TLS Configuration

Let's Encrypt with Certbot

# Install Certbot
sudo apt install -y certbot python3-certbot-nginx

# Obtain certificate
sudo certbot --nginx -d your-domain.com

# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet

Cloudflare SSL

# Configure Cloudflare origin certificates
# Download origin certificate and key
# Update Nginx/Caddy configuration with certificate paths

Monitoring and Logging

System Monitoring

# Install monitoring tools
sudo apt install -y htop iotop nethogs

# Install Prometheus Node Exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xvfz node_exporter-1.6.1.linux-amd64.tar.gz
sudo cp node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter

Log Management

# Configure log rotation
sudo tee /etc/logrotate.d/easystream << EOF
/var/www/easystream/f_data/logs/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 www-data www-data
}
EOF

Backup Strategy

Database Backup

#!/bin/bash
# backup-db.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/database"
mkdir -p $BACKUP_DIR

mysqldump -u easystream -p easystream | gzip > $BACKUP_DIR/easystream_$DATE.sql.gz

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

File Backup

#!/bin/bash
# backup-files.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/files"
SOURCE_DIR="/var/www/easystream/f_data"

mkdir -p $BACKUP_DIR
tar -czf $BACKUP_DIR/files_$DATE.tar.gz -C $SOURCE_DIR .

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

Performance Optimization

Database Optimization

-- MySQL/MariaDB configuration
[mysqld]
innodb_buffer_pool_size = 2G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
query_cache_size = 128M
query_cache_type = 1
max_connections = 200

PHP Optimization

; php.ini optimizations
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.fast_shutdown=1

realpath_cache_size=4096K
realpath_cache_ttl=600

CDN Configuration

# Configure CloudFlare or AWS CloudFront
# Cache static assets: images, videos, CSS, JS
# Set appropriate cache headers
# Enable compression (gzip/brotli)

Security Hardening

Firewall Configuration

# UFW firewall rules
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 1935/tcp  # RTMP
sudo ufw enable

Fail2Ban Setup

# Install Fail2Ban
sudo apt install -y fail2ban

# Configure jail
sudo tee /etc/fail2ban/jail.local << EOF
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
logpath = /var/log/nginx/error.log

[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
EOF

sudo systemctl restart fail2ban

Troubleshooting

Common Issues

  1. 502 Bad Gateway: Check PHP-FPM status and configuration
  2. Database Connection: Verify credentials and network connectivity
  3. File Permissions: Ensure www-data has proper permissions
  4. Memory Issues: Increase PHP memory limit and server RAM
  5. Streaming Issues: Check SRS configuration and network ports

Debug Commands

# Check service status
sudo systemctl status nginx php8.2-fpm mariadb

# View logs
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/www/easystream/f_data/logs/error_$(date +%Y-%m-%d).log

# Test database connection
mysql -u easystream -p -h localhost easystream

# Check disk space
df -h

# Monitor processes
htop

Maintenance

Regular Maintenance Tasks

#!/bin/bash
# maintenance.sh - Run weekly

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

# Clean up old logs
find /var/www/easystream/f_data/logs -name "*.log" -mtime +30 -delete

# Optimize database
mysql -u easystream -p -e "OPTIMIZE TABLE easystream.videos, easystream.users, easystream.comments;"

# Clear application cache
rm -rf /var/www/easystream/f_data/cache/*

# Restart services
sudo systemctl restart php8.2-fpm nginx

Health Checks

#!/bin/bash
# health-check.sh - Run every 5 minutes

# Check web server
if ! curl -f http://localhost > /dev/null 2>&1; then
    echo "Web server down" | mail -s "EasyStream Alert" admin@domain.com
fi

# Check database
if ! mysql -u easystream -p -e "SELECT 1" > /dev/null 2>&1; then
    echo "Database down" | mail -s "EasyStream Alert" admin@domain.com
fi

# Check disk space
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 90 ]; then
    echo "Disk usage: ${DISK_USAGE}%" | mail -s "EasyStream Alert" admin@domain.com
fi