340 lines
8.4 KiB
Bash
340 lines
8.4 KiB
Bash
#!/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
|