#!/bin/bash # # IT0 Backend Services - Deployment Script # ========================================= # # Usage: # ./deploy.sh install # First time setup (generate secrets, init databases) # ./deploy.sh up # Start all services # ./deploy.sh down # Stop all services # ./deploy.sh restart # Restart all services # ./deploy.sh status # Show service status # ./deploy.sh logs [svc] # View logs (optional: specific service) # ./deploy.sh build # Rebuild all images # ./deploy.sh migrate # Run database migrations (TypeORM) # ./deploy.sh health # Check health of all services # # Infrastructure: # ./deploy.sh infra-up # Start only infrastructure (postgres, redis) # ./deploy.sh infra-down # Stop infrastructure # ./deploy.sh infra-restart # Restart infrastructure # ./deploy.sh infra-status # Show infrastructure status # ./deploy.sh infra-logs # View infrastructure logs # # Voice Service (GPU): # ./deploy.sh voice-up # Start voice service with GPU support # ./deploy.sh voice-down # Stop voice service # ./deploy.sh voice-logs # View voice service logs # # SSL (Let's Encrypt): # ./deploy.sh ssl-init # Obtain SSL certificates for both domains # ./deploy.sh ssl-up # Start with Nginx + SSL # ./deploy.sh ssl-renew # Manually renew certificates # ./deploy.sh ssl-status # Check certificate status # set -e # =========================================================================== # Configuration # =========================================================================== SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" ENV_FILE="$SCRIPT_DIR/.env" COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" COMPOSE_VOICE_FILE="$SCRIPT_DIR/docker-compose.voice.yml" COMPOSE_SSL_FILE="$SCRIPT_DIR/docker-compose.ssl.yml" # Domain configuration API_DOMAIN="${API_DOMAIN:-it0api.szaiai.com}" WEB_DOMAIN="${WEB_DOMAIN:-it0.szaiai.com}" CERT_EMAIL="${CERT_EMAIL:-admin@szaiai.com}" # Container name prefix CONTAINER_PREFIX="it0" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } # =========================================================================== # Helper Functions # =========================================================================== generate_random_password() { openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32 } generate_hex_key() { openssl rand -hex 32 } check_docker() { if ! command -v docker &> /dev/null; then log_error "Docker is not installed. Please install Docker first." exit 1 fi if ! docker compose version &> /dev/null; then log_error "Docker Compose is not installed. Please install Docker Compose first." exit 1 fi log_info "Docker version: $(docker --version)" log_info "Docker Compose version: $(docker compose version --short)" } # =========================================================================== # Install / Initialize # =========================================================================== install() { log_step "Installing IT0 Backend Services..." check_docker # Generate .env file if not exists if [ ! -f "$ENV_FILE" ]; then log_step "Generating secure configuration..." POSTGRES_PASSWORD=$(generate_random_password) JWT_SECRET=$(generate_random_password) JWT_REFRESH_SECRET=$(generate_random_password) VAULT_MASTER_KEY=$(generate_hex_key) cat > "$ENV_FILE" << EOF # ============================================================================= # IT0 Backend Services - Production Environment Configuration # ============================================================================= # Generated: $(date) # WARNING: Keep this file secure! Do not commit to version control! # ============================================================================= # PostgreSQL Database POSTGRES_USER=it0 POSTGRES_PASSWORD=${POSTGRES_PASSWORD} POSTGRES_DB=it0 # Redis (leave empty for no password) REDIS_PASSWORD= # JWT Configuration JWT_SECRET=${JWT_SECRET} JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET} # Vault Master Key (for credential encryption in inventory-service) VAULT_MASTER_KEY=${VAULT_MASTER_KEY} # Anthropic API Key (for agent-service AI capabilities) ANTHROPIC_API_KEY= # Twilio (for comm-service SMS/voice calls, optional) TWILIO_ACCOUNT_SID= TWILIO_AUTH_TOKEN= TWILIO_PHONE_NUMBER= # Voice Service Configuration WHISPER_MODEL=large-v3 KOKORO_MODEL=kokoro-82m VOICE_DEVICE=cpu EOF chmod 600 "$ENV_FILE" log_info "Environment file created: $ENV_FILE" log_info "Secrets have been auto-generated" log_warn "Please set ANTHROPIC_API_KEY in $ENV_FILE before starting services" else log_info "Environment file already exists: $ENV_FILE" fi # Create scripts directory mkdir -p "$SCRIPT_DIR/scripts" # Create database init script create_db_init_script log_info "Installation complete!" log_info "" log_info "Next steps:" log_info " 1. Edit .env and set ANTHROPIC_API_KEY" log_info " 2. Run: ./deploy.sh build" log_info " 3. Run: ./deploy.sh up" } create_db_init_script() { cat > "$SCRIPT_DIR/scripts/init-databases.sh" << 'DBSCRIPT' #!/bin/bash set -e # IT0 uses schema-per-tenant with a single database # This script ensures the main database exists and creates # required schemas for multi-tenant isolation echo "Initializing IT0 database..." psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL -- Create shared schema for cross-tenant data CREATE SCHEMA IF NOT EXISTS shared; -- Create default tenant schema CREATE SCHEMA IF NOT EXISTS tenant_default; -- Grant permissions GRANT ALL ON SCHEMA shared TO $POSTGRES_USER; GRANT ALL ON SCHEMA tenant_default TO $POSTGRES_USER; EOSQL echo "Database initialization complete!" DBSCRIPT chmod +x "$SCRIPT_DIR/scripts/init-databases.sh" log_info "Database init script created" } # =========================================================================== # Docker Compose Operations # =========================================================================== up() { log_step "Starting IT0 Backend Services..." if [ ! -f "$ENV_FILE" ]; then log_error "Environment file not found. Run './deploy.sh install' first." exit 1 fi # Start infrastructure first log_info "Starting infrastructure services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d postgres redis # Wait for infrastructure log_info "Waiting for infrastructure to be ready..." wait_for_postgres wait_for_redis # Start application services log_info "Starting application services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d log_info "All services started!" log_info "" log_info "Check status with: ./deploy.sh status" log_info "View logs with: ./deploy.sh logs" } down() { log_step "Stopping IT0 Backend Services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down log_info "All services stopped" } restart() { log_step "Restarting IT0 Backend Services..." down sleep 3 up } build() { log_step "Building Docker images..." if [ ! -f "$ENV_FILE" ]; then log_error "Environment file not found. Run './deploy.sh install' first." exit 1 fi docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build --parallel log_info "All images built successfully" } build_no_cache() { log_step "Building Docker images (no cache)..." if [ ! -f "$ENV_FILE" ]; then log_error "Environment file not found. Run './deploy.sh install' first." exit 1 fi docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build --no-cache --parallel log_info "All images built successfully (no cache)" } # =========================================================================== # Wait Helpers # =========================================================================== wait_for_postgres() { log_info "Waiting for PostgreSQL..." for i in {1..30}; do if docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T postgres pg_isready -U it0 &>/dev/null; then log_info "PostgreSQL is ready!" return fi sleep 2 done log_warn "PostgreSQL not ready after 60s, continuing anyway..." } wait_for_redis() { log_info "Waiting for Redis..." for i in {1..30}; do if docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T redis redis-cli ping &>/dev/null; then log_info "Redis is ready!" return fi sleep 2 done log_warn "Redis not ready after 60s, continuing anyway..." } # =========================================================================== # Status and Monitoring # =========================================================================== status() { echo "" echo "============================================" echo "IT0 Backend Services Status" echo "============================================" echo "" docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps echo "" echo "============================================" echo "Service Health Check" echo "============================================" echo "" health } health() { # Format: "service-name:port:health-endpoint" local services=( "auth-service:13001:/api/health" "agent-service:13002:/api/health" "ops-service:13003:/api/health" "inventory-service:13004:/api/health" "monitor-service:13005:/api/health" "comm-service:13006:/api/health" "audit-service:13007:/api/health" "voice-service:13008:/health" "api-gateway:18000:/status" ) echo "Application Services:" for svc in "${services[@]}"; do name="${svc%%:*}" rest="${svc#*:}" port="${rest%%:*}" endpoint="${rest#*:}" if curl -s -o /dev/null -w "%{http_code}" "http://localhost:${port}${endpoint}" 2>/dev/null | grep -q "200"; then echo -e " ${GREEN}[OK]${NC} $name (port $port)" else echo -e " ${RED}[FAIL]${NC} $name (port $port)" fi done echo "" echo "Infrastructure:" if docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T postgres pg_isready -U it0 &>/dev/null; then echo -e " ${GREEN}[OK]${NC} PostgreSQL (port 15432)" else echo -e " ${RED}[FAIL]${NC} PostgreSQL (port 15432)" fi if docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T redis redis-cli ping &>/dev/null; then echo -e " ${GREEN}[OK]${NC} Redis (port 16379)" else echo -e " ${RED}[FAIL]${NC} Redis (port 16379)" fi } logs() { local service="$1" if [ -n "$service" ]; then docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f "$service" else docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f fi } # =========================================================================== # Database Operations (TypeORM) # =========================================================================== migrate() { log_step "Running TypeORM migrations..." local services=( "auth-service" "agent-service" "ops-service" "inventory-service" "monitor-service" "comm-service" "audit-service" ) for svc in "${services[@]}"; do log_info "Running migrations for $svc..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T "$svc" \ npx typeorm migration:run -d dist/infrastructure/database/data-source.js 2>/dev/null || \ log_warn "Migration skipped for $svc (no migrations or service not running)" done log_info "Migrations complete" } migrate_generate() { local service="$1" local name="$2" if [ -z "$service" ] || [ -z "$name" ]; then log_error "Usage: ./deploy.sh migrate-generate " exit 1 fi log_step "Generating migration for $service: $name..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T "$service" \ npx typeorm migration:generate -d dist/infrastructure/database/data-source.js \ "src/infrastructure/database/migrations/$name" log_info "Migration generated for $service" } migrate_revert() { local service="$1" if [ -z "$service" ]; then log_error "Usage: ./deploy.sh migrate-revert " exit 1 fi log_warn "This will revert the last migration for $service!" read -p "Are you sure? (y/N): " confirm if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then log_info "Migration revert cancelled" exit 0 fi log_step "Reverting last migration for $service..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T "$service" \ npx typeorm migration:revert -d dist/infrastructure/database/data-source.js log_info "Migration reverted for $service" } schema_sync() { local service="$1" if [ -z "$service" ]; then log_error "Usage: ./deploy.sh schema-sync " exit 1 fi log_warn "This will force sync schema for $service (may cause data loss)!" read -p "Are you sure? (y/N): " confirm if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then log_info "Schema sync cancelled" exit 0 fi log_step "Syncing schema for $service..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T "$service" \ npx typeorm schema:sync -d dist/infrastructure/database/data-source.js log_info "Schema sync complete for $service" } # =========================================================================== # Cleanup # =========================================================================== clean() { log_warn "This will remove all containers, volumes, and images!" read -p "Are you sure? (y/N): " confirm if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then log_step "Cleaning up..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down -v --rmi all docker image prune -f log_info "Cleanup complete" else log_info "Cleanup cancelled" fi } # =========================================================================== # Infrastructure Operations # =========================================================================== infra_up() { log_step "Starting infrastructure services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d postgres redis wait_for_postgres wait_for_redis log_info "Infrastructure services started" } infra_down() { log_step "Stopping infrastructure services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop postgres redis log_info "Infrastructure services stopped" } infra_restart() { log_step "Restarting infrastructure services..." infra_down sleep 3 infra_up } infra_status() { echo "" echo "============================================" echo "Infrastructure Status" echo "============================================" echo "" docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps postgres redis echo "" echo "Health Check:" if docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T postgres pg_isready -U it0 &>/dev/null; then echo -e " ${GREEN}[OK]${NC} PostgreSQL (port 15432)" else echo -e " ${RED}[FAIL]${NC} PostgreSQL (port 15432)" fi if docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T redis redis-cli ping &>/dev/null; then echo -e " ${GREEN}[OK]${NC} Redis (port 16379)" else echo -e " ${RED}[FAIL]${NC} Redis (port 16379)" fi } infra_logs() { docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f postgres redis } infra_clean() { log_warn "This will remove infrastructure containers and ALL DATA (postgres, redis)!" log_warn "All databases will be DELETED!" read -p "Are you sure? (y/N): " confirm if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then log_step "Stopping infrastructure services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop postgres redis log_step "Removing infrastructure containers..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" rm -f postgres redis log_step "Removing infrastructure volumes..." docker volume rm -f docker_postgres_data 2>/dev/null || true log_info "Infrastructure cleanup complete" log_info "" log_info "To reinstall, run:" log_info " ./deploy.sh infra-up" log_info " ./deploy.sh migrate" else log_info "Cleanup cancelled" fi } infra_reset() { log_warn "This will RESET all infrastructure (clean + reinstall)!" log_warn "All databases will be DELETED and recreated!" read -p "Are you sure? (y/N): " confirm if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then log_step "Stopping infrastructure services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop postgres redis log_step "Removing infrastructure containers..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" rm -f postgres redis log_step "Removing infrastructure volumes..." docker volume rm -f docker_postgres_data 2>/dev/null || true log_step "Starting fresh infrastructure..." sleep 3 infra_up log_info "Infrastructure reset complete!" log_info "" log_info "Next steps:" log_info " 1. Restart application services: ./deploy.sh restart" log_info " 2. Run migrations: ./deploy.sh migrate" else log_info "Reset cancelled" fi } # =========================================================================== # Voice Service Operations (GPU support) # =========================================================================== voice_up() { log_step "Starting voice service with GPU support..." docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_VOICE_FILE" --env-file "$ENV_FILE" up -d voice-service log_info "Voice service started (GPU mode)" } voice_down() { log_step "Stopping voice service..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop voice-service log_info "Voice service stopped" } voice_logs() { docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f voice-service } voice_rebuild() { log_step "Rebuilding voice service..." local no_cache="$1" if [ "$no_cache" = "--no-cache" ]; then docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_VOICE_FILE" --env-file "$ENV_FILE" build --no-cache voice-service else docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_VOICE_FILE" --env-file "$ENV_FILE" build voice-service fi docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_VOICE_FILE" --env-file "$ENV_FILE" up -d voice-service log_info "Voice service rebuilt and started" } # =========================================================================== # SSL / Let's Encrypt Operations # =========================================================================== ssl_init() { log_step "Obtaining Let's Encrypt SSL certificates..." log_info "Domains: $API_DOMAIN, $WEB_DOMAIN" log_info "Email: $CERT_EMAIL" if [ ! -f "$ENV_FILE" ]; then log_error "Environment file not found. Run './deploy.sh install' first." exit 1 fi # Ensure services are running (nginx needs upstream targets) log_info "Ensuring backend services are running..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d # Step 1: Start nginx with HTTP-only config for ACME challenge log_info "Starting Nginx with HTTP-only config for certificate verification..." cp "$SCRIPT_DIR/nginx/nginx-init.conf" "$SCRIPT_DIR/nginx/nginx-active.conf" docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" up -d nginx sleep 3 # Step 2: Obtain certificate for API domain log_step "Obtaining certificate for $API_DOMAIN..." docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" run --rm certbot \ certbot certonly --webroot \ --webroot-path=/var/www/certbot \ --email "$CERT_EMAIL" \ --agree-tos \ --no-eff-email \ -d "$API_DOMAIN" if [ $? -eq 0 ]; then log_info "Certificate obtained for $API_DOMAIN" else log_error "Failed to obtain certificate for $API_DOMAIN" log_error "Make sure DNS for $API_DOMAIN points to this server" exit 1 fi # Step 3: Obtain certificate for Web Admin domain log_step "Obtaining certificate for $WEB_DOMAIN..." docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" run --rm certbot \ certbot certonly --webroot \ --webroot-path=/var/www/certbot \ --email "$CERT_EMAIL" \ --agree-tos \ --no-eff-email \ -d "$WEB_DOMAIN" if [ $? -eq 0 ]; then log_info "Certificate obtained for $WEB_DOMAIN" else log_error "Failed to obtain certificate for $WEB_DOMAIN" log_error "Make sure DNS for $WEB_DOMAIN points to this server" exit 1 fi # Step 4: Switch to full SSL nginx config and reload log_step "Switching to full SSL configuration..." rm -f "$SCRIPT_DIR/nginx/nginx-active.conf" docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" up -d nginx docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" exec -T nginx nginx -s reload 2>/dev/null || \ docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" restart nginx # Start certbot auto-renewal sidecar docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" up -d certbot log_info "" log_info "SSL certificates obtained successfully!" log_info " API: https://$API_DOMAIN" log_info " Admin: https://$WEB_DOMAIN" log_info "" log_info "Certificates will auto-renew via the certbot container." } ssl_up() { log_step "Starting services with SSL (Nginx + Certbot)..." if [ ! -f "$ENV_FILE" ]; then log_error "Environment file not found. Run './deploy.sh install' first." exit 1 fi # Start all services including nginx + certbot docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" up -d log_info "All services started with SSL!" log_info " API: https://$API_DOMAIN" log_info " Admin: https://$WEB_DOMAIN" } ssl_down() { log_step "Stopping all services including SSL proxy..." docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" down log_info "All services stopped" } ssl_renew() { log_step "Manually renewing SSL certificates..." docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" run --rm certbot \ certbot renew --webroot -w /var/www/certbot # Reload nginx to pick up new certs docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" exec -T nginx nginx -s reload log_info "Certificate renewal complete" } ssl_status() { echo "" echo "============================================" echo "SSL Certificate Status" echo "============================================" echo "" for domain in "$API_DOMAIN" "$WEB_DOMAIN"; do echo "Domain: $domain" docker compose -f "$COMPOSE_FILE" -f "$COMPOSE_SSL_FILE" --env-file "$ENV_FILE" run --rm certbot \ certbot certificates -d "$domain" 2>/dev/null || echo " No certificate found" echo "" done echo "Nginx Status:" if docker ps --filter "name=it0-nginx" --format "{{.Status}}" | grep -q "Up"; then echo -e " ${GREEN}[OK]${NC} Nginx is running" else echo -e " ${RED}[FAIL]${NC} Nginx is not running" fi echo "Certbot Status:" if docker ps --filter "name=it0-certbot" --format "{{.Status}}" | grep -q "Up"; then echo -e " ${GREEN}[OK]${NC} Certbot auto-renewal is active" else echo -e " ${YELLOW}[WARN]${NC} Certbot auto-renewal is not running" fi } # =========================================================================== # Single Service Operations # =========================================================================== start_service() { local service="$1" if [ -z "$service" ]; then log_error "Please specify a service name" exit 1 fi log_info "Starting $service..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d "$service" } stop_service() { local service="$1" if [ -z "$service" ]; then log_error "Please specify a service name" exit 1 fi log_info "Stopping $service..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop "$service" } rebuild_service() { local service="$1" local no_cache="$2" if [ -z "$service" ]; then log_error "Please specify a service name" exit 1 fi log_info "Rebuilding $service..." if [ "$no_cache" = "--no-cache" ]; then log_info "Building without cache..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build --no-cache "$service" else docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build "$service" fi docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d "$service" } service_logs() { local service="$1" if [ -z "$service" ]; then log_error "Please specify a service name" exit 1 fi docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f "$service" } # =========================================================================== # Main # =========================================================================== case "${1:-}" in install) install ;; up|start) up ;; down|stop) down ;; restart) restart ;; build) build ;; build-no-cache) build_no_cache ;; status|ps) status ;; health) health ;; logs) logs "$2" ;; migrate) migrate ;; migrate-generate) migrate_generate "$2" "$3" ;; migrate-revert) migrate_revert "$2" ;; schema-sync) schema_sync "$2" ;; clean) clean ;; start-svc) start_service "$2" ;; stop-svc) stop_service "$2" ;; rebuild-svc) rebuild_service "$2" "$3" ;; svc-logs) service_logs "$2" ;; infra-up) infra_up ;; infra-down) infra_down ;; infra-restart) infra_restart ;; infra-status) infra_status ;; infra-logs) infra_logs ;; infra-clean) infra_clean ;; infra-reset) infra_reset ;; voice-up) voice_up ;; voice-down) voice_down ;; voice-logs) voice_logs ;; voice-rebuild) voice_rebuild "$2" ;; ssl-init) ssl_init ;; ssl-up) ssl_up ;; ssl-down) ssl_down ;; ssl-renew) ssl_renew ;; ssl-status) ssl_status ;; *) echo "IT0 Backend Services Deployment Script" echo "" echo "Usage: $0 [options]" echo "" echo "Commands:" echo " install - First time setup (generate secrets, create configs)" echo " up/start - Start all services" echo " down/stop - Stop all services" echo " restart - Restart all services" echo " build - Build all Docker images" echo " build-no-cache - Build all images without cache" echo " status/ps - Show service status" echo " health - Check health of all services" echo " logs [svc] - View logs (optionally for specific service)" echo " clean - Remove all containers, volumes, and images" echo "" echo "Database Commands (TypeORM):" echo " migrate - Run migrations for all services" echo " migrate-generate - Generate a new migration" echo " migrate-revert - Revert last migration" echo " schema-sync - Force sync schema (DEV ONLY)" echo "" echo "Single Service Commands:" echo " start-svc - Start a specific service" echo " stop-svc - Stop a specific service" echo " rebuild-svc [--no-cache] - Rebuild and restart a specific service" echo " svc-logs - View logs for a specific service" echo "" echo "Infrastructure Commands:" echo " infra-up - Start infrastructure (postgres, redis)" echo " infra-down - Stop infrastructure services" echo " infra-restart - Restart infrastructure services" echo " infra-status - Show infrastructure status and health" echo " infra-logs - View infrastructure logs" echo " infra-clean - Remove infrastructure containers and volumes (DELETES DATA)" echo " infra-reset - Clean and reinstall infrastructure (DELETES DATA)" echo "" echo "Voice Service Commands (GPU):" echo " voice-up - Start voice service with GPU support" echo " voice-down - Stop voice service" echo " voice-logs - View voice service logs" echo " voice-rebuild [--no-cache] - Rebuild voice service" echo "" echo "SSL / Let's Encrypt Commands:" echo " ssl-init - Obtain SSL certificates for both domains" echo " ssl-up - Start all services with Nginx SSL proxy" echo " ssl-down - Stop all services including SSL proxy" echo " ssl-renew - Manually renew certificates" echo " ssl-status - Check certificate and proxy status" echo "" echo "Domains:" echo " API: https://it0api.szaiai.com (configurable via API_DOMAIN)" echo " Admin: https://it0.szaiai.com (configurable via WEB_DOMAIN)" echo "" echo "Services:" echo " auth-service, agent-service, ops-service, inventory-service," echo " monitor-service, comm-service, audit-service, voice-service," echo " api-gateway, web-admin" echo "" echo "Examples:" echo " $0 install # First time setup" echo " $0 build # Build images" echo " $0 up # Start all services" echo " $0 logs agent-service # View agent-service logs" echo " $0 rebuild-svc auth-service # Rebuild specific service" echo " $0 voice-up # Start voice with GPU" echo " $0 migrate # Run all migrations" echo " $0 migrate-generate auth-service AddUserTable # Generate migration" echo " $0 ssl-init # First time SSL setup" echo " $0 ssl-up # Start with SSL" echo "" exit 1 ;; esac