#!/bin/bash # Monaco USA Portal - Production Deployment Script # For Debian/Ubuntu Linux servers # # Usage: ./deploy.sh [command] # Commands: # setup - First-time setup (install Docker, configure firewall) # deploy - Build and start all services # update - Pull latest changes and rebuild portal # logs - View logs # status - Check service status # backup - Backup database # restore - Restore database from backup set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Configuration COMPOSE_FILE="docker-compose.nginx.yml" PROJECT_NAME="monacousa" log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check if running as root check_root() { if [ "$EUID" -ne 0 ]; then log_error "Please run as root (sudo ./deploy.sh)" exit 1 fi } # Install Docker and Docker Compose on Debian install_docker() { log_info "Installing Docker..." # Remove old versions apt-get remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true # Install dependencies apt-get update apt-get install -y \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-release # Add Docker's official GPG key install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpg # Add repository echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ tee /etc/apt/sources.list.d/docker.list > /dev/null # Install Docker apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # Start and enable Docker systemctl start docker systemctl enable docker log_info "Docker installed successfully" } # Configure firewall configure_firewall() { log_info "Configuring firewall..." # Install ufw if not present apt-get install -y ufw # Allow SSH, HTTP, HTTPS ufw allow ssh ufw allow http ufw allow https # Enable firewall ufw --force enable log_info "Firewall configured (SSH, HTTP, HTTPS allowed)" } # First-time setup setup() { check_root log_info "Starting first-time setup..." # Update system apt-get update && apt-get upgrade -y # Install Docker install_docker # Configure firewall configure_firewall # Install useful tools apt-get install -y htop nano git apache2-utils # Check for .env file if [ ! -f .env ]; then log_warn ".env file not found!" log_info "Copy .env.production.example to .env and configure it:" echo " cp .env.production.example .env" echo " nano .env" fi log_info "Setup complete! Next steps:" echo " 1. Configure .env file: nano .env" echo " 2. Deploy: ./deploy.sh deploy" } # Generate secrets helper generate_secrets() { log_info "Generating secrets..." echo "" echo "JWT_SECRET=$(openssl rand -base64 32)" echo "POSTGRES_PASSWORD=$(openssl rand -base64 32)" echo "SECRET_KEY_BASE=$(openssl rand -base64 64)" echo "" log_info "Copy these values to your .env file" } # Deploy/start services deploy() { log_info "Deploying Monaco USA Portal..." # Check for .env file if [ ! -f .env ]; then log_error ".env file not found! Copy .env.production.example to .env first." exit 1 fi # Build and start docker compose -f $COMPOSE_FILE -p $PROJECT_NAME build --no-cache portal docker compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d log_info "Deployment complete!" log_info "Waiting for services to be healthy..." sleep 10 # Show status docker compose -f $COMPOSE_FILE -p $PROJECT_NAME ps log_info "Portal should be available at https://\$(grep DOMAIN .env | cut -d '=' -f2)" } # Update and rebuild update() { log_info "Updating Monaco USA Portal..." # Pull latest code (if git repo) if [ -d .git ]; then git pull origin main fi # Rebuild only the portal service docker compose -f $COMPOSE_FILE -p $PROJECT_NAME build --no-cache portal # Restart portal with zero downtime docker compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d --no-deps portal log_info "Update complete!" } # View logs logs() { local service=${1:-""} if [ -z "$service" ]; then docker compose -f $COMPOSE_FILE -p $PROJECT_NAME logs -f --tail=100 else docker compose -f $COMPOSE_FILE -p $PROJECT_NAME logs -f --tail=100 $service fi } # Check status status() { log_info "Service Status:" docker compose -f $COMPOSE_FILE -p $PROJECT_NAME ps echo "" log_info "Resource Usage:" docker stats --no-stream $(docker compose -f $COMPOSE_FILE -p $PROJECT_NAME ps -q) } # Backup database backup() { local backup_file="backup_$(date +%Y%m%d_%H%M%S).sql" log_info "Backing up database to $backup_file..." docker compose -f $COMPOSE_FILE -p $PROJECT_NAME exec -T db \ pg_dump -U postgres postgres > "$backup_file" # Compress gzip "$backup_file" log_info "Backup complete: ${backup_file}.gz" } # Restore database restore() { local backup_file=$1 if [ -z "$backup_file" ]; then log_error "Usage: ./deploy.sh restore " exit 1 fi log_warn "This will overwrite the current database!" read -p "Are you sure? (y/N) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi log_info "Restoring database from $backup_file..." # Decompress if needed if [[ "$backup_file" == *.gz ]]; then gunzip -c "$backup_file" | docker compose -f $COMPOSE_FILE -p $PROJECT_NAME exec -T db \ psql -U postgres postgres else cat "$backup_file" | docker compose -f $COMPOSE_FILE -p $PROJECT_NAME exec -T db \ psql -U postgres postgres fi log_info "Restore complete!" } # Stop all services stop() { log_info "Stopping all services..." docker compose -f $COMPOSE_FILE -p $PROJECT_NAME down log_info "All services stopped" } # Restart all services restart() { log_info "Restarting all services..." docker compose -f $COMPOSE_FILE -p $PROJECT_NAME restart log_info "All services restarted" } # Clean up unused Docker resources cleanup() { log_info "Cleaning up unused Docker resources..." docker system prune -af --volumes log_info "Cleanup complete" } # Show help help() { echo "Monaco USA Portal - Deployment Script" echo "" echo "Usage: ./deploy.sh [command]" echo "" echo "Commands:" echo " setup First-time server setup (install Docker, firewall)" echo " generate-secrets Generate random secrets for .env" echo " deploy Build and start all services" echo " update Pull latest code and rebuild portal" echo " stop Stop all services" echo " restart Restart all services" echo " status Show service status and resource usage" echo " logs [service] View logs (optionally for specific service)" echo " backup Backup database to file" echo " restore Restore database from backup" echo " cleanup Remove unused Docker resources" echo " help Show this help message" echo "" echo "Examples:" echo " sudo ./deploy.sh setup # First-time setup" echo " ./deploy.sh deploy # Deploy the portal" echo " ./deploy.sh logs portal # View portal logs" echo " ./deploy.sh backup # Backup database" } # Main command handler case "${1:-help}" in setup) setup ;; generate-secrets) generate_secrets ;; deploy) deploy ;; update) update ;; stop) stop ;; restart) restart ;; status) status ;; logs) logs $2 ;; backup) backup ;; restore) restore $2 ;; cleanup) cleanup ;; help|--help|-h) help ;; *) log_error "Unknown command: $1" help exit 1 ;; esac