#!/bin/bash # Traefik Production Deployment Script # Comprehensive deployment with security, monitoring, and validation set -euo pipefail # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" DOMAIN="${DOMAIN:-localhost}" EMAIL="${EMAIL:-admin@localhost}" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Logging log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Validation functions check_prerequisites() { log_info "Checking prerequisites..." # Check if running as root if [[ $EUID -eq 0 ]]; then log_error "This script should not be run as root for security reasons" exit 1 fi # Check Docker if ! command -v docker &> /dev/null; then log_error "Docker is not installed" exit 1 fi # Check Docker Swarm if ! docker info --format '{{.Swarm.LocalNodeState}}' | grep -q "active"; then log_error "Docker Swarm is not initialized" log_info "Initialize with: docker swarm init" exit 1 fi # Check SELinux if command -v getenforce &> /dev/null; then SELINUX_STATUS=$(getenforce) if [[ "$SELINUX_STATUS" != "Enforcing" && "$SELINUX_STATUS" != "Permissive" ]]; then log_error "SELinux is disabled. Enable SELinux for production security." exit 1 fi log_info "SELinux status: $SELINUX_STATUS" fi # Check required ports for port in 80 443 8080; do if netstat -tlnp | grep -q ":$port "; then log_warning "Port $port is already in use" fi done log_success "Prerequisites check completed" } install_selinux_policy() { log_info "Installing SELinux policy for Traefik Docker access..." if [[ ! -f "$PROJECT_ROOT/selinux/install_selinux_policy.sh" ]]; then log_error "SELinux policy installation script not found" exit 1 fi cd "$PROJECT_ROOT/selinux" chmod +x install_selinux_policy.sh if ./install_selinux_policy.sh; then log_success "SELinux policy installed successfully" else log_error "Failed to install SELinux policy" exit 1 fi } create_directories() { log_info "Creating required directories..." # Traefik directories sudo mkdir -p /opt/traefik/{letsencrypt,logs} # Monitoring directories sudo mkdir -p /opt/monitoring/{prometheus/{data,config},grafana/{data,config}} sudo mkdir -p /opt/monitoring/{alertmanager/{data,config},loki/data,promtail/config} # Set permissions sudo chown -R $(id -u):$(id -g) /opt/traefik sudo chown -R 65534:65534 /opt/monitoring/prometheus sudo chown -R 472:472 /opt/monitoring/grafana sudo chown -R 65534:65534 /opt/monitoring/alertmanager sudo chown -R 10001:10001 /opt/monitoring/loki log_success "Directories created with proper permissions" } setup_network() { log_info "Setting up Docker overlay network..." if docker network ls | grep -q "traefik-public"; then log_warning "Network traefik-public already exists" else docker network create \ --driver overlay \ --attachable \ --subnet 10.0.1.0/24 \ traefik-public log_success "Created traefik-public overlay network" fi } deploy_configurations() { log_info "Deploying monitoring configurations..." # Copy monitoring configs sudo cp "$PROJECT_ROOT/configs/monitoring/prometheus.yml" /opt/monitoring/prometheus/config/ sudo cp "$PROJECT_ROOT/configs/monitoring/traefik_rules.yml" /opt/monitoring/prometheus/config/ sudo cp "$PROJECT_ROOT/configs/monitoring/alertmanager.yml" /opt/monitoring/alertmanager/config/ # Create environment file cat > /tmp/traefik.env << EOF DOMAIN=$DOMAIN EMAIL=$EMAIL EOF sudo mv /tmp/traefik.env /opt/traefik/.env log_success "Configuration files deployed" } deploy_traefik() { log_info "Deploying Traefik stack..." export DOMAIN EMAIL if docker stack deploy -c "$PROJECT_ROOT/stacks/core/traefik-production.yml" traefik; then log_success "Traefik stack deployed successfully" else log_error "Failed to deploy Traefik stack" exit 1 fi } deploy_monitoring() { log_info "Deploying monitoring stack..." export DOMAIN if docker stack deploy -c "$PROJECT_ROOT/stacks/monitoring/traefik-monitoring.yml" monitoring; then log_success "Monitoring stack deployed successfully" else log_error "Failed to deploy monitoring stack" exit 1 fi } wait_for_services() { log_info "Waiting for services to become healthy..." local max_attempts=30 local attempt=0 while [[ $attempt -lt $max_attempts ]]; do local healthy_count=0 # Check Traefik if curl -sf http://localhost:8080/ping >/dev/null 2>&1; then ((healthy_count++)) fi # Check Prometheus if curl -sf http://localhost:9090/-/healthy >/dev/null 2>&1; then ((healthy_count++)) fi if [[ $healthy_count -eq 2 ]]; then log_success "All services are healthy" return 0 fi log_info "Attempt $((attempt + 1))/$max_attempts - $healthy_count/2 services healthy" sleep 10 ((attempt++)) done log_warning "Some services may not be healthy yet" } validate_deployment() { log_info "Validating deployment..." local validation_passed=true # Test Traefik API if curl -sf http://localhost:8080/api/overview >/dev/null; then log_success "✓ Traefik API accessible" else log_error "✗ Traefik API not accessible" validation_passed=false fi # Test authentication (should fail without credentials) if curl -sf "http://localhost:8080/dashboard/" >/dev/null; then log_error "✗ Dashboard accessible without authentication" validation_passed=false else log_success "✓ Dashboard requires authentication" fi # Test authentication with credentials if curl -sf -u "admin:secure_password_2024" "http://localhost:8080/dashboard/" >/dev/null; then log_success "✓ Dashboard accessible with correct credentials" else log_error "✗ Dashboard not accessible with credentials" validation_passed=false fi # Test HTTPS redirect local redirect_response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost/") if [[ "$redirect_response" == "301" || "$redirect_response" == "302" ]]; then log_success "✓ HTTP to HTTPS redirect working" else log_warning "⚠ HTTP redirect response: $redirect_response" fi # Test Prometheus metrics if curl -sf http://localhost:8080/metrics | grep -q "traefik_"; then log_success "✓ Prometheus metrics available" else log_error "✗ Prometheus metrics not available" validation_passed=false fi # Check Docker socket access if docker service logs traefik_traefik --tail 10 | grep -q "permission denied"; then log_error "✗ Docker socket permission issues detected" validation_passed=false else log_success "✓ Docker socket access working" fi if [[ "$validation_passed" == true ]]; then log_success "All validation checks passed" return 0 else log_error "Some validation checks failed" return 1 fi } generate_summary() { log_info "Generating deployment summary..." cat << EOF 🎉 Traefik Production Deployment Complete! 📊 Services Deployed: • Traefik v3.1 (Load Balancer & Reverse Proxy) • Prometheus (Metrics & Alerting) • Grafana (Monitoring Dashboards) • AlertManager (Alert Management) • Loki + Promtail (Log Aggregation) 🔐 Access Points: • Traefik Dashboard: https://traefik.$DOMAIN/dashboard/ • Prometheus: https://prometheus.$DOMAIN • Grafana: https://grafana.$DOMAIN • AlertManager: https://alertmanager.$DOMAIN 🔑 Default Credentials: • Username: admin • Password: secure_password_2024 • ⚠️ CHANGE THESE IN PRODUCTION! 🛡️ Security Features: • ✅ SELinux policy installed • ✅ TLS/SSL with automatic certificates • ✅ Security headers enabled • ✅ Rate limiting configured • ✅ Authentication required • ✅ Monitoring & alerting active 📝 Next Steps: 1. Update DNS records to point to this server 2. Change default passwords 3. Configure alert notifications 4. Review security checklist: TRAEFIK_SECURITY_CHECKLIST.md 5. Set up regular backups 📚 Documentation: • Full Guide: TRAEFIK_DEPLOYMENT_GUIDE.md • Security Checklist: TRAEFIK_SECURITY_CHECKLIST.md EOF } # Main deployment function main() { log_info "Starting Traefik Production Deployment" log_info "Domain: $DOMAIN" log_info "Email: $EMAIL" check_prerequisites install_selinux_policy create_directories setup_network deploy_configurations deploy_traefik deploy_monitoring wait_for_services if validate_deployment; then generate_summary log_success "🎉 Deployment completed successfully!" else log_error "❌ Deployment validation failed. Check logs for details." exit 1 fi } # Run main function main "$@"