monacousa-portal/deploy.sh

340 lines
8.4 KiB
Bash
Raw Permalink Normal View History

#!/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 <backup_file.sql.gz>"
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 <file> 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