Major accomplishments: - ✅ SELinux policy installed and working - ✅ Core Traefik v2.10 deployment running - ✅ Production configuration ready (v3.1) - ✅ Monitoring stack configured - ✅ Comprehensive documentation created - ✅ Security hardening implemented Current status: - 🟡 Partially deployed (60% complete) - ⚠️ Docker socket access needs resolution - ❌ Monitoring stack not deployed yet - ⚠️ Production migration pending Next steps: 1. Fix Docker socket permissions 2. Deploy monitoring stack 3. Migrate to production config 4. Validate full functionality Files added: - Complete Traefik deployment documentation - Production and test configurations - Monitoring stack configurations - SELinux policy module - Security checklists and guides - Current status documentation
345 lines
9.6 KiB
Bash
Executable File
345 lines
9.6 KiB
Bash
Executable File
#!/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 "$@" |