- 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
15 KiB
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
Recommended Requirements
- 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
- 502 Bad Gateway: Check PHP-FPM status and configuration
- Database Connection: Verify credentials and network connectivity
- File Permissions: Ensure www-data has proper permissions
- Memory Issues: Increase PHP memory limit and server RAM
- 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