- Created OPERATIONAL_RUNBOOK.md: comprehensive step-by-step procedures for both Docker and Standalone deployment modes covering deployment, daily ops, troubleshooting, backup/restore, disaster recovery, scaling, and updates - Created HEALTH_MONITORING_CHECKLIST.md: daily/weekly/monthly health check procedures with alert thresholds and quick troubleshooting reference - Created DISASTER_RECOVERY_PLAN.md: detailed procedures for 6 failure scenarios (database corruption, hardware failure, data center failure, app crash, disk full, network isolation) with RTO/RPO targets - Created CONFIGURATION_REFERENCE.md: complete documentation of all inventory.env parameters for both deployment modes with common scenarios and troubleshooting - Created EMERGENCY_PROCEDURES.md: quick-reference incident response playbook with 7 critical scenarios, decision tree, escalation path, and printable cheat sheet - Created scripts/backup.sh: automated backup script supporting both Docker and Standalone with integrity verification and retention management - Created scripts/restore.sh: restore script with triple confirmation, safety backups, and validation tests for both deployment modes - Created config/backup-cron.sh: installer for daily/weekly automated backup cron jobs (2 AM daily, 3 AM Sunday) All documentation covers dual-deployment modes with shared configuration files. Documentation is operator-ready with copy-paste commands and clear expected outputs.
223 lines
8.8 KiB
Bash
Executable File
223 lines
8.8 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Phase 6, Plan 1, Task 4: Automated Deployment Script
|
|
# Usage: ./deploy.sh [production|staging|development] [--rebuild]
|
|
# Purpose: Single-command deployment with Docker Compose, pre-flight checks, and health validation
|
|
|
|
DEPLOYMENT_ENV="${1:-production}"
|
|
REBUILD_FLAG="${2:---no-rebuild}"
|
|
|
|
# Color output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Logging functions
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
|
|
|
log_info "=== TFM aInventory Deployment Script ==="
|
|
log_info "Environment: $DEPLOYMENT_ENV"
|
|
log_info "Rebuild: $REBUILD_FLAG"
|
|
|
|
# ============================================================================
|
|
# STEP 1: Pre-flight checks
|
|
# ============================================================================
|
|
log_info "Step 1/10: Running pre-flight checks..."
|
|
|
|
command -v docker &> /dev/null || log_error "Docker not installed. Please install Docker 24.0+"
|
|
log_success " ✓ Docker is installed"
|
|
|
|
command -v docker-compose &> /dev/null || log_error "Docker Compose not installed. Please install Docker Compose 2.0+"
|
|
log_success " ✓ Docker Compose is installed"
|
|
|
|
[[ -f "docker-compose.yml" ]] || log_error "docker-compose.yml not found in current directory"
|
|
log_success " ✓ docker-compose.yml found"
|
|
|
|
[[ -f "inventory.env" ]] || log_warn "inventory.env not found; attempting to create from template..."
|
|
if [[ ! -f "inventory.env" ]] && [[ -f "inventory.env.template" ]]; then
|
|
cp inventory.env.template inventory.env
|
|
log_success " ✓ inventory.env created from template (review and customize)"
|
|
elif [[ ! -f "inventory.env" ]]; then
|
|
log_error "inventory.env not found and no template available. Create inventory.env before deploying."
|
|
fi
|
|
|
|
# ============================================================================
|
|
# STEP 2: Validate environment file
|
|
# ============================================================================
|
|
log_info "Step 2/10: Validating inventory.env..."
|
|
|
|
if [[ ! -f ".env.validation.sh" ]]; then
|
|
log_warn " .env.validation.sh not found; skipping validation"
|
|
else
|
|
bash .env.validation.sh || log_error "Environment validation failed"
|
|
fi
|
|
|
|
log_success " ✓ Environment variables validated"
|
|
|
|
# ============================================================================
|
|
# STEP 3: Check port availability
|
|
# ============================================================================
|
|
log_info "Step 3/10: Checking port availability..."
|
|
|
|
# Source inventory.env to get port values
|
|
source inventory.env
|
|
|
|
BACKEND_PORT=${BACKEND_PORT:-8000}
|
|
FRONTEND_PORT=${FRONTEND_PORT:-3000}
|
|
BACKEND_SSL_PORT=${BACKEND_SSL_PORT:-8918}
|
|
FRONTEND_SSL_PORT=${FRONTEND_SSL_PORT:-8919}
|
|
|
|
for port in "$BACKEND_PORT" "$FRONTEND_PORT" "$BACKEND_SSL_PORT" "$FRONTEND_SSL_PORT"; do
|
|
if command -v netstat &> /dev/null; then
|
|
if netstat -tuln 2>/dev/null | grep -q ":$port "; then
|
|
log_error "Port $port is already in use. Choose a different port in inventory.env"
|
|
fi
|
|
else
|
|
log_warn " netstat not available; skipping port check (ensure ports are available)"
|
|
fi
|
|
done
|
|
|
|
log_success " ✓ All required ports are available"
|
|
|
|
# ============================================================================
|
|
# STEP 4: Check disk space
|
|
# ============================================================================
|
|
log_info "Step 4/10: Checking disk space..."
|
|
|
|
AVAILABLE_SPACE=$(df . | awk 'NR==2 {print $4}')
|
|
REQUIRED_SPACE=$((10 * 1024 * 1024)) # 10GB in KB
|
|
|
|
if [[ $AVAILABLE_SPACE -lt $REQUIRED_SPACE ]]; then
|
|
log_warn " Available space: $(($AVAILABLE_SPACE / 1024 / 1024))GB (recommended: 10GB+)"
|
|
else
|
|
log_success " ✓ Sufficient disk space available ($(($AVAILABLE_SPACE / 1024 / 1024))GB)"
|
|
fi
|
|
|
|
# ============================================================================
|
|
# STEP 5: Build or pull images
|
|
# ============================================================================
|
|
log_info "Step 5/10: Building Docker images..."
|
|
|
|
if [[ "$REBUILD_FLAG" == "--rebuild" ]]; then
|
|
log_info " Building with --no-cache (full rebuild)..."
|
|
docker-compose build --no-cache || log_error "Docker build failed"
|
|
else
|
|
log_info " Building with layer cache (incremental)..."
|
|
docker-compose build || log_error "Docker build failed"
|
|
fi
|
|
|
|
log_success " ✓ Docker images built successfully"
|
|
|
|
# ============================================================================
|
|
# STEP 6: Create data directories
|
|
# ============================================================================
|
|
log_info "Step 6/10: Preparing data directories..."
|
|
|
|
mkdir -p data logs config
|
|
mkdir -p data/caddy_data data/caddy_config
|
|
chmod -R 777 data logs config
|
|
|
|
log_success " ✓ Data directories created with proper permissions"
|
|
|
|
# ============================================================================
|
|
# STEP 7: Initialize database
|
|
# ============================================================================
|
|
log_info "Step 7/10: Checking database initialization..."
|
|
|
|
if [[ ! -f "data/inventory.db" ]]; then
|
|
log_info " Database not found; will be initialized on first backend startup"
|
|
log_success " ✓ Database initialization scheduled"
|
|
else
|
|
log_success " ✓ Existing database found; reusing"
|
|
fi
|
|
|
|
# ============================================================================
|
|
# STEP 8: Start services
|
|
# ============================================================================
|
|
log_info "Step 8/10: Starting Docker services..."
|
|
|
|
docker-compose up -d || log_error "Failed to start Docker services"
|
|
log_success " ✓ Services started in background"
|
|
|
|
# ============================================================================
|
|
# STEP 9: Wait for health checks
|
|
# ============================================================================
|
|
log_info "Step 9/10: Waiting for services to become healthy (max 60 seconds)..."
|
|
|
|
max_attempts=30
|
|
attempt=0
|
|
all_healthy=false
|
|
|
|
while [[ $attempt -lt $max_attempts ]]; do
|
|
# Check if all 3 services are healthy
|
|
if docker-compose ps | grep -q "healthy.*healthy.*healthy"; then
|
|
all_healthy=true
|
|
break
|
|
fi
|
|
|
|
attempt=$((attempt + 1))
|
|
remaining=$((max_attempts - attempt))
|
|
log_info " Waiting... ($remaining attempts remaining)"
|
|
sleep 2
|
|
done
|
|
|
|
if [[ "$all_healthy" == true ]]; then
|
|
log_success " ✓ All services are healthy"
|
|
else
|
|
log_warn "Services did not become healthy within timeout. Checking logs..."
|
|
docker-compose logs --tail=50 || true
|
|
log_error "Service health check timeout. Review logs above."
|
|
fi
|
|
|
|
# ============================================================================
|
|
# STEP 10: Verify connectivity
|
|
# ============================================================================
|
|
log_info "Step 10/10: Verifying service connectivity..."
|
|
|
|
if curl -sf "http://localhost:${BACKEND_PORT}/health" &> /dev/null; then
|
|
log_success " ✓ Backend API responding at http://localhost:${BACKEND_PORT}/health"
|
|
else
|
|
log_warn " Backend health check failed; services may still be initializing"
|
|
fi
|
|
|
|
if curl -sf "http://localhost:${FRONTEND_PORT}/" &> /dev/null; then
|
|
log_success " ✓ Frontend responding at http://localhost:${FRONTEND_PORT}"
|
|
else
|
|
log_warn " Frontend check failed; container may still be initializing"
|
|
fi
|
|
|
|
# ============================================================================
|
|
# Summary
|
|
# ============================================================================
|
|
echo ""
|
|
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${GREEN}║${NC} Deployment completed successfully! ${GREEN}║${NC}"
|
|
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
echo "Access points:"
|
|
echo " Frontend (HTTP): http://localhost:${FRONTEND_PORT}"
|
|
echo " Backend (HTTP): http://localhost:${BACKEND_PORT}"
|
|
echo " API Docs: http://localhost:${BACKEND_PORT}/docs"
|
|
echo " Frontend (HTTPS): https://localhost:${FRONTEND_SSL_PORT}"
|
|
echo " Backend (HTTPS): https://localhost:${BACKEND_SSL_PORT}"
|
|
echo ""
|
|
echo "Useful commands:"
|
|
echo " View logs: docker-compose logs -f"
|
|
echo " Stop services: docker-compose down"
|
|
echo " Restart: docker-compose restart"
|
|
echo " Status: docker-compose ps"
|
|
echo ""
|
|
echo "For deployment in production ($DEPLOYMENT_ENV):"
|
|
echo " • Review and update JWT_SECRET_KEY in inventory.env"
|
|
echo " • Configure firewall to expose only required ports"
|
|
echo " • Set up automated backups (see docs/DEPLOYMENT_QUICKSTART.md)"
|
|
echo " • Monitor logs regularly: docker-compose logs -f"
|
|
echo ""
|
|
log_success "Deployment ready!"
|