#!/bin/bash ################################################################################ # WOODPECKER CI PRODUCTION DEPLOYMENT SCRIPT ################################################################################ # # ⚠️ WARNING: THIS SCRIPT IS EXCLUSIVELY FOR WOODPECKER CI USE # # This script is designed to run within the Woodpecker CI environment with # specific environment variables and Docker socket access. # # 🚫 DO NOT RUN THIS ON A DEVELOPER WORKSTATION # 🚫 This will attempt to remove production Docker stacks and secrets # 🚫 This requires access to production Docker swarm manager nodes # # This script handles: # - Production stack removal and cleanup # - Docker secrets recreation with fresh values # - New stack deployment with verification # - Health checking and deployment validation # ################################################################################ set -euo pipefail # Color codes for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Logging function log() { echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}" } error() { echo -e "${RED}[ERROR] $1${NC}" } success() { echo -e "${GREEN}[SUCCESS] $1${NC}" } warning() { echo -e "${YELLOW}[WARNING] $1${NC}" } # Verify we're running in CI environment if [[ -z "${CI_REPO_NAME:-}" ]]; then error "This script must only be run in Woodpecker CI environment!" error "Missing CI_REPO_NAME environment variable" exit 1 fi log "Starting production deployment for ${CI_REPO_NAME}" # Step 1: Docker registry login log "Logging into Docker registry" echo "${REGISTRY_PASSWORD}" | docker login -u "${REGISTRY_USER}" --password-stdin git.nixc.us # Step 2: Remove old stack to release secrets log "Removing old stack to release secrets" docker stack rm "${CI_REPO_NAME}" || true # Step 3: Wait for complete stack removal log "Waiting for complete stack removal (30 seconds)" sleep 30 log "Verifying stack removal completed" while docker stack ls | grep -q "${CI_REPO_NAME}"; do log "Stack still exists, waiting..." sleep 5 done success "Stack removal completed" # Step 4: Remove old Docker secrets log "Removing old Docker secrets" declare -a SECRETS=( "AUTHENTICATION_BACKEND_LDAP_PASSWORD" "IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET" "STORAGE_ENCRYPTION_KEY" "SESSION_SECRET" "NOTIFIER_SMTP_PASSWORD" "IDENTITY_PROVIDERS_OIDC_HMAC_SECRET" "IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY" "IDENTITY_PROVIDERS_OIDC_JWKS_KEY" "CLIENT_SECRET_HEADSCALE" "CLIENT_SECRET_HEADADMIN" ) for secret in "${SECRETS[@]}"; do docker secret rm "$secret" || true log "Removed secret: $secret" done # Step 5: Create new Docker secrets with updated values log "Creating new Docker secrets with updated values" for secret in "${SECRETS[@]}"; do env_var="${secret}" if [[ -n "${!env_var:-}" ]]; then echo "${!env_var}" | docker secret create "$secret" - success "Created secret: $secret" else error "Environment variable $env_var is not set!" exit 1 fi done # Step 6: Deploy new stack with fresh secrets log "Deploying new stack with fresh secrets" docker stack deploy --with-registry-auth -c ./stack.production.yml "${CI_REPO_NAME}" # Step 7: Wait for services to initialize log "Waiting for services to initialize (30 seconds)" sleep 30 # Step 8: Check deployment status log "Checking deployment status" docker stack ps "${CI_REPO_NAME}" # Step 9: Health check loop for authelia service log "Checking service health for 60 seconds" for i in {1..12}; do if docker stack ps "${CI_REPO_NAME}" | grep Running | grep -q "authelia_authelia"; then success "✅ Authelia service is running!" # Additional health verification log "Performing additional health checks..." sleep 5 # Check if service is actually healthy (not just running) if docker stack ps "${CI_REPO_NAME}" | grep -A 5 "authelia_authelia" | grep -q "Running"; then success "🎉 Production deployment completed successfully!" success "Authelia service is healthy and running" exit 0 fi elif [ $i -eq 12 ]; then error "❌ Deployment verification failed after 60 seconds" error "Showing service logs for debugging:" docker service logs "${CI_REPO_NAME}_authelia" --tail 20 error "Showing stack status:" docker stack ps "${CI_REPO_NAME}" exit 1 else log "Attempt $i/12: Waiting for authelia service..." sleep 5 fi done error "Health check timeout - this should not be reached" exit 1