#!/bin/bash ############################################# # Voice to Text - Production Deploy Script ############################################# # Deploys backend (Python API) and frontend (PHP) to production # Usage: sudo ./deploy.sh [options] set -e # Exit on error # 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 # Configuration BACKEND_DIR="/opt/voice2text" FRONTEND_DIR="/var/www/html/voice2txt" SERVICE_NAME="voice2text-api" SERVICE_FILE="voice2text-api.service" SERVICE_PATH="/etc/systemd/system/${SERVICE_FILE}" # Parse command line arguments DRY_RUN=false BACKEND_ONLY=false FRONTEND_ONLY=false VERBOSE=false SKIP_GIT_CHECK=false while [[ $# -gt 0 ]]; do case $1 in --dry-run) DRY_RUN=true shift ;; --backend-only) BACKEND_ONLY=true shift ;; --frontend-only) FRONTEND_ONLY=true shift ;; --verbose|-v) VERBOSE=true shift ;; --skip-git-check) SKIP_GIT_CHECK=true shift ;; --help|-h) echo "Usage: sudo ./deploy.sh [options]" echo "" echo "Options:" echo " --dry-run Show what would be deployed without executing" echo " --backend-only Deploy only the Python API backend" echo " --frontend-only Deploy only the PHP frontend" echo " --verbose, -v Show detailed output" echo " --skip-git-check Skip the git status verification prompt" echo " --help, -h Show this help message" echo "" echo "Note: This script does NOT pull code from git." echo " Pull the desired code/branch BEFORE running this script." exit 0 ;; *) echo -e "${RED}Unknown option: $1${NC}" exit 1 ;; esac done # Helper functions print_header() { echo -e "\n${BLUE}═══════════════════════════════════════════════════${NC}" echo -e "${BLUE} $1${NC}" echo -e "${BLUE}═══════════════════════════════════════════════════${NC}\n" } print_success() { echo -e "${GREEN}✓${NC} $1" } print_error() { echo -e "${RED}✗${NC} $1" } print_warning() { echo -e "${YELLOW}⚠${NC} $1" } print_info() { echo -e "${BLUE}ℹ${NC} $1" } run_command() { if [ "$VERBOSE" = true ]; then echo -e "${BLUE}Running:${NC} $*" fi if [ "$DRY_RUN" = true ]; then echo -e "${YELLOW}[DRY RUN]${NC} Would execute: $*" else "$@" fi } # Pre-flight checks print_header "Pre-flight Checks" # Check if running as root if [ "$EUID" -ne 0 ]; then print_error "This script must be run as root (use sudo)" exit 1 fi print_success "Running as root" # Check if backend directory exists if [ ! -d "$BACKEND_DIR" ]; then print_error "Backend directory not found: $BACKEND_DIR" print_info "Create directory and clone repo first: git clone $BACKEND_DIR" exit 1 fi print_success "Backend directory exists: $BACKEND_DIR" # Change to backend directory cd "$BACKEND_DIR" # Check for required system dependencies print_header "Checking Required Dependencies" # Check Python (REQUIRED) if ! command -v python3 &> /dev/null; then print_error "Python 3 is not installed (REQUIRED)" print_info "Install: sudo apt install python3 python3-venv python3-pip" exit 1 fi print_success "Python 3 found: $(python3 --version)" # Check Composer (REQUIRED for PHP dependencies) if ! command -v composer &> /dev/null; then print_error "Composer is not installed (REQUIRED)" print_info "Install: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer" exit 1 fi print_success "Composer found: $(composer --version | head -n 1)" # Check FFmpeg (REQUIRED for audio processing) if ! command -v ffmpeg &> /dev/null; then print_error "FFmpeg is not installed (REQUIRED)" print_info "Install: sudo apt install ffmpeg" exit 1 fi print_success "FFmpeg found: $(ffmpeg -version | head -n 1 | cut -d' ' -f3)" # Detect if this is first deployment FIRST_DEPLOY=false if [ ! -f "$SERVICE_PATH" ]; then FIRST_DEPLOY=true print_info "First deployment detected" else print_info "Updating existing deployment" fi # Verify we're ready to deploy print_header "Pre-Deployment Verification" print_info "Backend directory: ${GREEN}${BACKEND_DIR}${NC}" # Prompt user to confirm they've pulled the latest code if [ "$SKIP_GIT_CHECK" != true ] && [ "$DRY_RUN" != true ]; then echo "" echo -e "${YELLOW}IMPORTANT:${NC} This script does NOT pull code from git." echo -e " Make sure you've pulled the code you want to deploy BEFORE running this script." echo "" echo "Expected workflow:" echo " 1. cd ${BACKEND_DIR}" echo " 2. git pull origin main (or checkout desired branch/tag)" echo " 3. Review changes" echo " 4. Run this deploy script" echo "" read -p "Are you ready to deploy the current code? (y/n) " -n 1 -r echo "" if [[ ! $REPLY =~ ^[Yy]$ ]]; then print_error "Deployment cancelled." exit 1 fi print_success "Proceeding with deployment" else if [ "$SKIP_GIT_CHECK" = true ]; then print_info "Skipping deployment confirmation (--skip-git-check)" fi print_success "Proceeding with deployment" fi # Deploy Backend if [ "$FRONTEND_ONLY" != true ]; then print_header "Deploying Backend (Python API)" cd "$BACKEND_DIR" # Check for Python if ! command -v python3 &> /dev/null; then print_error "Python 3 is not installed" exit 1 fi print_success "Python 3 found: $(python3 --version)" # Create virtual environment if it doesn't exist if [ ! -d "venv" ]; then print_info "Creating Python virtual environment..." run_command python3 -m venv venv print_success "Virtual environment created" else print_success "Virtual environment exists" fi # Activate venv and install/update dependencies print_info "Installing Python dependencies..." run_command venv/bin/pip install --upgrade pip run_command venv/bin/pip install -r requirements.txt print_success "Python dependencies installed" # Install/update Composer dependencies (REQUIRED) print_info "Installing PHP dependencies (Composer)..." run_command composer install --no-dev --optimize-autoloader # VERIFY vendor/ directory was created if [ ! -d "vendor" ]; then print_error "Composer dependencies failed to install - vendor/ directory missing!" print_info "Try running: composer install --verbose" exit 1 fi if [ ! -f "vendor/autoload.php" ]; then print_error "Composer autoload.php is missing!" print_info "This indicates a broken Composer installation" exit 1 fi print_success "Composer dependencies installed and verified" # Create outputs directory if it doesn't exist if [ ! -d "outputs" ]; then print_info "Creating outputs directory..." run_command mkdir -p outputs fi # Set proper ownership and permissions print_info "Setting permissions..." run_command chown -R www-data:www-data "$BACKEND_DIR" run_command chmod -R 755 "$BACKEND_DIR" run_command chmod 777 "$BACKEND_DIR/outputs" print_success "Permissions set" # Handle .env file if [ ! -f ".env" ]; then print_warning ".env file not found in $BACKEND_DIR" if [ -f ".env.example" ]; then print_info "Copying .env.example to .env..." run_command cp .env.example .env print_warning "IMPORTANT: Edit $BACKEND_DIR/.env with production credentials!" else print_error ".env.example not found - cannot create .env" exit 1 fi else print_success ".env file exists (not overwriting)" fi # Install systemd service print_info "Installing systemd service..." run_command cp "$BACKEND_DIR/$SERVICE_FILE" "$SERVICE_PATH" run_command systemctl daemon-reload print_success "Systemd service installed" # Enable and start/restart service if [ "$FIRST_DEPLOY" = true ]; then print_info "Enabling service..." run_command systemctl enable "$SERVICE_NAME" print_success "Service enabled" print_info "Starting service..." run_command systemctl start "$SERVICE_NAME" print_success "Service started" else print_info "Restarting service..." run_command systemctl restart "$SERVICE_NAME" print_success "Service restarted" fi # Wait for service to start print_info "Waiting for service to start..." sleep 3 # Check service status if systemctl is-active --quiet "$SERVICE_NAME"; then print_success "Service is running" else print_error "Service failed to start" echo "" echo "Service status:" systemctl status "$SERVICE_NAME" --no-pager echo "" echo "Recent logs:" journalctl -u "$SERVICE_NAME" -n 20 --no-pager exit 1 fi # Test API health endpoint print_info "Testing API health endpoint..." if curl -sf http://localhost:5010/health > /dev/null; then print_success "API is responding at http://localhost:5010" else print_warning "API health check failed - service may still be starting" fi fi # Deploy Frontend if [ "$BACKEND_ONLY" != true ]; then print_header "Deploying Frontend (PHP)" # Create frontend directory if it doesn't exist if [ ! -d "$FRONTEND_DIR" ]; then print_info "Creating frontend directory..." run_command mkdir -p "$FRONTEND_DIR" fi # Copy frontend files print_info "Copying frontend files..." # PHP files run_command cp "$BACKEND_DIR"/*.php "$FRONTEND_DIR/" # Config files run_command cp "$BACKEND_DIR/.htaccess" "$FRONTEND_DIR/" run_command cp "$BACKEND_DIR/.user.ini" "$FRONTEND_DIR/" # Assets run_command cp "$BACKEND_DIR/style.css" "$FRONTEND_DIR/" if [ -f "$BACKEND_DIR/V2T.svg" ]; then run_command cp "$BACKEND_DIR/V2T.svg" "$FRONTEND_DIR/" fi # Composer vendor directory (REQUIRED) if [ ! -d "$BACKEND_DIR/vendor" ]; then print_error "vendor/ directory not found in backend!" print_info "This should have been created during backend deployment" exit 1 fi print_info "Copying Composer dependencies..." run_command cp -r "$BACKEND_DIR/vendor" "$FRONTEND_DIR/" # VERIFY vendor/ was copied successfully if [ ! -f "$FRONTEND_DIR/vendor/autoload.php" ]; then print_error "Failed to copy vendor/ to frontend!" print_info "Check permissions and disk space" exit 1 fi print_success "Composer dependencies copied and verified" print_success "Frontend files copied" # Handle .env file for frontend if [ ! -f "$FRONTEND_DIR/.env" ]; then print_warning ".env file not found in $FRONTEND_DIR" if [ -f "$BACKEND_DIR/.env.example" ]; then print_info "Copying .env.example to frontend..." run_command cp "$BACKEND_DIR/.env.example" "$FRONTEND_DIR/.env" print_warning "IMPORTANT: Edit $FRONTEND_DIR/.env with production credentials!" fi else print_success ".env file exists in frontend (not overwriting)" fi # Create outputs directory symlink or copy if [ ! -d "$FRONTEND_DIR/outputs" ]; then print_info "Linking outputs directory..." run_command ln -s "$BACKEND_DIR/outputs" "$FRONTEND_DIR/outputs" print_success "Outputs directory linked" fi # Set proper ownership and permissions print_info "Setting frontend permissions..." run_command chown -R www-data:www-data "$FRONTEND_DIR" run_command chmod -R 755 "$FRONTEND_DIR" print_success "Frontend permissions set" fi # Final summary print_header "Deployment Summary" if [ "$BACKEND_ONLY" != true ]; then echo -e "${GREEN}Frontend:${NC}" echo " Location: $FRONTEND_DIR" echo " Files: *.php, style.css, .htaccess, vendor/" fi if [ "$FRONTEND_ONLY" != true ]; then echo -e "${GREEN}Backend:${NC}" echo " Location: $BACKEND_DIR" echo " Service: $SERVICE_NAME" echo " Status: $(systemctl is-active $SERVICE_NAME)" echo " API: http://localhost:5010" fi echo "" print_success "Deployment completed successfully!" echo "" # Show useful commands print_header "Useful Commands" echo "Service management:" echo " systemctl status $SERVICE_NAME # Check service status" echo " systemctl restart $SERVICE_NAME # Restart service" echo " systemctl stop $SERVICE_NAME # Stop service" echo "" echo "View logs:" echo " journalctl -u $SERVICE_NAME -f # Follow live logs" echo " journalctl -u $SERVICE_NAME -n 50 # Last 50 log entries" echo "" echo "Test API:" echo " curl http://localhost:5010/health # Health check" echo "" if [ -f "$FRONTEND_DIR/.env" ] && grep -q "DEV_MODE=true" "$FRONTEND_DIR/.env" 2>/dev/null; then print_warning "WARNING: DEV_MODE=true detected in .env!" print_warning "Remember to set DEV_MODE=false for production" fi