438 lines
13 KiB
Bash
Executable File
438 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
################################################################################
|
|
# VidRip Production Startup Script
|
|
################################################################################
|
|
# This script builds and runs the VidRip service in production mode.
|
|
# It handles dependency checks, builds both frontend and backend, and starts
|
|
# the backend server with proper process management.
|
|
################################################################################
|
|
|
|
set -e # Exit on error
|
|
set -u # Exit on undefined variable
|
|
|
|
# Color codes for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Script directory
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$SCRIPT_DIR"
|
|
|
|
# Configuration
|
|
BACKEND_DIR="$SCRIPT_DIR/backend"
|
|
FRONTEND_DIR="$SCRIPT_DIR/frontend"
|
|
LOG_DIR="$SCRIPT_DIR/logs"
|
|
PID_FILE="$SCRIPT_DIR/vidrip.pid"
|
|
LOG_FILE="$LOG_DIR/vidrip.log"
|
|
ERROR_LOG_FILE="$LOG_DIR/vidrip-error.log"
|
|
WEB_ROOT="/var/www/vidrip"
|
|
|
|
################################################################################
|
|
# Helper Functions
|
|
################################################################################
|
|
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
check_command() {
|
|
if ! command -v "$1" &> /dev/null; then
|
|
log_error "$1 is not installed or not in PATH"
|
|
return 1
|
|
fi
|
|
log_success "$1 is installed"
|
|
return 0
|
|
}
|
|
|
|
cleanup_on_exit() {
|
|
log_info "Cleaning up..."
|
|
if [ -f "$PID_FILE" ]; then
|
|
rm -f "$PID_FILE"
|
|
fi
|
|
}
|
|
|
|
################################################################################
|
|
# Pre-flight Checks
|
|
################################################################################
|
|
|
|
log_info "Starting VidRip production deployment..."
|
|
echo ""
|
|
|
|
log_info "Checking system requirements..."
|
|
|
|
# Check for Node.js
|
|
if ! check_command node; then
|
|
log_error "Node.js is required but not installed"
|
|
exit 1
|
|
fi
|
|
|
|
NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
|
if [ "$NODE_VERSION" -lt 18 ]; then
|
|
log_error "Node.js version 18 or higher is required (found v$NODE_VERSION)"
|
|
exit 1
|
|
fi
|
|
log_success "Node.js version: $(node --version)"
|
|
|
|
# Check for npm
|
|
if ! check_command npm; then
|
|
log_error "npm is required but not installed"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for yt-dlp
|
|
if ! check_command yt-dlp; then
|
|
log_warning "yt-dlp is not installed or not in PATH"
|
|
log_warning "Install with: pip install yt-dlp OR brew install yt-dlp"
|
|
log_warning "The application will not be able to download videos without yt-dlp"
|
|
else
|
|
log_success "yt-dlp version: $(yt-dlp --version)"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Check for existing process
|
|
################################################################################
|
|
|
|
if [ -f "$PID_FILE" ]; then
|
|
OLD_PID=$(cat "$PID_FILE")
|
|
if ps -p "$OLD_PID" > /dev/null 2>&1; then
|
|
log_error "VidRip is already running (PID: $OLD_PID)"
|
|
log_info "Stop it first with: kill $OLD_PID"
|
|
exit 1
|
|
else
|
|
log_warning "Stale PID file found, removing..."
|
|
rm -f "$PID_FILE"
|
|
fi
|
|
fi
|
|
|
|
################################################################################
|
|
# Create necessary directories
|
|
################################################################################
|
|
|
|
log_info "Creating necessary directories..."
|
|
mkdir -p "$LOG_DIR"
|
|
mkdir -p "$BACKEND_DIR/downloads"
|
|
mkdir -p "$BACKEND_DIR/dist"
|
|
log_success "Directories created"
|
|
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Install Dependencies
|
|
################################################################################
|
|
|
|
log_info "Installing dependencies..."
|
|
|
|
# Backend dependencies
|
|
log_info "Installing backend dependencies..."
|
|
cd "$BACKEND_DIR"
|
|
if [ ! -d "node_modules" ]; then
|
|
npm install --production=false
|
|
else
|
|
log_info "Backend node_modules already exists, skipping install"
|
|
fi
|
|
log_success "Backend dependencies installed"
|
|
|
|
# Frontend dependencies
|
|
log_info "Installing frontend dependencies..."
|
|
cd "$FRONTEND_DIR"
|
|
if [ ! -d "node_modules" ]; then
|
|
npm install --production=false
|
|
else
|
|
log_info "Frontend node_modules already exists, skipping install"
|
|
fi
|
|
log_success "Frontend dependencies installed"
|
|
|
|
cd "$SCRIPT_DIR"
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Build Applications
|
|
################################################################################
|
|
|
|
log_info "Building applications..."
|
|
|
|
# Build backend
|
|
log_info "Building backend (TypeScript compilation)..."
|
|
cd "$BACKEND_DIR"
|
|
npm run build
|
|
if [ ! -f "dist/server.js" ]; then
|
|
log_error "Backend build failed - dist/server.js not found"
|
|
exit 1
|
|
fi
|
|
log_success "Backend built successfully"
|
|
|
|
# Build frontend
|
|
log_info "Building frontend (Vite production build)..."
|
|
cd "$FRONTEND_DIR"
|
|
npm run build
|
|
if [ ! -d "dist" ]; then
|
|
log_error "Frontend build failed - dist directory not found"
|
|
exit 1
|
|
fi
|
|
log_success "Frontend built successfully"
|
|
|
|
cd "$SCRIPT_DIR"
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Generate Caddyfile (if needed)
|
|
################################################################################
|
|
|
|
if [ ! -f "$SCRIPT_DIR/Caddyfile" ]; then
|
|
log_info "Caddyfile not found. Let's create one!"
|
|
echo ""
|
|
|
|
# Ask for domain
|
|
read -p "Enter your domain name (or press Enter to skip): " DOMAIN_INPUT
|
|
|
|
if [ -n "$DOMAIN_INPUT" ]; then
|
|
log_info "Generating Caddyfile for domain: $DOMAIN_INPUT"
|
|
|
|
cat > "$SCRIPT_DIR/Caddyfile" << EOF
|
|
# VidRip Caddyfile
|
|
# Auto-generated configuration for ${DOMAIN_INPUT}
|
|
|
|
${DOMAIN_INPUT} {
|
|
# Enable compression
|
|
encode gzip zstd
|
|
|
|
# Security headers
|
|
header {
|
|
# Enable HSTS (forces HTTPS)
|
|
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
|
# Prevent clickjacking
|
|
X-Frame-Options "SAMEORIGIN"
|
|
# Prevent MIME type sniffing
|
|
X-Content-Type-Options "nosniff"
|
|
# Enable XSS protection
|
|
X-XSS-Protection "1; mode=block"
|
|
# Referrer policy
|
|
Referrer-Policy "strict-origin-when-cross-origin"
|
|
# Remove server header for security
|
|
-Server
|
|
}
|
|
|
|
# API routes - proxy to backend
|
|
handle /api/* {
|
|
reverse_proxy localhost:3001 {
|
|
# Health check
|
|
health_uri /api/health
|
|
health_interval 10s
|
|
health_timeout 5s
|
|
|
|
# Headers
|
|
header_up Host {host}
|
|
header_up X-Real-IP {remote_host}
|
|
header_up X-Forwarded-For {remote_host}
|
|
header_up X-Forwarded-Proto {scheme}
|
|
}
|
|
}
|
|
|
|
# Serve frontend static files
|
|
handle {
|
|
# Root directory is the frontend build output
|
|
root * ${WEB_ROOT}
|
|
|
|
# Try files first, fall back to index.html for SPA routing
|
|
try_files {path} /index.html
|
|
|
|
# Serve files
|
|
file_server
|
|
|
|
# Cache static assets
|
|
@static {
|
|
path *.js *.css *.woff *.woff2 *.ttf *.eot *.ico *.png *.jpg *.jpeg *.gif *.svg *.webp
|
|
}
|
|
header @static {
|
|
Cache-Control "public, max-age=31536000, immutable"
|
|
}
|
|
|
|
# Don't cache index.html
|
|
@html {
|
|
path *.html
|
|
}
|
|
header @html {
|
|
Cache-Control "no-cache, no-store, must-revalidate"
|
|
}
|
|
}
|
|
|
|
# Logging
|
|
log {
|
|
output file /var/log/caddy/vidrip-access.log {
|
|
roll_size 100mb
|
|
roll_keep 10
|
|
}
|
|
format json
|
|
}
|
|
}
|
|
EOF
|
|
|
|
log_success "Caddyfile created successfully!"
|
|
log_info "You can edit it later at: $SCRIPT_DIR/Caddyfile"
|
|
else
|
|
log_info "Skipping Caddyfile generation"
|
|
log_info "You can create it manually later or use nginx/Apache"
|
|
fi
|
|
echo ""
|
|
else
|
|
log_info "Caddyfile already exists, skipping generation"
|
|
echo ""
|
|
fi
|
|
|
|
################################################################################
|
|
# Deploy Frontend to Web Root
|
|
################################################################################
|
|
|
|
log_info "Deploying frontend to web root..."
|
|
|
|
# Check if we have permissions to write to /var/www
|
|
if [ -w "/var/www" ]; then
|
|
# Create web root directory
|
|
sudo mkdir -p "$WEB_ROOT"
|
|
|
|
# Copy frontend build to web root
|
|
log_info "Copying frontend build to $WEB_ROOT..."
|
|
sudo rm -rf "$WEB_ROOT"/*
|
|
sudo cp -r "$FRONTEND_DIR/dist/"* "$WEB_ROOT/"
|
|
|
|
# Set proper permissions
|
|
sudo chown -R www-data:www-data "$WEB_ROOT" 2>/dev/null || sudo chown -R $USER:$USER "$WEB_ROOT"
|
|
sudo chmod -R 755 "$WEB_ROOT"
|
|
|
|
log_success "Frontend deployed to $WEB_ROOT"
|
|
else
|
|
log_warning "No write permission to /var/www"
|
|
log_warning "Run with sudo to deploy frontend, or manually copy:"
|
|
log_warning " sudo mkdir -p $WEB_ROOT"
|
|
log_warning " sudo cp -r $FRONTEND_DIR/dist/* $WEB_ROOT/"
|
|
log_warning " sudo chown -R www-data:www-data $WEB_ROOT"
|
|
log_warning " sudo chmod -R 755 $WEB_ROOT"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
################################################################################
|
|
# Start Backend Server
|
|
################################################################################
|
|
|
|
log_info "Starting VidRip backend server..."
|
|
|
|
# Setup environment
|
|
export NODE_ENV=production
|
|
|
|
# Start the backend server
|
|
cd "$BACKEND_DIR"
|
|
|
|
# Run in background with output redirected to log files
|
|
nohup node dist/server.js > "$LOG_FILE" 2> "$ERROR_LOG_FILE" &
|
|
SERVER_PID=$!
|
|
|
|
# Save PID
|
|
echo "$SERVER_PID" > "$PID_FILE"
|
|
|
|
# Wait a moment and check if process is still running
|
|
sleep 2
|
|
if ! ps -p "$SERVER_PID" > /dev/null 2>&1; then
|
|
log_error "Server failed to start"
|
|
log_error "Check logs at:"
|
|
log_error " - $LOG_FILE"
|
|
log_error " - $ERROR_LOG_FILE"
|
|
rm -f "$PID_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "VidRip backend started successfully!"
|
|
echo ""
|
|
log_info "Process ID: $SERVER_PID"
|
|
log_info "PID file: $PID_FILE"
|
|
log_info "Log file: $LOG_FILE"
|
|
log_info "Error log: $ERROR_LOG_FILE"
|
|
echo ""
|
|
|
|
# Check for port in logs (default 3001)
|
|
sleep 1
|
|
if grep -q "Server running" "$LOG_FILE" 2>/dev/null; then
|
|
PORT_INFO=$(grep "Server running" "$LOG_FILE" | tail -1)
|
|
log_success "$PORT_INFO"
|
|
else
|
|
log_info "Server should be running on port 3001 (or PORT from .env)"
|
|
fi
|
|
|
|
echo ""
|
|
log_info "==================================================================="
|
|
log_info "VidRip is now running in production mode"
|
|
log_info "==================================================================="
|
|
echo ""
|
|
log_info "Backend Server:"
|
|
log_info " Running on port 3001 (or PORT from .env)"
|
|
log_info " PID: $SERVER_PID"
|
|
echo ""
|
|
log_info "Frontend:"
|
|
log_info " Deployed to: $WEB_ROOT"
|
|
echo ""
|
|
log_info "To stop the backend service:"
|
|
log_info " ./stop-production.sh"
|
|
echo ""
|
|
log_info "To view logs:"
|
|
log_info " tail -f $LOG_FILE"
|
|
echo ""
|
|
log_info "To view errors:"
|
|
log_info " tail -f $ERROR_LOG_FILE"
|
|
echo ""
|
|
if [ -f "$SCRIPT_DIR/Caddyfile" ]; then
|
|
log_warning "NEXT STEPS - Caddy Setup:"
|
|
log_warning " 1. Install Caddy: https://caddyserver.com/docs/install"
|
|
log_warning " Quick install (Ubuntu/Debian):"
|
|
log_warning " sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https"
|
|
log_warning " curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg"
|
|
log_warning " curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list"
|
|
log_warning " sudo apt update && sudo apt install caddy"
|
|
echo ""
|
|
log_warning " 2. Copy Caddyfile to Caddy config directory:"
|
|
log_warning " sudo cp $SCRIPT_DIR/Caddyfile /etc/caddy/Caddyfile"
|
|
echo ""
|
|
log_warning " 3. Start Caddy:"
|
|
log_warning " sudo systemctl enable caddy"
|
|
log_warning " sudo systemctl start caddy"
|
|
echo ""
|
|
log_warning " 4. Configure firewall to allow ports 80/443:"
|
|
log_warning " sudo ufw allow 80/tcp"
|
|
log_warning " sudo ufw allow 443/tcp"
|
|
echo ""
|
|
log_success "Caddy will automatically obtain SSL certificates from Let's Encrypt!"
|
|
else
|
|
log_warning "NEXT STEPS:"
|
|
log_warning " 1. Install Caddy: https://caddyserver.com/docs/install"
|
|
log_warning " 2. Edit Caddyfile and replace 'your-domain.com' with your domain"
|
|
log_warning " 3. Start Caddy: sudo caddy start"
|
|
log_warning " (or for testing: caddy run)"
|
|
log_warning " 4. Configure firewall to allow ports 80/443"
|
|
fi
|
|
echo ""
|
|
log_info "Alternative web servers:"
|
|
log_info " - See DEPLOYMENT.md for nginx/Apache configurations"
|
|
echo ""
|
|
|
|
# Register cleanup on script exit
|
|
trap cleanup_on_exit EXIT
|
|
|
|
exit 0
|