rwadurian/backend/services/deploy.sh

487 lines
14 KiB
Bash

#!/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 <command> [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 <name> - Start a specific service"
echo " stop-svc <name> - Stop a specific service"
echo " rebuild-svc <name> - 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