fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
435
scripts/deployment/health-check.sh
Executable file
435
scripts/deployment/health-check.sh
Executable file
@@ -0,0 +1,435 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Production Health Check Script
|
||||
# Comprehensive health monitoring for all production services
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/health-check.sh [--verbose] [--json]
|
||||
#
|
||||
# Options:
|
||||
# --verbose Show detailed output
|
||||
# --json Output in JSON format
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
VERBOSE=false
|
||||
JSON_OUTPUT=false
|
||||
|
||||
# Parse arguments
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--verbose)
|
||||
VERBOSE=true
|
||||
;;
|
||||
--json)
|
||||
JSON_OUTPUT=true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Colors
|
||||
GREEN="\e[32m"
|
||||
YELLOW="\e[33m"
|
||||
RED="\e[31m"
|
||||
BLUE="\e[34m"
|
||||
RESET="\e[0m"
|
||||
|
||||
# Health check results
|
||||
declare -A HEALTH_RESULTS
|
||||
OVERALL_HEALTHY=true
|
||||
|
||||
# Logging functions
|
||||
log() {
|
||||
if [[ "$JSON_OUTPUT" == "false" ]]; then
|
||||
echo -e "${BLUE}[$(date +'%H:%M:%S')]${RESET} $1"
|
||||
fi
|
||||
}
|
||||
|
||||
success() {
|
||||
if [[ "$JSON_OUTPUT" == "false" ]]; then
|
||||
echo -e "${GREEN}✅ $1${RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
warning() {
|
||||
if [[ "$JSON_OUTPUT" == "false" ]]; then
|
||||
echo -e "${YELLOW}⚠️ $1${RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
error() {
|
||||
if [[ "$JSON_OUTPUT" == "false" ]]; then
|
||||
echo -e "${RED}❌ $1${RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check Docker daemon
|
||||
check_docker() {
|
||||
log "Checking Docker daemon..."
|
||||
|
||||
if docker info &>/dev/null; then
|
||||
HEALTH_RESULTS[docker]="healthy"
|
||||
success "Docker daemon is running"
|
||||
return 0
|
||||
else
|
||||
HEALTH_RESULTS[docker]="unhealthy"
|
||||
error "Docker daemon is not running"
|
||||
OVERALL_HEALTHY=false
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check Docker Compose services
|
||||
check_docker_services() {
|
||||
log "Checking Docker Compose services..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
local services=("web" "php" "db" "redis" "queue-worker")
|
||||
local all_healthy=true
|
||||
|
||||
for service in "${services[@]}"; do
|
||||
if docker compose ps "$service" | grep -q "Up"; then
|
||||
HEALTH_RESULTS["service_${service}"]="healthy"
|
||||
[[ "$VERBOSE" == "true" ]] && success "$service is running"
|
||||
else
|
||||
HEALTH_RESULTS["service_${service}"]="unhealthy"
|
||||
error "$service is not running"
|
||||
all_healthy=false
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$all_healthy" == "true" ]]; then
|
||||
success "All Docker services are running"
|
||||
else
|
||||
error "Some Docker services are not running"
|
||||
OVERALL_HEALTHY=false
|
||||
fi
|
||||
}
|
||||
|
||||
# Check web server response
|
||||
check_web_response() {
|
||||
log "Checking web server response..."
|
||||
|
||||
local max_retries=3
|
||||
local retry_count=0
|
||||
|
||||
while [[ $retry_count -lt $max_retries ]]; do
|
||||
if curl -f -s -k -H "User-Agent: Mozilla/5.0 (Health Check)" "https://localhost" > /dev/null 2>&1; then
|
||||
HEALTH_RESULTS[web_response]="healthy"
|
||||
success "Web server is responding"
|
||||
return 0
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
sleep 2
|
||||
done
|
||||
|
||||
HEALTH_RESULTS[web_response]="unhealthy"
|
||||
error "Web server is not responding"
|
||||
OVERALL_HEALTHY=false
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check health endpoint
|
||||
check_health_endpoint() {
|
||||
log "Checking /health endpoint..."
|
||||
|
||||
if response=$(curl -f -s -k -H "User-Agent: Mozilla/5.0 (Health Check)" "https://localhost/health" 2>&1); then
|
||||
HEALTH_RESULTS[health_endpoint]="healthy"
|
||||
success "Health endpoint is responding"
|
||||
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
echo "$response" | head -20
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
HEALTH_RESULTS[health_endpoint]="unhealthy"
|
||||
error "Health endpoint is not responding"
|
||||
OVERALL_HEALTHY=false
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check database connectivity
|
||||
check_database() {
|
||||
log "Checking database connectivity..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if docker compose exec -T db pg_isready -U postgres &>/dev/null; then
|
||||
HEALTH_RESULTS[database]="healthy"
|
||||
success "Database is accepting connections"
|
||||
|
||||
# Get connection count
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
local conn_count=$(docker compose exec -T db psql -U postgres -t -c "SELECT count(*) FROM pg_stat_activity;" | tr -d ' ')
|
||||
log "Active connections: $conn_count"
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
HEALTH_RESULTS[database]="unhealthy"
|
||||
error "Database is not accepting connections"
|
||||
OVERALL_HEALTHY=false
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check Redis connectivity
|
||||
check_redis() {
|
||||
log "Checking Redis connectivity..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if docker compose exec -T redis redis-cli ping &>/dev/null; then
|
||||
HEALTH_RESULTS[redis]="healthy"
|
||||
success "Redis is responding"
|
||||
|
||||
# Get Redis info
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
local used_memory=$(docker compose exec -T redis redis-cli info memory | grep "used_memory_human" | cut -d: -f2 | tr -d '\r')
|
||||
log "Redis memory usage: $used_memory"
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
HEALTH_RESULTS[redis]="unhealthy"
|
||||
error "Redis is not responding"
|
||||
OVERALL_HEALTHY=false
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check SSL certificate
|
||||
check_ssl_certificate() {
|
||||
log "Checking SSL certificate..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if docker compose exec -T php php console.php ssl:status 2>/dev/null | grep -q "Certificate is valid"; then
|
||||
HEALTH_RESULTS[ssl]="healthy"
|
||||
success "SSL certificate is valid"
|
||||
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
docker compose exec -T php php console.php ssl:status
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
HEALTH_RESULTS[ssl]="warning"
|
||||
warning "SSL certificate status unclear"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check Vault connectivity
|
||||
check_vault() {
|
||||
log "Checking Vault connectivity..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if docker compose exec -T php php console.php vault:list &>/dev/null; then
|
||||
HEALTH_RESULTS[vault]="healthy"
|
||||
success "Vault is accessible"
|
||||
return 0
|
||||
else
|
||||
HEALTH_RESULTS[vault]="unhealthy"
|
||||
error "Vault is not accessible"
|
||||
OVERALL_HEALTHY=false
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check disk space
|
||||
check_disk_space() {
|
||||
log "Checking disk space..."
|
||||
|
||||
local disk_usage=$(df -h "$PROJECT_ROOT" | tail -1 | awk '{print $5}' | tr -d '%')
|
||||
|
||||
if [[ $disk_usage -lt 80 ]]; then
|
||||
HEALTH_RESULTS[disk_space]="healthy"
|
||||
success "Disk space usage: ${disk_usage}%"
|
||||
elif [[ $disk_usage -lt 90 ]]; then
|
||||
HEALTH_RESULTS[disk_space]="warning"
|
||||
warning "Disk space usage: ${disk_usage}% (consider cleanup)"
|
||||
else
|
||||
HEALTH_RESULTS[disk_space]="critical"
|
||||
error "Disk space usage: ${disk_usage}% (critical)"
|
||||
OVERALL_HEALTHY=false
|
||||
fi
|
||||
}
|
||||
|
||||
# Check memory usage
|
||||
check_memory() {
|
||||
log "Checking memory usage..."
|
||||
|
||||
local mem_usage=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100}')
|
||||
|
||||
if [[ $mem_usage -lt 80 ]]; then
|
||||
HEALTH_RESULTS[memory]="healthy"
|
||||
success "Memory usage: ${mem_usage}%"
|
||||
elif [[ $mem_usage -lt 90 ]]; then
|
||||
HEALTH_RESULTS[memory]="warning"
|
||||
warning "Memory usage: ${mem_usage}% (high)"
|
||||
else
|
||||
HEALTH_RESULTS[memory]="critical"
|
||||
error "Memory usage: ${mem_usage}% (critical)"
|
||||
OVERALL_HEALTHY=false
|
||||
fi
|
||||
}
|
||||
|
||||
# Check queue worker status
|
||||
check_queue_workers() {
|
||||
log "Checking queue workers..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
local worker_count=$(docker compose ps queue-worker | grep "Up" | wc -l)
|
||||
|
||||
if [[ $worker_count -ge 2 ]]; then
|
||||
HEALTH_RESULTS[queue_workers]="healthy"
|
||||
success "Queue workers: $worker_count running"
|
||||
elif [[ $worker_count -ge 1 ]]; then
|
||||
HEALTH_RESULTS[queue_workers]="warning"
|
||||
warning "Queue workers: only $worker_count running (expected 2)"
|
||||
else
|
||||
HEALTH_RESULTS[queue_workers]="unhealthy"
|
||||
error "Queue workers: none running"
|
||||
OVERALL_HEALTHY=false
|
||||
fi
|
||||
}
|
||||
|
||||
# Check logs for errors
|
||||
check_recent_errors() {
|
||||
log "Checking recent errors in logs..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
local error_count=$(docker compose logs --tail=1000 php 2>/dev/null | grep -ci "error\|exception\|fatal" || echo "0")
|
||||
|
||||
if [[ $error_count -lt 5 ]]; then
|
||||
HEALTH_RESULTS[recent_errors]="healthy"
|
||||
success "Recent errors: $error_count (last 1000 lines)"
|
||||
elif [[ $error_count -lt 20 ]]; then
|
||||
HEALTH_RESULTS[recent_errors]="warning"
|
||||
warning "Recent errors: $error_count (last 1000 lines)"
|
||||
else
|
||||
HEALTH_RESULTS[recent_errors]="critical"
|
||||
error "Recent errors: $error_count (last 1000 lines)"
|
||||
OVERALL_HEALTHY=false
|
||||
fi
|
||||
}
|
||||
|
||||
# Output JSON report
|
||||
output_json() {
|
||||
echo "{"
|
||||
echo " \"timestamp\": \"$(date -Iseconds)\","
|
||||
echo " \"overall_status\": \"$([ "$OVERALL_HEALTHY" == "true" ] && echo "healthy" || echo "unhealthy")\","
|
||||
echo " \"checks\": {"
|
||||
|
||||
local first=true
|
||||
for check in "${!HEALTH_RESULTS[@]}"; do
|
||||
if [[ "$first" == "true" ]]; then
|
||||
first=false
|
||||
else
|
||||
echo ","
|
||||
fi
|
||||
echo -n " \"$check\": \"${HEALTH_RESULTS[$check]}\""
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo " }"
|
||||
echo "}"
|
||||
}
|
||||
|
||||
# Display summary
|
||||
display_summary() {
|
||||
echo ""
|
||||
echo -e "${BLUE}========================================${RESET}"
|
||||
echo -e "${BLUE} Production Health Check Summary${RESET}"
|
||||
echo -e "${BLUE}========================================${RESET}"
|
||||
echo ""
|
||||
|
||||
local healthy_count=0
|
||||
local warning_count=0
|
||||
local unhealthy_count=0
|
||||
|
||||
for status in "${HEALTH_RESULTS[@]}"; do
|
||||
case $status in
|
||||
healthy)
|
||||
healthy_count=$((healthy_count + 1))
|
||||
;;
|
||||
warning)
|
||||
warning_count=$((warning_count + 1))
|
||||
;;
|
||||
unhealthy|critical)
|
||||
unhealthy_count=$((unhealthy_count + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "📊 Health Status:"
|
||||
echo " ✅ Healthy: $healthy_count"
|
||||
echo " ⚠️ Warnings: $warning_count"
|
||||
echo " ❌ Unhealthy: $unhealthy_count"
|
||||
echo ""
|
||||
|
||||
if [[ "$OVERALL_HEALTHY" == "true" ]]; then
|
||||
echo -e "${GREEN}Overall Status: HEALTHY ✅${RESET}"
|
||||
echo ""
|
||||
echo "🎉 All critical systems are operational"
|
||||
else
|
||||
echo -e "${RED}Overall Status: UNHEALTHY ❌${RESET}"
|
||||
echo ""
|
||||
echo "⚠️ Critical issues detected - immediate action required"
|
||||
echo ""
|
||||
echo "📝 Recommended Actions:"
|
||||
echo " 1. Check Docker logs: docker compose logs -f --tail=100"
|
||||
echo " 2. Review service status: docker compose ps"
|
||||
echo " 3. Check system resources: df -h && free -h"
|
||||
echo " 4. Review recent deployments for issues"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}========================================${RESET}"
|
||||
}
|
||||
|
||||
# Main health check execution
|
||||
main() {
|
||||
if [[ "$JSON_OUTPUT" == "false" ]]; then
|
||||
log "🔍 Starting production health check..."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
check_docker
|
||||
check_docker_services
|
||||
check_web_response
|
||||
check_health_endpoint
|
||||
check_database
|
||||
check_redis
|
||||
check_ssl_certificate
|
||||
check_vault
|
||||
check_disk_space
|
||||
check_memory
|
||||
check_queue_workers
|
||||
check_recent_errors
|
||||
|
||||
if [[ "$JSON_OUTPUT" == "true" ]]; then
|
||||
output_json
|
||||
else
|
||||
display_summary
|
||||
fi
|
||||
|
||||
# Exit with appropriate code
|
||||
if [[ "$OVERALL_HEALTHY" == "true" ]]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main
|
||||
main "$@"
|
||||
244
scripts/deployment/migrate-env-to-base-override.sh
Normal file
244
scripts/deployment/migrate-env-to-base-override.sh
Normal file
@@ -0,0 +1,244 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Migration Script: .env → .env.base + .env.local
|
||||
#
|
||||
# This script helps migrate from the legacy single .env file
|
||||
# to the new Base+Override Pattern (.env.base + .env.local)
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/migrate-env-to-base-override.sh
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo "🔄 Migration: .env → .env.base + .env.local"
|
||||
echo ""
|
||||
|
||||
# Check if .env exists
|
||||
if [ ! -f .env ]; then
|
||||
echo "❌ .env Datei nicht gefunden"
|
||||
echo "💡 Erstelle zuerst .env aus .env.example"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Backup existing .env
|
||||
BACKUP_FILE=".env.backup.$(date +%Y%m%d-%H%M%S)"
|
||||
echo "📦 Backup erstellen: $BACKUP_FILE"
|
||||
cp .env "$BACKUP_FILE"
|
||||
echo "✅ Backup erstellt"
|
||||
|
||||
# Check if .env.base exists
|
||||
if [ -f .env.base ]; then
|
||||
echo ""
|
||||
echo "⚠️ .env.base existiert bereits"
|
||||
echo "💡 .env.base wird als Basis verwendet"
|
||||
USE_EXISTING_BASE=true
|
||||
else
|
||||
USE_EXISTING_BASE=false
|
||||
fi
|
||||
|
||||
# Check if .env.local exists
|
||||
if [ -f .env.local ]; then
|
||||
echo ""
|
||||
echo "⚠️ .env.local existiert bereits"
|
||||
read -p "Überschreiben? (j/n): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Jj]$ ]]; then
|
||||
echo "❌ Abgebrochen"
|
||||
exit 1
|
||||
fi
|
||||
BACKUP_LOCAL=".env.local.backup.$(date +%Y%m%d-%H%M%S)"
|
||||
cp .env.local "$BACKUP_LOCAL"
|
||||
echo "📦 Backup von .env.local erstellt: $BACKUP_LOCAL"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📝 Analysiere .env Datei..."
|
||||
|
||||
# Common variables that should go to .env.base
|
||||
# (These are typically environment-agnostic)
|
||||
BASE_VARS=(
|
||||
"APP_NAME"
|
||||
"APP_TIMEZONE"
|
||||
"APP_LOCALE"
|
||||
"DB_DRIVER"
|
||||
"DB_PORT"
|
||||
"DB_CHARSET"
|
||||
"REDIS_PORT"
|
||||
"CACHE_DRIVER"
|
||||
"SESSION_DRIVER"
|
||||
"SESSION_LIFETIME"
|
||||
"QUEUE_DRIVER"
|
||||
"QUEUE_CONNECTION"
|
||||
"QUEUE_WORKER_SLEEP"
|
||||
"QUEUE_WORKER_TRIES"
|
||||
"QUEUE_WORKER_TIMEOUT"
|
||||
"SECURITY_RATE_LIMIT_PER_MINUTE"
|
||||
"SECURITY_RATE_LIMIT_BURST"
|
||||
"CACHE_PREFIX"
|
||||
)
|
||||
|
||||
# Local-specific variables (development overrides)
|
||||
LOCAL_VARS=(
|
||||
"APP_ENV"
|
||||
"APP_DEBUG"
|
||||
"APP_URL"
|
||||
"APP_KEY"
|
||||
"APP_DOMAIN"
|
||||
"DB_HOST"
|
||||
"DB_DATABASE"
|
||||
"DB_USERNAME"
|
||||
"DB_PASSWORD"
|
||||
"REDIS_HOST"
|
||||
"REDIS_PASSWORD"
|
||||
"SECURITY_ALLOWED_HOSTS"
|
||||
"FORCE_HTTPS"
|
||||
"XDEBUG_MODE"
|
||||
"PHP_IDE_CONFIG"
|
||||
)
|
||||
|
||||
# Variables that should NOT be in .env.base (secrets)
|
||||
SECRET_PATTERNS=(
|
||||
"PASSWORD"
|
||||
"SECRET"
|
||||
"KEY"
|
||||
"TOKEN"
|
||||
"ENCRYPTION"
|
||||
"VAULT"
|
||||
)
|
||||
|
||||
echo ""
|
||||
echo "📋 Trenne Variablen in Base und Local..."
|
||||
|
||||
# Create temporary files
|
||||
TMP_BASE=$(mktemp)
|
||||
TMP_LOCAL=$(mktemp)
|
||||
|
||||
# Read .env line by line
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
# Skip empty lines and comments
|
||||
if [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]]; then
|
||||
echo "$line" >> "$TMP_BASE"
|
||||
echo "$line" >> "$TMP_LOCAL"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Extract variable name
|
||||
if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)= ]]; then
|
||||
VAR_NAME="${BASH_REMATCH[1]}"
|
||||
|
||||
# Check if it's a secret
|
||||
IS_SECRET=false
|
||||
for pattern in "${SECRET_PATTERNS[@]}"; do
|
||||
if [[ "$VAR_NAME" == *"$pattern"* ]]; then
|
||||
IS_SECRET=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$IS_SECRET" = true ]; then
|
||||
# Secrets go to .env.local (or should be in Docker Secrets)
|
||||
echo "# TODO: Möglicherweise in Docker Secrets verschieben" >> "$TMP_LOCAL"
|
||||
echo "$line" >> "$TMP_LOCAL"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if it's a base variable
|
||||
IS_BASE=false
|
||||
for base_var in "${BASE_VARS[@]}"; do
|
||||
if [[ "$VAR_NAME" == "$base_var" ]]; then
|
||||
IS_BASE=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if it's a local variable
|
||||
IS_LOCAL=false
|
||||
for local_var in "${LOCAL_VARS[@]}"; do
|
||||
if [[ "$VAR_NAME" == "$local_var" ]]; then
|
||||
IS_LOCAL=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$IS_BASE" = true ]; then
|
||||
# Go to .env.base
|
||||
echo "$line" >> "$TMP_BASE"
|
||||
elif [ "$IS_LOCAL" = true ]; then
|
||||
# Go to .env.local
|
||||
echo "$line" >> "$TMP_LOCAL"
|
||||
else
|
||||
# Unknown: Ask or put in local as default
|
||||
echo "# TODO: Prüfen ob Base oder Local" >> "$TMP_LOCAL"
|
||||
echo "$line" >> "$TMP_LOCAL"
|
||||
fi
|
||||
else
|
||||
# Non-standard line format: keep in both (shouldn't happen)
|
||||
echo "$line" >> "$TMP_BASE"
|
||||
echo "$line" >> "$TMP_LOCAL"
|
||||
fi
|
||||
done < .env
|
||||
|
||||
# Create .env.base if it doesn't exist
|
||||
if [ "$USE_EXISTING_BASE" = false ]; then
|
||||
echo ""
|
||||
echo "📝 Erstelle .env.base..."
|
||||
cat > .env.base << 'EOF'
|
||||
# Base Environment Configuration
|
||||
# This file contains shared environment variables for all environments.
|
||||
# Use with environment-specific override files:
|
||||
# - .env.local (local development overrides)
|
||||
# - .env.staging (staging-specific overrides, optional)
|
||||
# - .env.production (production - generated by Ansible)
|
||||
#
|
||||
# Framework automatically loads: .env.base → .env.local (if exists)
|
||||
# See ENV_SETUP.md for details
|
||||
#
|
||||
EOF
|
||||
cat "$TMP_BASE" >> .env.base
|
||||
echo "✅ .env.base erstellt"
|
||||
else
|
||||
echo ""
|
||||
echo "ℹ️ .env.base existiert bereits, wird nicht überschrieben"
|
||||
fi
|
||||
|
||||
# Create .env.local
|
||||
echo ""
|
||||
echo "📝 Erstelle .env.local..."
|
||||
cat > .env.local << 'EOF'
|
||||
# Local Development Environment Overrides
|
||||
# This file overrides .env.base with local development-specific settings.
|
||||
# This file is gitignored - each developer has their own version.
|
||||
#
|
||||
# Framework loads: .env.base → .env.local (this file) → System ENV vars
|
||||
# See ENV_SETUP.md for details
|
||||
#
|
||||
EOF
|
||||
cat "$TMP_LOCAL" >> .env.local
|
||||
echo "✅ .env.local erstellt"
|
||||
|
||||
# Cleanup
|
||||
rm -f "$TMP_BASE" "$TMP_LOCAL"
|
||||
|
||||
echo ""
|
||||
echo "✅ Migration abgeschlossen!"
|
||||
echo ""
|
||||
echo "📋 Nächste Schritte:"
|
||||
echo " 1. Prüfe .env.base - entferne Secrets falls vorhanden"
|
||||
echo " 2. Prüfe .env.local - passe lokale Overrides an"
|
||||
echo " 3. Teste die Anwendung: make up"
|
||||
echo " 4. Optional: .env kann später entfernt werden (wird als Fallback geladen)"
|
||||
echo ""
|
||||
echo "📝 Backup-Dateien:"
|
||||
echo " - $BACKUP_FILE"
|
||||
if [ -n "$BACKUP_LOCAL" ]; then
|
||||
echo " - $BACKUP_LOCAL"
|
||||
fi
|
||||
echo ""
|
||||
echo "💡 Siehe ENV_SETUP.md für Details zur neuen Struktur"
|
||||
|
||||
34
scripts/deployment/prepare-secrets.sh
Executable file
34
scripts/deployment/prepare-secrets.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
# Helper Script to prepare secrets for Gitea manual setup
|
||||
# Usage: ./scripts/prepare-secrets.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "=== Gitea Secrets - Werte zum Kopieren ==="
|
||||
echo ""
|
||||
echo "1. REGISTRY_USER:"
|
||||
echo "─────────────────"
|
||||
echo "admin"
|
||||
echo ""
|
||||
echo ""
|
||||
echo "2. REGISTRY_PASSWORD:"
|
||||
echo "─────────────────────"
|
||||
echo "registry-secure-password-2025"
|
||||
echo ""
|
||||
echo ""
|
||||
echo "3. SSH_PRIVATE_KEY:"
|
||||
echo "───────────────────"
|
||||
if [ -f ~/.ssh/production ]; then
|
||||
cat ~/.ssh/production
|
||||
else
|
||||
echo "⚠️ FEHLER: ~/.ssh/production nicht gefunden!"
|
||||
echo "Bitte SSH Key erstellen oder Pfad anpassen."
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
echo ""
|
||||
echo "=== Nächste Schritte ==="
|
||||
echo "1. Gehe zu: https://git.michaelschiemer.de/<username>/michaelschiemer/settings/secrets"
|
||||
echo "2. Füge jedes Secret oben einzeln hinzu"
|
||||
echo "3. Kopiere die Werte von oben für jedes Secret"
|
||||
echo ""
|
||||
238
scripts/deployment/setup-autossh.sh
Executable file
238
scripts/deployment/setup-autossh.sh
Executable file
@@ -0,0 +1,238 @@
|
||||
#!/bin/bash
|
||||
# Setup script for autossh persistent SSH connections
|
||||
# Usage: ./scripts/setup-autossh.sh [production|git|both]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
SSH_CONFIG="$HOME/.ssh/config"
|
||||
SERVICE_TYPE="${1:-both}"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Functions
|
||||
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 autossh is installed
|
||||
check_autossh() {
|
||||
if ! command -v autossh &> /dev/null; then
|
||||
log_error "autossh is not installed!"
|
||||
echo ""
|
||||
echo "Installation:"
|
||||
echo " Ubuntu/Debian: sudo apt install autossh"
|
||||
echo " macOS: brew install autossh"
|
||||
exit 1
|
||||
fi
|
||||
log_info "autossh is installed: $(which autossh)"
|
||||
}
|
||||
|
||||
# Check if SSH config exists
|
||||
check_ssh_config() {
|
||||
if [ ! -d "$HOME/.ssh" ]; then
|
||||
log_info "Creating ~/.ssh directory"
|
||||
mkdir -p "$HOME/.ssh"
|
||||
chmod 700 "$HOME/.ssh"
|
||||
fi
|
||||
|
||||
if [ ! -f "$SSH_CONFIG" ]; then
|
||||
log_info "Creating SSH config file"
|
||||
touch "$SSH_CONFIG"
|
||||
chmod 600 "$SSH_CONFIG"
|
||||
fi
|
||||
}
|
||||
|
||||
# Add SSH config entries
|
||||
add_ssh_config() {
|
||||
log_info "Checking SSH config..."
|
||||
|
||||
# Production server config
|
||||
if ! grep -q "Host production" "$SSH_CONFIG" 2>/dev/null; then
|
||||
log_info "Adding production server config to SSH config"
|
||||
cat >> "$SSH_CONFIG" << 'EOF'
|
||||
|
||||
# Production Server - Persistent Connection
|
||||
Host production
|
||||
HostName 94.16.110.151
|
||||
User deploy
|
||||
IdentityFile ~/.ssh/production
|
||||
ServerAliveInterval 60
|
||||
ServerAliveCountMax 3
|
||||
TCPKeepAlive yes
|
||||
Compression yes
|
||||
StrictHostKeyChecking accept-new
|
||||
EOF
|
||||
else
|
||||
log_info "Production server config already exists in SSH config"
|
||||
fi
|
||||
|
||||
# Git server config
|
||||
if ! grep -q "Host git.michaelschiemer.de" "$SSH_CONFIG" 2>/dev/null; then
|
||||
log_info "Adding git server config to SSH config"
|
||||
cat >> "$SSH_CONFIG" << 'EOF'
|
||||
|
||||
# Git Server - Persistent Connection
|
||||
Host git.michaelschiemer.de
|
||||
HostName git.michaelschiemer.de
|
||||
Port 2222
|
||||
User git
|
||||
IdentityFile ~/.ssh/git_michaelschiemer
|
||||
ServerAliveInterval 60
|
||||
ServerAliveCountMax 3
|
||||
TCPKeepAlive yes
|
||||
Compression yes
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile /dev/null
|
||||
EOF
|
||||
else
|
||||
log_info "Git server config already exists in SSH config"
|
||||
fi
|
||||
}
|
||||
|
||||
# Create systemd service
|
||||
create_systemd_service() {
|
||||
local host=$1
|
||||
local port=$2
|
||||
local service_name="autossh-${host}"
|
||||
local service_dir="$HOME/.config/systemd/user"
|
||||
|
||||
log_info "Creating systemd service for ${host}..."
|
||||
|
||||
mkdir -p "$service_dir"
|
||||
|
||||
cat > "${service_dir}/${service_name}.service" << EOF
|
||||
[Unit]
|
||||
Description=AutoSSH for ${host}
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Environment="AUTOSSH_GATETIME=0"
|
||||
Environment="AUTOSSH_POLL=10"
|
||||
ExecStart=/usr/bin/autossh -M ${port} -N -o "ServerAliveInterval=60" -o "ServerAliveCountMax=3" ${host}
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
EOF
|
||||
|
||||
log_info "Systemd service created: ${service_dir}/${service_name}.service"
|
||||
}
|
||||
|
||||
# Setup systemd services
|
||||
setup_systemd_services() {
|
||||
if ! systemctl --user --version &> /dev/null; then
|
||||
log_warn "systemd user services not available (might be on macOS or non-systemd system)"
|
||||
log_info "Skipping systemd service setup. See docs/deployment/AUTOSSH-SETUP.md for manual setup."
|
||||
return
|
||||
fi
|
||||
|
||||
log_info "Setting up systemd services..."
|
||||
|
||||
case "$SERVICE_TYPE" in
|
||||
production)
|
||||
create_systemd_service "production" "20000"
|
||||
systemctl --user daemon-reload
|
||||
log_info "To enable: systemctl --user enable autossh-production.service"
|
||||
log_info "To start: systemctl --user start autossh-production.service"
|
||||
;;
|
||||
git)
|
||||
create_systemd_service "git.michaelschiemer.de" "20001"
|
||||
systemctl --user daemon-reload
|
||||
log_info "To enable: systemctl --user enable autossh-git.michaelschiemer.de.service"
|
||||
log_info "To start: systemctl --user start autossh-git.michaelschiemer.de.service"
|
||||
;;
|
||||
both)
|
||||
create_systemd_service "production" "20000"
|
||||
create_systemd_service "git.michaelschiemer.de" "20001"
|
||||
systemctl --user daemon-reload
|
||||
log_info "To enable:"
|
||||
log_info " systemctl --user enable autossh-production.service"
|
||||
log_info " systemctl --user enable autossh-git.michaelschiemer.de.service"
|
||||
log_info "To start:"
|
||||
log_info " systemctl --user start autossh-production.service"
|
||||
log_info " systemctl --user start autossh-git.michaelschiemer.de.service"
|
||||
;;
|
||||
*)
|
||||
log_error "Invalid service type: $SERVICE_TYPE"
|
||||
log_info "Usage: $0 [production|git|both]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Test SSH connections
|
||||
test_connections() {
|
||||
log_info "Testing SSH connections..."
|
||||
|
||||
case "$SERVICE_TYPE" in
|
||||
production)
|
||||
if ssh -o ConnectTimeout=5 production "echo 'Connection successful'" 2>/dev/null; then
|
||||
log_info "? Production server connection successful"
|
||||
else
|
||||
log_warn "?? Production server connection failed"
|
||||
log_info "Make sure SSH key is set up: ssh-keygen -t ed25519 -f ~/.ssh/production"
|
||||
fi
|
||||
;;
|
||||
git)
|
||||
if ssh -o ConnectTimeout=5 git.michaelschiemer.de "echo 'Connection successful'" 2>/dev/null; then
|
||||
log_info "? Git server connection successful"
|
||||
else
|
||||
log_warn "?? Git server connection failed"
|
||||
log_info "Make sure SSH key is set up: ssh-keygen -t ed25519 -f ~/.ssh/git_michaelschiemer"
|
||||
fi
|
||||
;;
|
||||
both)
|
||||
if ssh -o ConnectTimeout=5 production "echo 'Connection successful'" 2>/dev/null; then
|
||||
log_info "? Production server connection successful"
|
||||
else
|
||||
log_warn "?? Production server connection failed"
|
||||
fi
|
||||
if ssh -o ConnectTimeout=5 git.michaelschiemer.de "echo 'Connection successful'" 2>/dev/null; then
|
||||
log_info "? Git server connection successful"
|
||||
else
|
||||
log_warn "?? Git server connection failed"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
log_info "Setting up autossh for persistent SSH connections"
|
||||
echo ""
|
||||
|
||||
check_autossh
|
||||
check_ssh_config
|
||||
add_ssh_config
|
||||
setup_systemd_services
|
||||
test_connections
|
||||
|
||||
echo ""
|
||||
log_info "Setup complete!"
|
||||
echo ""
|
||||
log_info "Next steps:"
|
||||
echo " 1. Review SSH config: cat ~/.ssh/config"
|
||||
echo " 2. Enable systemd services (see output above)"
|
||||
echo " 3. Start services (see output above)"
|
||||
echo " 4. Check status: systemctl --user status autossh-*.service"
|
||||
echo ""
|
||||
log_info "Documentation: docs/deployment/AUTOSSH-SETUP.md"
|
||||
}
|
||||
|
||||
main
|
||||
123
scripts/deployment/setup-gitea-secrets-interactive.sh
Executable file
123
scripts/deployment/setup-gitea-secrets-interactive.sh
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/bin/bash
|
||||
# Interactive Script to set Gitea Repository Secrets via API
|
||||
# Usage: ./scripts/setup-gitea-secrets-interactive.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GITEA_URL="${GITEA_URL:-https://git.michaelschiemer.de}"
|
||||
REPO_OWNER="${REPO_OWNER:-michael}"
|
||||
REPO_NAME="${REPO_NAME:-michaelschiemer}"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}=== Gitea Repository Secrets Setup ===${NC}"
|
||||
echo ""
|
||||
echo "Repository: ${REPO_OWNER}/${REPO_NAME}"
|
||||
echo "Gitea URL: ${GITEA_URL}"
|
||||
echo ""
|
||||
|
||||
# Check for existing token
|
||||
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||
echo -e "${YELLOW}Gitea Access Token benötigt${NC}"
|
||||
echo ""
|
||||
echo "Bitte generiere einen Token:"
|
||||
echo "1. Gehe zu: ${GITEA_URL}/user/settings/applications"
|
||||
echo "2. Klicke 'Generate New Token'"
|
||||
echo "3. Name: 'secrets-setup'"
|
||||
echo "4. Scopes: 'write:repository' (oder alle)"
|
||||
echo "5. Kopiere den Token"
|
||||
echo ""
|
||||
read -sp "Gitea Token: " GITEA_TOKEN
|
||||
echo ""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||
echo -e "${RED}❌ Token erforderlich - Abbruch${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to create/update secret via API
|
||||
set_secret() {
|
||||
local secret_name=$1
|
||||
local secret_value=$2
|
||||
|
||||
echo -n "Setting $secret_name... "
|
||||
|
||||
# Gitea API endpoint: PUT /repos/{owner}/{repo}/actions/secrets/{secretname}
|
||||
local response=$(curl -s -w "\n%{http_code}" \
|
||||
-X PUT \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/actions/secrets/${secret_name}" \
|
||||
-d "{
|
||||
\"data\": \"$(printf '%s' "$secret_value" | base64 | tr -d '\n')\"
|
||||
}" 2>&1)
|
||||
|
||||
local http_code=$(echo "$response" | tail -n1)
|
||||
local body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" = "204" ] || [ "$http_code" = "201" ]; then
|
||||
echo -e "${GREEN}✅ OK${NC}"
|
||||
return 0
|
||||
elif [ "$http_code" = "404" ]; then
|
||||
echo -e "${YELLOW}⚠️ Repository oder Token-Berechtigung fehlt${NC}"
|
||||
return 1
|
||||
else
|
||||
echo -e "${RED}❌ FAILED (HTTP $http_code)${NC}"
|
||||
echo "Response: $body"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get registry password (default)
|
||||
REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-registry-secure-password-2025}"
|
||||
|
||||
# Get SSH private key
|
||||
if [ -f ~/.ssh/production ]; then
|
||||
SSH_PRIVATE_KEY=$(cat ~/.ssh/production)
|
||||
echo -e "${GREEN}✓ SSH private key gefunden${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ SSH private key nicht gefunden in ~/.ssh/production${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Setting secrets for repository: ${REPO_OWNER}/${REPO_NAME}"
|
||||
echo ""
|
||||
|
||||
# Test API connection first
|
||||
echo -n "Testing API connection... "
|
||||
test_response=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}")
|
||||
|
||||
if [ "$test_response" != "200" ]; then
|
||||
者可 echo -e "${RED}❌ FAILED (HTTP $test_response)${NC}"
|
||||
echo ""
|
||||
echo "Mögliche Probleme:"
|
||||
echo "- Token ungültig oder fehlende Berechtigungen"
|
||||
echo "- Repository nicht gefunden: ${REPO_OWNER}/${REPO_NAME}"
|
||||
echo "- Netzwerkproblem"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ OK${NC}"
|
||||
echo ""
|
||||
|
||||
# Set secrets
|
||||
set_secret "REGISTRY_USER" "admin"
|
||||
set_secret "REGISTRY_PASSWORD" "$REGISTRY_PASSWORD"
|
||||
set_secret "SSH_PRIVATE_KEY" "$SSH_PRIVATE_KEY"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}=== Secrets Setup Complete ===${NC}"
|
||||
echo ""
|
||||
echo "Prüfe Secrets in Gitea UI:"
|
||||
echo "${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/settings/secrets/actions"
|
||||
echo ""
|
||||
120
scripts/deployment/setup-gitea-secrets-with-token.sh
Executable file
120
scripts/deployment/setup-gitea-secrets-with-token.sh
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
# Set Gitea Repository Secrets with Token
|
||||
# Usage: ./scripts/setup-gitea-secrets-with-token.sh <GITEA_TOKEN>
|
||||
# or: GITEA_TOKEN=xxx ./scripts/setup-gitea-secrets-with-token.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GITEA_URL="${GITEA_URL:-https://git.michaelschiemer.de}"
|
||||
REPO_OWNER="${REPO_OWNER:-michael}"
|
||||
REPO_NAME="${REPO_NAME:-michaelschiemer}"
|
||||
GITEA_TOKEN="${1:-${GITEA_TOKEN:-}}"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}=== Gitea Repository Secrets Setup ===${NC}"
|
||||
echo ""
|
||||
echo "Repository: ${REPO_OWNER}/${REPO_NAME}"
|
||||
echo "Gitea URL: ${GITEA_URL}"
|
||||
echo ""
|
||||
|
||||
# Check if token is provided
|
||||
if [ -z "$GITEA_TOKEN" ]; then
|
||||
echo -e "${RED}❌ Fehler: GITEA_TOKEN nicht angegeben${NC}"
|
||||
echo ""
|
||||
echo "Verwendung:"
|
||||
echo " $0 <GITEA_TOKEN>"
|
||||
echo " oder:"
|
||||
echo " GITEA_TOKEN=<token> $0"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to create/update secret via API
|
||||
set_secret() {
|
||||
local secret_name=$1
|
||||
local secret_value=$2
|
||||
|
||||
echo -n "Setting $secret_name... "
|
||||
|
||||
# Base64 encode the secret value
|
||||
local encoded_value=$(printf '%s' "$secret_value" | base64 | tr -d '\n')
|
||||
|
||||
# Gitea API endpoint: PUT /repos/{owner}/{repo}/actions/secrets/{secretname}
|
||||
local response=$(curl -s -w "\n%{http_code}" \
|
||||
-X PUT \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/actions/secrets/${secret_name}" \
|
||||
-d "{
|
||||
\"data\": \"${encoded_value}\"
|
||||
}" 2>&1)
|
||||
|
||||
local http_code=$(echo "$response" | tail -n1)
|
||||
local body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" = "204" ] || [ "$http_code" = "201" ]; then
|
||||
echo -e "${GREEN}✅ OK${NC}"
|
||||
return 0
|
||||
elif [ "$http_code" = "404" ]; then
|
||||
echo -e "${YELLOW}⚠️ Repository oder Token-Berechtigung fehlt${NC}"
|
||||
echo "Response: $body"
|
||||
return 1
|
||||
else
|
||||
echo -e "${RED}❌ FAILED (HTTP $http_code)${NC}"
|
||||
echo "Response: $body"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get registry password (default)
|
||||
REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-registry-secure-password-2025}"
|
||||
|
||||
# Get SSH private key
|
||||
if [ -f ~/.ssh/production ]; then
|
||||
SSH_PRIVATE_KEY=$(cat ~/.ssh/production)
|
||||
echo -e "${GREEN}✓ SSH private key gefunden${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ SSH private key nicht gefunden in ~/.ssh/production${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Testing API connection..."
|
||||
|
||||
# Test API connection first
|
||||
test_response=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}")
|
||||
|
||||
if [ "$test_response" != "200" ]; then
|
||||
echo -e "${RED}❌ API-Verbindung fehlgeschlagen (HTTP $test_response)${NC}"
|
||||
echo ""
|
||||
echo "Mögliche Probleme:"
|
||||
echo "- Token ungültig oder fehlende Berechtigungen"
|
||||
echo "- Repository nicht gefunden: ${REPO_OWNER}/${REPO_NAME}"
|
||||
echo "- Netzwerkproblem"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ API-Verbindung erfolgreich${NC}"
|
||||
echo ""
|
||||
echo "Setting secrets..."
|
||||
echo ""
|
||||
|
||||
# Set secrets
|
||||
set_secret "REGISTRY_USER" "admin"
|
||||
set_secret "REGISTRY_PASSWORD" "$REGISTRY_PASSWORD"
|
||||
set_secret "SSH_PRIVATE_KEY" "$SSH_PRIVATE_KEY"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}=== Secrets Setup Complete ===${NC}"
|
||||
echo ""
|
||||
echo "Prüfe Secrets in Gitea UI:"
|
||||
echo "${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/settings/secrets/actions"
|
||||
echo ""
|
||||
96
scripts/deployment/setup-gitea-secrets.sh
Executable file
96
scripts/deployment/setup-gitea-secrets.sh
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/bin/bash
|
||||
# Helper Script to set Gitea Repository Secrets
|
||||
# Usage: ./scripts/setup-gitea-secrets.sh [GITEA_TOKEN]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GITEA_URL="${GITEA_URL:-https://git.michaelschiemer.de}"
|
||||
REPO_OWNER="${REPO_OWNER:-$(git config user.name || echo 'michael')}"
|
||||
REPO_NAME="${REPO_NAME:-michaelschiemer}"
|
||||
GITEA_TOKEN="${1:-${GITEA_TOKEN:-}}"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${GREEN}=== Gitea Repository Secrets Setup ===${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if token is provided
|
||||
if [ -z "$GITEA_TOKEN" ]; then
|
||||
echo -e "${YELLOW}⚠️ GITEA_TOKEN nicht gesetzt${NC}"
|
||||
echo ""
|
||||
echo "Bitte generiere einen Gitea Access Token:"
|
||||
echo "1. Gehe zu: ${GITEA_URL}/user/settings/applications"
|
||||
echo "2. Klicke 'Generate New Token'"
|
||||
echo "3. Name: 'secrets-setup'"
|
||||
echo "4. Scopes: 'write:repository'"
|
||||
echo "5. Kopiere den Token"
|
||||
echo ""
|
||||
echo "Dann führe aus:"
|
||||
echo " export GITEA_TOKEN='dein-token'"
|
||||
echo " ./scripts/setup-gitea-secrets.sh"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to create/update secret
|
||||
set_secret() {
|
||||
local secret_name=$1
|
||||
local secret_value=$2
|
||||
|
||||
echo -n "Setting $secret_name... "
|
||||
|
||||
# Gitea API endpoint for repository secrets
|
||||
local response=$(curl -s -w "\n%{http_code}" \
|
||||
-X PUT \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/actions/secrets/${secret_name}" \
|
||||
-d "{
|
||||
\"data\": \"${secret_value}\"
|
||||
}")
|
||||
|
||||
local http_code=$(echo "$response" | tail -n1)
|
||||
local body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" = "204" ] || [ "$http_code" = "201" ]; then
|
||||
echo -e "${GREEN}✅ OK${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}❌ FAILED (HTTP $http_code)${NC}"
|
||||
echo "Response: $body"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get registry password (default or from vault)
|
||||
REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-registry-secure-password-2025}"
|
||||
|
||||
# Get SSH private key
|
||||
if [ -f ~/.ssh/production ]; then
|
||||
SSH_PRIVATE_KEY=$(cat ~/.ssh/production)
|
||||
echo -e "${GREEN}✓ SSH private key gefunden${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ SSH private key nicht gefunden in ~/.ssh/production${NC}"
|
||||
echo "Bitte SSH key Pfad anpassen oder manuell setzen"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Setting secrets for repository: ${REPO_OWNER}/${REPO_NAME}"
|
||||
echo ""
|
||||
|
||||
# Set secrets
|
||||
set_secret "REGISTRY_USER" "admin"
|
||||
set_secret "REGISTRY_PASSWORD" "$REGISTRY_PASSWORD"
|
||||
set_secret "SSH_PRIVATE_KEY" "$SSH_PRIVATE_KEY"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}=== Secrets Setup Complete ===${NC}"
|
||||
echo ""
|
||||
echo "Prüfe Secrets in Gitea UI:"
|
||||
echo "${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/enu/repo/settings/secrets"
|
||||
echo ""
|
||||
85
scripts/deployment/setup-production-secrets.sh
Executable file
85
scripts/deployment/setup-production-secrets.sh
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# Production Secrets Setup Script
|
||||
# ==============================================================================
|
||||
# This script creates Docker Secrets on the production server from .env values
|
||||
# Run this ONCE during initial setup on the production server.
|
||||
# ==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔐 Docker Secrets Setup for Production"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
|
||||
# Check if running on production server
|
||||
if [ ! -f /home/deploy/framework/.env ]; then
|
||||
echo "❌ ERROR: /home/deploy/framework/.env not found"
|
||||
echo " Please ensure .env file exists on production server"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if Docker Swarm is initialized
|
||||
if ! docker info | grep -q "Swarm: active"; then
|
||||
echo "❌ ERROR: Docker Swarm is not initialized"
|
||||
echo " Run: docker swarm init"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📋 Reading secrets from .env file..."
|
||||
cd /home/deploy/framework
|
||||
|
||||
# Function to create secret from .env
|
||||
create_secret() {
|
||||
local secret_name=$1
|
||||
local env_key=$2
|
||||
|
||||
# Extract value from .env
|
||||
local value=$(grep "^${env_key}=" .env | cut -d'=' -f2- | sed 's/^"\(.*\)"$/\1/')
|
||||
|
||||
if [ -z "$value" ]; then
|
||||
echo "⚠️ WARNING: ${env_key} not found in .env, skipping ${secret_name}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if secret already exists
|
||||
if docker secret ls --format "{{.Name}}" | grep -q "^${secret_name}$"; then
|
||||
echo "ℹ️ Secret '${secret_name}' already exists, skipping..."
|
||||
return
|
||||
fi
|
||||
|
||||
# Create secret
|
||||
echo "$value" | docker secret create "$secret_name" - 2>/dev/null
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Created secret: ${secret_name}"
|
||||
else
|
||||
echo "❌ Failed to create secret: ${secret_name}"
|
||||
fi
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "🔑 Creating Docker Secrets..."
|
||||
echo ""
|
||||
|
||||
# Create all required secrets
|
||||
create_secret "db_password" "DB_PASSWORD"
|
||||
create_secret "app_key" "APP_KEY"
|
||||
create_secret "vault_encryption_key" "VAULT_ENCRYPTION_KEY"
|
||||
create_secret "shopify_webhook_secret" "SHOPIFY_WEBHOOK_SECRET"
|
||||
create_secret "rapidmail_password" "RAPIDMAIL_PASSWORD"
|
||||
|
||||
echo ""
|
||||
echo "📊 Verifying Secrets..."
|
||||
echo ""
|
||||
|
||||
docker secret ls
|
||||
|
||||
echo ""
|
||||
echo "✅ Secrets setup completed!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Deploy the stack: docker stack deploy -c docker-compose.prod.yml framework"
|
||||
echo " 2. Monitor deployment: watch docker stack ps framework"
|
||||
echo " 3. Check logs: docker service logs framework_web"
|
||||
echo ""
|
||||
320
scripts/deployment/setup-production-ssl.sh
Executable file
320
scripts/deployment/setup-production-ssl.sh
Executable file
@@ -0,0 +1,320 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Production SSL Certificate Setup Script for michaelschiemer.de
|
||||
# Sets up Let's Encrypt SSL certificates on the production server
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Configuration
|
||||
SERVER_USER="deploy"
|
||||
SERVER_IP="94.16.110.151"
|
||||
REMOTE_PATH="/home/deploy/michaelschiemer"
|
||||
DOMAIN="michaelschiemer.de"
|
||||
EMAIL="michael@michaelschiemer.de" # Change this to your email
|
||||
SSH_OPTS="-i ~/.ssh/production -o StrictHostKeyChecking=no"
|
||||
|
||||
# Colors for output
|
||||
GREEN="\e[32m"
|
||||
YELLOW="\e[33m"
|
||||
RED="\e[31m"
|
||||
BLUE="\e[34m"
|
||||
RESET="\e[0m"
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${RESET} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${RESET} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${RESET} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${RESET} $1"
|
||||
}
|
||||
|
||||
# Check if domain resolves to production server
|
||||
check_dns() {
|
||||
log_info "Checking DNS resolution for $DOMAIN..."
|
||||
local resolved_ip=$(dig +short "$DOMAIN" | head -1)
|
||||
|
||||
if [[ "$resolved_ip" == "$SERVER_IP" ]]; then
|
||||
log_success "Domain $DOMAIN resolves correctly to $SERVER_IP"
|
||||
else
|
||||
log_warning "Domain $DOMAIN resolves to $resolved_ip (expected: $SERVER_IP)"
|
||||
log_warning "SSL certificate might fail if DNS is incorrect"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install certbot on production server
|
||||
install_certbot() {
|
||||
log_info "Installing certbot on production server..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" '
|
||||
# Update package list
|
||||
sudo apt update
|
||||
|
||||
# Install snapd if not present
|
||||
if ! command -v snap &> /dev/null; then
|
||||
sudo apt install -y snapd
|
||||
fi
|
||||
|
||||
# Install certbot via snap
|
||||
if ! command -v certbot &> /dev/null; then
|
||||
sudo snap install core; sudo snap refresh core
|
||||
sudo snap install --classic certbot
|
||||
sudo ln -sf /snap/bin/certbot /usr/bin/certbot
|
||||
fi
|
||||
|
||||
# Verify certbot installation
|
||||
certbot --version
|
||||
'
|
||||
|
||||
log_success "Certbot installed successfully"
|
||||
}
|
||||
|
||||
# Stop nginx temporarily for certificate generation
|
||||
prepare_nginx() {
|
||||
log_info "Preparing nginx for certificate generation..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Stop nginx container temporarily
|
||||
docker compose down web 2>/dev/null || true
|
||||
|
||||
# Create ssl directory
|
||||
mkdir -p ssl
|
||||
|
||||
# Create temporary nginx config for certbot
|
||||
cat > ssl/nginx-temp.conf << 'EOF'
|
||||
server {
|
||||
listen 80;
|
||||
server_name $DOMAIN;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://\$server_name\$request_uri;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Start temporary nginx for certificate validation
|
||||
docker run -d --name nginx-temp \\
|
||||
-p 80:80 \\
|
||||
-v \$(pwd)/ssl/nginx-temp.conf:/etc/nginx/conf.d/default.conf \\
|
||||
-v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
|
||||
nginx:alpine
|
||||
"
|
||||
|
||||
log_success "Nginx prepared for certificate generation"
|
||||
}
|
||||
|
||||
# Generate Let's Encrypt certificate
|
||||
generate_certificate() {
|
||||
log_info "Generating Let's Encrypt certificate for $DOMAIN..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Create webroot directory
|
||||
mkdir -p ssl/certbot-webroot
|
||||
|
||||
# Generate certificate
|
||||
docker run --rm \\
|
||||
-v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
|
||||
-v \$(pwd)/ssl:/etc/letsencrypt \\
|
||||
certbot/certbot certonly \\
|
||||
--webroot \\
|
||||
--webroot-path=/var/www/certbot \\
|
||||
--email $EMAIL \\
|
||||
--agree-tos \\
|
||||
--no-eff-email \\
|
||||
-d $DOMAIN
|
||||
|
||||
# Copy certificates to expected location
|
||||
if [ -d \"ssl/live/$DOMAIN\" ]; then
|
||||
cp ssl/live/$DOMAIN/fullchain.pem ssl/fullchain.pem
|
||||
cp ssl/live/$DOMAIN/privkey.pem ssl/privkey.pem
|
||||
chmod 644 ssl/fullchain.pem ssl/privkey.pem
|
||||
log_success 'SSL certificates generated and copied'
|
||||
else
|
||||
log_error 'Certificate generation failed'
|
||||
exit 1
|
||||
fi
|
||||
"
|
||||
|
||||
log_success "SSL certificate generated successfully"
|
||||
}
|
||||
|
||||
# Clean up temporary nginx
|
||||
cleanup_nginx() {
|
||||
log_info "Cleaning up temporary nginx..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Stop and remove temporary nginx
|
||||
docker stop nginx-temp 2>/dev/null || true
|
||||
docker rm nginx-temp 2>/dev/null || true
|
||||
|
||||
# Clean up temporary files
|
||||
rm -f ssl/nginx-temp.conf
|
||||
rm -rf ssl/certbot-webroot
|
||||
"
|
||||
|
||||
log_success "Temporary nginx cleaned up"
|
||||
}
|
||||
|
||||
# Start the application with SSL
|
||||
start_application() {
|
||||
log_info "Starting application with SSL certificates..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
cd $REMOTE_PATH
|
||||
|
||||
# Start all services
|
||||
docker compose up -d
|
||||
|
||||
# Wait for services to start
|
||||
sleep 10
|
||||
|
||||
# Check container status
|
||||
docker compose ps
|
||||
"
|
||||
|
||||
log_success "Application started with SSL certificates"
|
||||
}
|
||||
|
||||
# Test SSL certificate
|
||||
test_ssl() {
|
||||
log_info "Testing SSL certificate..."
|
||||
|
||||
# Test HTTPS connection
|
||||
if curl -sSf "https://$DOMAIN" > /dev/null 2>&1; then
|
||||
log_success "HTTPS connection successful!"
|
||||
else
|
||||
log_warning "HTTPS connection test failed - checking certificate..."
|
||||
fi
|
||||
|
||||
# Check certificate details
|
||||
echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | openssl x509 -noout -dates
|
||||
|
||||
log_info "SSL setup completed!"
|
||||
log_success "Your site should now be accessible at: https://$DOMAIN"
|
||||
}
|
||||
|
||||
# Setup certificate renewal
|
||||
setup_renewal() {
|
||||
log_info "Setting up automatic certificate renewal..."
|
||||
|
||||
ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
|
||||
# Create renewal script
|
||||
cat > /home/deploy/renew-certificates.sh << 'RENEWAL_SCRIPT'
|
||||
#!/bin/bash
|
||||
cd /home/deploy/michaelschiemer
|
||||
|
||||
# Stop nginx container
|
||||
docker compose down web
|
||||
|
||||
# Renew certificate
|
||||
docker run --rm \\
|
||||
-v \$(pwd)/ssl:/etc/letsencrypt \\
|
||||
-v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
|
||||
certbot/certbot renew \\
|
||||
--webroot \\
|
||||
--webroot-path=/var/www/certbot
|
||||
|
||||
# Copy renewed certificates
|
||||
if [ -f \"ssl/live/$DOMAIN/fullchain.pem\" ]; then
|
||||
cp ssl/live/$DOMAIN/fullchain.pem ssl/fullchain.pem
|
||||
cp ssl/live/$DOMAIN/privkey.pem ssl/privkey.pem
|
||||
chmod 644 ssl/fullchain.pem ssl/privkey.pem
|
||||
fi
|
||||
|
||||
# Restart services
|
||||
docker compose up -d
|
||||
RENEWAL_SCRIPT
|
||||
|
||||
chmod +x /home/deploy/renew-certificates.sh
|
||||
|
||||
# Add cron job for automatic renewal (runs twice daily)
|
||||
(crontab -l 2>/dev/null; echo '0 12,0 * * * /home/deploy/renew-certificates.sh >> /var/log/letsencrypt-renewal.log 2>&1') | crontab -
|
||||
"
|
||||
|
||||
log_success "Automatic certificate renewal configured"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
log_info "Starting SSL certificate setup for $DOMAIN"
|
||||
|
||||
# Check DNS
|
||||
check_dns
|
||||
|
||||
# Install certbot
|
||||
install_certbot
|
||||
|
||||
# Prepare nginx
|
||||
prepare_nginx
|
||||
|
||||
# Generate certificate
|
||||
generate_certificate
|
||||
|
||||
# Clean up temporary nginx
|
||||
cleanup_nginx
|
||||
|
||||
# Start application
|
||||
start_application
|
||||
|
||||
# Test SSL
|
||||
test_ssl
|
||||
|
||||
# Setup renewal
|
||||
setup_renewal
|
||||
|
||||
log_success "SSL certificate setup completed successfully!"
|
||||
log_info "Next steps:"
|
||||
echo " 1. Test your site: https://$DOMAIN"
|
||||
echo " 2. Certificates will auto-renew twice daily"
|
||||
echo " 3. Check renewal logs: ssh $SERVER_USER@$SERVER_IP 'tail -f /var/log/letsencrypt-renewal.log'"
|
||||
}
|
||||
|
||||
# Show usage
|
||||
show_usage() {
|
||||
echo "Usage: $0 [--help]"
|
||||
echo ""
|
||||
echo "This script sets up Let's Encrypt SSL certificates for $DOMAIN"
|
||||
echo ""
|
||||
echo "Prerequisites:"
|
||||
echo " - Domain $DOMAIN must point to $SERVER_IP"
|
||||
echo " - SSH access to production server configured"
|
||||
echo " - Docker and docker-compose installed on server"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help Show this help message"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
case "${1:-}" in
|
||||
--help|-h)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
"")
|
||||
main
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown option: $1"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
183
scripts/deployment/setup-secrets-interactive.sh
Executable file
183
scripts/deployment/setup-secrets-interactive.sh
Executable file
@@ -0,0 +1,183 @@
|
||||
#!/bin/bash
|
||||
# Interaktives Script zum Setzen der Gitea Secrets via API
|
||||
# Fragt nach Token falls nicht vorhanden
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Repository Info aus git remote
|
||||
REPO_FULL=$(git remote get-url origin 2>/dev/null | sed -E 's/.*[:/]([^/]+)\/([^/]+)\.git$/\1\/\2/' || echo "michael/michaelschiemer")
|
||||
REPO_OWNER=$(echo "$REPO_FULL" | cut -d'/' -f1)
|
||||
REPO_NAME=$(echo "$REPO_FULL" | cut -d'/' -f2)
|
||||
|
||||
GITEA_URL="${GITEA_URL:-https://git.michaelschiemer.de}"
|
||||
GITEA_TOKEN="${GITEA_TOKEN:-}"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE}Gitea Repository Secrets Setup via API${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
echo -e "Repository: ${GREEN}${REPO_OWNER}/${REPO_NAME}${NC}"
|
||||
echo -e "Gitea URL: ${GREEN}${GITEA_URL}${NC}"
|
||||
echo ""
|
||||
|
||||
# Prüfe ob Token vorhanden
|
||||
if [ -z "$GITEA_TOKEN" ]; then
|
||||
echo -e "${YELLOW}⚠️ GITEA_TOKEN nicht gefunden${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}Du musst zuerst einen Gitea Access Token erstellen:${NC}"
|
||||
echo ""
|
||||
echo "1. Öffne im Browser:"
|
||||
echo -e " ${GREEN}${GITEA_URL}/user/settings/applications${NC}"
|
||||
echo ""
|
||||
echo "2. Scrolle zu 'Generate New Token'"
|
||||
echo ""
|
||||
echo "3. Konfiguration:"
|
||||
echo " - Name: z.B. 'CI/CD Secrets Setup'"
|
||||
echo " - Scopes: ✅ write:repository (mindestens)"
|
||||
echo ""
|
||||
echo "4. Klicke 'Generate Token'"
|
||||
echo ""
|
||||
echo "5. Kopiere den Token (wird nur einmal angezeigt!)"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Dann füge den Token hier ein (wird nicht angezeigt):${NC}"
|
||||
read -s -p "Gitea Token: " GITEA_TOKEN
|
||||
echo ""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Funktion zum Setzen eines Secrets
|
||||
set_secret() {
|
||||
local secret_name=$1
|
||||
local secret_value=$2
|
||||
|
||||
echo -n "Setting $secret_name... "
|
||||
|
||||
local response=$(curl -s -w "\n%{http_code}" \
|
||||
-X PUT \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/actions/secrets/${secret_name}" \
|
||||
-d "{
|
||||
\"data\": \"${secret_value}\"
|
||||
}" 2>&1)
|
||||
|
||||
local http_code=$(echo "$response" | tail -n1)
|
||||
local body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" = "204" ] || [ "$http_code" = "201" ]; then
|
||||
echo -e "${GREEN}✅ OK${NC}"
|
||||
return 0
|
||||
elif [ "$http_code" = "404" ]; then
|
||||
echo -e "${RED}❌ Repository nicht gefunden (404)${NC}"
|
||||
echo " Prüfe: REPO_OWNER=${REPO_OWNER}, REPO_NAME=${REPO_NAME}"
|
||||
return 1
|
||||
elif [ "$http_code" = "403" ]; then
|
||||
echo -e "${RED}❌ Keine Berechtigung (403)${NC}"
|
||||
echo " Token benötigt 'write:repository' Scope"
|
||||
return 1
|
||||
elif [ "$http_code" = "401" ]; then
|
||||
echo -e "${RED}❌ Ungültiger Token (401)${NC}"
|
||||
return 1
|
||||
else
|
||||
echo -e "${RED}❌ FAILED (HTTP $http_code)${NC}"
|
||||
echo "Response: $body"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Prüfe Token-Gültigkeit
|
||||
echo -e "${BLUE}Prüfe Token-Gültigkeit...${NC}"
|
||||
TOKEN_CHECK=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_URL}/api/v1/user" 2>&1)
|
||||
|
||||
if [ "$TOKEN_CHECK" != "200" ]; then
|
||||
echo -e "${RED}❌ Token ist ungültig oder hat keine ausreichenden Berechtigungen${NC}"
|
||||
echo "HTTP Status: $TOKEN_CHECK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Token ist gültig${NC}"
|
||||
echo ""
|
||||
|
||||
# Registry Password
|
||||
REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-registry-secure-password-2025}"
|
||||
|
||||
# SSH Private Key
|
||||
SSH_KEY_PATH="${SSH_KEY_PATH:-$HOME/.ssh/production}"
|
||||
if [ -f "$SSH_KEY_PATH" ]; then
|
||||
SSH_PRIVATE_KEY=$(cat "$SSH_KEY_PATH")
|
||||
echo -e "${GREEN}✓ SSH private key gefunden: ${SSH_KEY_PATH}${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ SSH private key nicht gefunden: ${SSH_KEY_PATH}${NC}"
|
||||
echo ""
|
||||
read -p "SSH Key Pfad (oder Enter für Skip): " custom_ssh_path
|
||||
if [ -n "$custom_ssh_path" ] && [ -f "$custom_ssh_path" ]; then
|
||||
SSH_PRIVATE_KEY=$(cat "$custom_ssh_path")
|
||||
echo -e "${GREEN}✓ SSH private key geladen${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Überspringe SSH_PRIVATE_KEY${NC}"
|
||||
SSH_PRIVATE_KEY=""
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}Setze Secrets für Repository: ${REPO_OWNER}/${REPO_NAME}${NC}"
|
||||
echo ""
|
||||
|
||||
# Setze Secrets
|
||||
ERRORS=0
|
||||
|
||||
echo -e "${BLUE}Secret 1/3: REGISTRY_USER${NC}"
|
||||
if set_secret "REGISTRY_USER" "admin"; then
|
||||
echo ""
|
||||
else
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}Secret 2/3: REGISTRY_PASSWORD${NC}"
|
||||
if set_secret "REGISTRY_PASSWORD" "$REGISTRY_PASSWORD"; then
|
||||
echo ""
|
||||
else
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
if [ -n "$SSH_PRIVATE_KEY" ]; then
|
||||
echo -e "${BLUE}Secret 3/3: SSH_PRIVATE_KEY${NC}"
|
||||
# Escape JSON special characters
|
||||
SSH_PRIVATE_KEY_ESCAPED=$(echo "$SSH_PRIVATE_KEY" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
if set_secret "SSH_PRIVATE_KEY" "$SSH_PRIVATE_KEY_ESCAPED"; then
|
||||
echo ""
|
||||
else
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Überspringe SSH_PRIVATE_KEY (nicht gefunden)${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Zusammenfassung
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||||
if [ $ERRORS -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ Secrets Setup erfolgreich abgeschlossen!${NC}"
|
||||
echo ""
|
||||
echo -e "Verifizierung:"
|
||||
echo -e " - Gehe zu: ${GREEN}${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/settings${NC}"
|
||||
echo -e " - Oder teste den Workflow: ${GREEN}Repository → Actions → Test Registry Credentials${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}❌ Fehler beim Setzen von $ERRORS Secret(s)${NC}"
|
||||
echo ""
|
||||
echo "Troubleshooting:"
|
||||
echo " - Prüfe Token-Berechtigungen (benötigt: write:repository)"
|
||||
echo " - Prüfe Repository-Name: ${REPO_OWNER}/${REPO_NAME}"
|
||||
echo " - Prüfe ob Actions für das Repository aktiviert ist"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user