rackham-meeting-analyzer/deploy.sh

401 lines
13 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
set -e # Exit on any error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
print_header() {
echo -e "\n${BLUE}===================================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}===================================================${NC}\n"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
# Main deployment script
print_header "BTG Rackham Video Sales Coach - Deployment Script v2.0"
# 1. Check prerequisites
print_header "Step 1: Checking Prerequisites"
if ! command -v docker &> /dev/null; then
print_error "Docker is not installed. Please install Docker first."
echo "Visit: https://docs.docker.com/get-docker/"
exit 1
fi
print_success "Docker is installed: $(docker --version)"
# Check for docker compose (modern) or docker-compose (legacy)
if docker compose version &> /dev/null; then
DOCKER_COMPOSE="docker compose"
print_success "Docker Compose is installed: $(docker compose version)"
elif command -v docker-compose &> /dev/null; then
DOCKER_COMPOSE="docker-compose"
print_success "Docker Compose is installed: $(docker-compose --version)"
else
print_error "Docker Compose is not installed. Please install Docker Compose first."
echo "Visit: https://docs.docker.com/compose/install/"
exit 1
fi
# 2. Get deployment directory
print_header "Step 2: Deployment Location"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
print_info "Application directory: $SCRIPT_DIR"
# 3. Check if .env exists
print_header "Step 3: Environment Configuration"
ENV_FILE="$SCRIPT_DIR/infra/.env"
if [ -f "$ENV_FILE" ]; then
print_warning "Environment file already exists at: $ENV_FILE"
read -p "Do you want to reconfigure it? (y/N): " RECONFIGURE
if [[ ! $RECONFIGURE =~ ^[Yy]$ ]]; then
print_info "Keeping existing .env file"
SKIP_ENV_SETUP=true
fi
fi
if [ "$SKIP_ENV_SETUP" != true ]; then
# Copy example if it doesn't exist
if [ ! -f "$ENV_FILE" ]; then
if [ -f "$SCRIPT_DIR/infra/.env.example" ]; then
cp "$SCRIPT_DIR/infra/.env.example" "$ENV_FILE"
print_success "Created .env file from template"
else
print_error ".env.example not found. Creating basic .env file..."
cat > "$ENV_FILE" << 'EOF'
# MongoDB connection (internal docker network - don't change)
MONGO_URL=mongodb://mongo:27017/btg
GEMINI_API_KEY=
GEMINI_MODEL=gemini-2.5-pro
JWT_SECRET=
API_BASE_URL=http://localhost:8080/api
FRONTEND_BASE_PATH=/
CORS_ORIGINS=http://localhost:3009,http://localhost:8080
MAX_UPLOAD_SIZE_GB=2
CHUNK_SIZE_MB=10
DATA_RETENTION_DAYS=90
# Note: MongoDB is externally accessible on host port 27021
EOF
print_success "Created basic .env file"
fi
fi
# Prompt for required values
echo ""
print_info "Please provide the following required values:"
echo ""
# Get Gemini API Key
read -p "Enter your Gemini API Key: " GEMINI_KEY
if [ -z "$GEMINI_KEY" ]; then
print_error "Gemini API Key is required!"
echo "Get one at: https://aistudio.google.com/app/apikey"
exit 1
fi
# Generate JWT Secret
print_info "Generating secure JWT secret..."
JWT_SECRET=$(openssl rand -base64 32)
print_success "Generated JWT secret"
# Get server hostname for CORS
HOSTNAME=$(hostname -f 2>/dev/null || hostname)
read -p "Enter your server domain/hostname (default: $HOSTNAME): " DOMAIN
DOMAIN=${DOMAIN:-$HOSTNAME}
# Get API Base URL for reverse proxy
echo ""
print_info "Backend API Configuration:"
echo "For local development, use: http://localhost:8080/api"
echo "For production with reverse proxy, use your proxied backend URL"
echo "Example: https://ai-sandbox.oliver.solutions/rackham-back"
echo ""
read -p "Enter API Base URL (default: http://localhost:8080/api): " API_URL
API_URL=${API_URL:-http://localhost:8080/api}
print_success "Backend API URL set to: $API_URL"
# Get Frontend Base Path for reverse proxy
echo ""
print_info "Frontend Base Path Configuration:"
echo "For local development or root path, use: /"
echo "For production at subpath, use the path (e.g., /rackham)"
echo "Example: If frontend is at https://ai-sandbox.oliver.solutions/rackham, use: /rackham"
echo ""
read -p "Enter Frontend Base Path (default: /): " FRONTEND_PATH
FRONTEND_PATH=${FRONTEND_PATH:-/}
print_success "Frontend Base Path set to: $FRONTEND_PATH"
# Build CORS origins
CORS_ORIGINS="http://localhost:3009,http://localhost:8080,http://$DOMAIN,https://$DOMAIN"
if [[ "$API_URL" == https://* ]]; then
# Extract domain from API URL for CORS
API_DOMAIN=$(echo "$API_URL" | sed -E 's|https?://([^/]+).*|\1|')
CORS_ORIGINS="$CORS_ORIGINS,https://$API_DOMAIN"
fi
# Update .env file
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
sed -i '' "s|GEMINI_API_KEY=.*|GEMINI_API_KEY=$GEMINI_KEY|" "$ENV_FILE"
sed -i '' "s|JWT_SECRET=.*|JWT_SECRET=$JWT_SECRET|" "$ENV_FILE"
sed -i '' "s|API_BASE_URL=.*|API_BASE_URL=$API_URL|" "$ENV_FILE"
sed -i '' "s|FRONTEND_BASE_PATH=.*|FRONTEND_BASE_PATH=$FRONTEND_PATH|" "$ENV_FILE"
sed -i '' "s|CORS_ORIGINS=.*|CORS_ORIGINS=$CORS_ORIGINS|" "$ENV_FILE"
else
# Linux
sed -i "s|GEMINI_API_KEY=.*|GEMINI_API_KEY=$GEMINI_KEY|" "$ENV_FILE"
sed -i "s|JWT_SECRET=.*|JWT_SECRET=$JWT_SECRET|" "$ENV_FILE"
sed -i "s|API_BASE_URL=.*|API_BASE_URL=$API_URL|" "$ENV_FILE"
sed -i "s|FRONTEND_BASE_PATH=.*|FRONTEND_BASE_PATH=$FRONTEND_PATH|" "$ENV_FILE"
sed -i "s|CORS_ORIGINS=.*|CORS_ORIGINS=$CORS_ORIGINS|" "$ENV_FILE"
fi
print_success "Environment file configured"
echo ""
print_info "Configuration saved to: $ENV_FILE"
fi
# 4. Create data directories
print_header "Step 4: Creating Data Directories"
sudo mkdir -p /data/videos
sudo mkdir -p /tmp/chunks
sudo chown -R $USER:$USER /data/videos /tmp/chunks
print_success "Data directories created and permissions set"
# 5. Stop any existing containers
print_header "Step 5: Stopping Existing Containers"
cd "$SCRIPT_DIR/infra"
if $DOCKER_COMPOSE ps | grep -q "Up"; then
print_info "Stopping existing containers..."
$DOCKER_COMPOSE down
print_success "Existing containers stopped"
else
print_info "No existing containers running"
fi
# 6. Build containers
print_header "Step 6: Building Docker Containers"
print_info "This may take 5-10 minutes on first build..."
$DOCKER_COMPOSE build
if [ $? -eq 0 ]; then
print_success "Docker containers built successfully"
else
print_error "Docker build failed. Check the output above for errors."
exit 1
fi
# 7. Build Frontend Static Files
print_header "Step 7: Building Frontend for Production"
# Load values from .env file - ALWAYS load if we skipped env setup
if [ "$SKIP_ENV_SETUP" = true ] || [ -z "$API_URL" ] || [ -z "$FRONTEND_PATH" ]; then
if [ -f "$ENV_FILE" ]; then
print_info "Loading build configuration from .env..."
source "$ENV_FILE"
API_URL=${API_BASE_URL:-http://localhost:8080/api}
FRONTEND_PATH=${FRONTEND_BASE_PATH:-/rackham}
print_info " API Base: $API_URL"
print_info " Frontend Path: $FRONTEND_PATH"
fi
fi
cd "$SCRIPT_DIR/frontend"
print_info "Installing frontend dependencies..."
npm ci
print_info "Building frontend with production settings..."
echo " VITE_BASE_PATH=$FRONTEND_PATH"
echo " VITE_API_BASE=$API_URL"
echo ""
# Build with environment variables
VITE_BASE_PATH=$FRONTEND_PATH VITE_API_BASE=$API_URL npm run build
if [ $? -eq 0 ]; then
print_success "Frontend built successfully"
else
print_error "Frontend build failed. Check the output above for errors."
exit 1
fi
# 8. Deploy Frontend to Apache Web Root
print_header "Step 8: Deploying Frontend to Apache Web Root"
APACHE_WEB_ROOT="/var/www/html/rackham"
print_info "Deploying to: $APACHE_WEB_ROOT"
# Create directory and copy files
sudo mkdir -p "$APACHE_WEB_ROOT"
sudo rm -rf "$APACHE_WEB_ROOT"/*
sudo cp -r dist/* "$APACHE_WEB_ROOT/"
sudo chown -R www-data:www-data "$APACHE_WEB_ROOT"
sudo chmod -R 755 "$APACHE_WEB_ROOT"
print_success "Frontend deployed to $APACHE_WEB_ROOT"
# 9. Start Backend and Database Containers
print_header "Step 9: Starting Backend Services"
cd "$SCRIPT_DIR/infra"
$DOCKER_COMPOSE up -d backend mongo
if [ $? -eq 0 ]; then
print_success "Backend services started successfully"
else
print_error "Failed to start services. Check logs with: $DOCKER_COMPOSE logs"
exit 1
fi
# 10. Wait for services to be ready
print_header "Step 10: Waiting for Services to Initialize"
print_info "Waiting 15 seconds for services to start..."
sleep 15
# 9. Verify deployment
print_header "Step 9: Verifying Deployment"
# Check container status
echo ""
print_info "Container Status:"
$DOCKER_COMPOSE ps
echo ""
# Check backend
if curl -s http://localhost:8080/docs > /dev/null 2>&1; then
print_success "Backend is responding on port 8080"
else
print_warning "Backend may not be ready yet. Check logs: docker-compose logs backend"
fi
# Check frontend static files
if [ -f "/var/www/html/rackham/index.html" ]; then
print_success "Frontend deployed to /var/www/html/rackham"
FILE_COUNT=$(find /var/www/html/rackham -type f 2>/dev/null | wc -l)
print_info " Deployed $FILE_COUNT static files"
else
print_warning "Frontend files not found at /var/www/html/rackham"
fi
# Check MongoDB
if docker exec infra-mongo-1 mongosh btg --quiet --eval "db.runCommand({ ping: 1 }).ok" 2>/dev/null | grep -q "1"; then
print_success "MongoDB is running and accessible"
else
print_warning "MongoDB may not be ready yet. Check logs: docker-compose logs mongo"
fi
# 10. Display summary
print_header "🎉 Deployment Complete!"
echo ""
echo -e "${GREEN}The BTG Rackham Video Sales Coach is now deployed!${NC}"
echo ""
echo "Deployment Details:"
echo " - Frontend: Static files at /var/www/html/rackham (served by Apache)"
echo " - Backend: Docker container on port 8080"
echo " - MongoDB: Docker container on port 27021"
echo ""
if [ -n "$API_URL" ] && [[ "$API_URL" == https://* ]]; then
echo "Production Access:"
echo " - Frontend: https://ai-sandbox.oliver.solutions/rackham"
echo " - Backend: https://ai-sandbox.oliver.solutions/rackham-back"
echo " - API Docs: https://ai-sandbox.oliver.solutions/rackham-back/docs"
else
echo "Local Access:"
echo " - Frontend: Access via Apache (http://$DOMAIN/rackham)"
echo " - Backend: http://localhost:8080"
echo " - API Docs: http://localhost:8080/docs"
fi
echo ""
echo "Useful Commands:"
echo " - View backend logs: cd $SCRIPT_DIR/infra && $DOCKER_COMPOSE logs -f backend"
echo " - Restart backend: cd $SCRIPT_DIR/infra && $DOCKER_COMPOSE restart backend"
echo " - Stop services: cd $SCRIPT_DIR/infra && $DOCKER_COMPOSE down"
echo " - Rebuild frontend: cd $SCRIPT_DIR && ./deploy.sh (run again)"
echo ""
print_info "Next Steps:"
echo " 1. Add Apache config for /rackham (see instructions below)"
echo " 2. Reload Apache: sudo systemctl reload apache2"
echo " 3. Access: https://ai-sandbox.oliver.solutions/rackham"
echo " 4. Create your first user account"
echo " 5. Upload a test video (5-10 min recommended)"
echo ""
print_header "Apache Configuration Required"
echo -e "${YELLOW}Add the following to your /etc/apache2/apache2.conf:${NC}"
echo ""
echo "# rackham video analyzer frontend - SPA routing"
echo "<Directory /var/www/html/rackham>"
echo " Options -Indexes +FollowSymLinks"
echo " AllowOverride All"
echo " Require all granted"
echo ""
echo " # Handle React Router (SPA routing)"
echo " RewriteEngine On"
echo " RewriteBase /rackham/"
echo " RewriteRule ^index\\.html$ - [L]"
echo " RewriteCond %{REQUEST_FILENAME} !-f"
echo " RewriteCond %{REQUEST_FILENAME} !-d"
echo " RewriteRule . /rackham/index.html [L]"
echo ""
echo " # Cache static assets"
echo " <FilesMatch \"\\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$\">"
echo " Header set Cache-Control \"public, max-age=31536000, immutable\""
echo " </FilesMatch>"
echo ""
echo " # No cache for index.html"
echo " <FilesMatch \"^index\\.html$\">"
echo " Header set Cache-Control \"no-cache, no-store, must-revalidate\""
echo " </FilesMatch>"
echo "</Directory>"
echo ""
echo "# rackham video analyzer backend - already in your config"
echo "ProxyPass /rackham-back/ http://localhost:8080/"
echo "ProxyPassReverse /rackham-back/ http://localhost:8080/"
echo ""
echo -e "${YELLOW}Then run: sudo systemctl reload apache2${NC}"
echo ""
print_warning "IMPORTANT: Make sure to backup your .env file - it contains sensitive credentials!"
echo ""
# Create a backup of .env
ENV_BACKUP="$SCRIPT_DIR/infra/.env.backup-$(date +%Y%m%d-%H%M%S)"
cp "$ENV_FILE" "$ENV_BACKUP"
print_success "Backup of .env created at: $ENV_BACKUP"
echo ""
print_success "Deployment completed successfully! 🚀"
echo ""