#!/bin/bash # # RWA 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 # ./deploy.sh health # Check health of all services # set -e # =========================================================================== # Configuration # =========================================================================== SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="$SCRIPT_DIR/.env" COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" # 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 RWA 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) SERVICE_JWT_SECRET=$(generate_random_password) WALLET_ENCRYPTION_SALT=$(generate_random_password) BACKUP_ENCRYPTION_KEY=$(generate_hex_key) SHARE_MASTER_KEY=$(generate_hex_key) cat > "$ENV_FILE" << EOF # ============================================================================= # RWA Backend Services - Production Environment Configuration # ============================================================================= # Generated: $(date) # WARNING: Keep this file secure! Do not commit to version control! # ============================================================================= # PostgreSQL Database POSTGRES_USER=rwa_user POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # Redis (leave empty for no password) REDIS_PASSWORD= # JWT Configuration JWT_SECRET=${JWT_SECRET} # Service-to-Service Authentication SERVICE_JWT_SECRET=${SERVICE_JWT_SECRET} # Wallet Encryption WALLET_ENCRYPTION_SALT=${WALLET_ENCRYPTION_SALT} # Backup Encryption (256-bit hex key) BACKUP_ENCRYPTION_KEY=${BACKUP_ENCRYPTION_KEY} # MPC Share Master Key (256-bit hex key) SHARE_MASTER_KEY=${SHARE_MASTER_KEY} # MPC System Address (on 192.168.1.100) MPC_COORDINATOR_URL=http://192.168.1.100:8081 MPC_MESSAGE_ROUTER_URL=ws://192.168.1.100:8082 EOF chmod 600 "$ENV_FILE" log_info "Environment file created: $ENV_FILE" log_info "Secrets have been auto-generated" 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. Review and edit .env if needed" 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 # Function to create database if not exists create_database() { local database=$1 echo "Creating database: $database" psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL SELECT 'CREATE DATABASE $database' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$database')\gexec EOSQL } # Create all required databases for db in rwa_identity rwa_wallet rwa_mpc rwa_backup rwa_planting rwa_referral rwa_reward rwa_leaderboard rwa_reporting rwa_authorization; do create_database "$db" done echo "All databases created successfully!" DBSCRIPT chmod +x "$SCRIPT_DIR/scripts/init-databases.sh" log_info "Database init script created" } # =========================================================================== # Docker Compose Operations # =========================================================================== up() { log_step "Starting RWA 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 zookeeper kafka # Wait for infrastructure log_info "Waiting for infrastructure to be ready..." sleep 10 # 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 RWA Backend Services..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down log_info "All services stopped" } restart() { log_step "Restarting RWA 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)" } # =========================================================================== # Status and Monitoring # =========================================================================== status() { echo "" echo "============================================" echo "RWA 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() { local services=( "identity-service:3000" "wallet-service:3001" "backup-service:3002" "planting-service:3003" "referral-service:3004" "reward-service:3005" "mpc-service:3006" "leaderboard-service:3007" "reporting-service:3008" "authorization-service:3009" "admin-service:3010" ) for svc in "${services[@]}"; do name="${svc%%:*}" port="${svc##*:}" if curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port/health" 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 "" # Infrastructure health echo "Infrastructure:" if docker exec rwa-postgres pg_isready -U rwa_user &>/dev/null; then echo -e " ${GREEN}[OK]${NC} PostgreSQL" else echo -e " ${RED}[FAIL]${NC} PostgreSQL" fi if docker exec rwa-redis redis-cli ping &>/dev/null; then echo -e " ${GREEN}[OK]${NC} Redis" else echo -e " ${RED}[FAIL]${NC} Redis" fi if docker exec rwa-kafka kafka-topics --bootstrap-server localhost:9092 --list &>/dev/null; then echo -e " ${GREEN}[OK]${NC} Kafka" else echo -e " ${RED}[FAIL]${NC} Kafka" 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 # =========================================================================== migrate() { log_step "Running database migrations..." local services=( "identity-service" "wallet-service" "backup-service" "planting-service" "referral-service" "reward-service" "mpc-service" "leaderboard-service" "reporting-service" "authorization-service" ) for svc in "${services[@]}"; do log_info "Running migrations for $svc..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec "$svc" npx prisma migrate deploy 2>/dev/null || \ log_warn "Migration skipped for $svc (no migrations or service not running)" done log_info "Migrations complete" } # =========================================================================== # 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 log_info "Cleanup complete" else log_info "Cleanup cancelled" 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" if [ -z "$service" ]; then log_error "Please specify a service name" exit 1 fi log_info "Rebuilding $service..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build "$service" docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d "$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 ;; clean) clean ;; start-svc) start_service "$2" ;; stop-svc) stop_service "$2" ;; rebuild-svc) rebuild_service "$2" ;; *) echo "RWA 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 " migrate - Run database migrations" echo " clean - Remove all containers, volumes, and images" echo "" echo "Single Service Commands:" echo " start-svc - Start a specific service" echo " stop-svc - Stop a specific service" echo " rebuild-svc - Rebuild and restart a specific service" echo "" echo "Services:" echo " identity-service, wallet-service, backup-service, planting-service," echo " referral-service, reward-service, mpc-service, leaderboard-service," echo " reporting-service, authorization-service, admin-service" echo "" echo "Examples:" echo " $0 install # First time setup" echo " $0 build # Build images" echo " $0 up # Start all services" echo " $0 logs identity-service # View identity-service logs" echo " $0 rebuild-svc mpc-service # Rebuild specific service" echo "" exit 1 ;; esac