ci: setup CI/CD pipeline with Gitea Actions and secrets configuration

This commit is contained in:
2025-10-31 01:31:44 +01:00
parent 38baaca06b
commit 55c04e4fd0
28 changed files with 2113 additions and 958 deletions

View File

@@ -1,83 +0,0 @@
#!/bin/bash
# Production Deployment Script
# This script prepares the application for production deployment
set -e
echo "🚀 Starting Production Deployment..."
# Check if we're in the right directory
if [ ! -f "composer.json" ]; then
echo "❌ Error: Must be run from project root directory"
exit 1
fi
# Backup current .env if it exists
if [ -f ".env" ]; then
echo "📦 Backing up current .env to .env.backup"
cp .env .env.backup
fi
# Copy production environment file
echo "📝 Setting up production environment..."
cp .env.production .env
# Clear all caches
echo "🧹 Clearing caches..."
rm -rf storage/cache/*
rm -rf var/cache/*
rm -rf cache/*
# Install production dependencies (no dev dependencies)
echo "📦 Installing production dependencies..."
composer install --no-dev --optimize-autoloader --no-interaction
# Build production assets
echo "🎨 Building production assets..."
npm run build
# Set correct permissions
echo "🔐 Setting correct permissions..."
chmod -R 755 storage/
chmod -R 755 var/
chmod -R 755 public/
# Create necessary directories
mkdir -p storage/logs
mkdir -p storage/cache
mkdir -p var/cache
mkdir -p var/logs
# Run database migrations
echo "🗄️ Running database migrations..."
php console.php db:migrate --force
# Clear PHP opcache if available
if command -v cachetool &> /dev/null; then
echo "🔄 Clearing PHP opcache..."
cachetool opcache:reset
fi
# Restart services (if using systemctl)
if command -v systemctl &> /dev/null; then
echo "🔄 Restarting services..."
sudo systemctl restart php8.4-fpm
sudo systemctl restart nginx
fi
echo "✅ Production deployment complete!"
echo ""
echo "⚠️ IMPORTANT REMINDERS:"
echo "1. Ensure APP_ENV=production in .env"
echo "2. Ensure APP_DEBUG=false in .env"
echo "3. Update database credentials if needed"
echo "4. Update ADMIN_ALLOWED_IPS in .env for admin access"
echo "5. Test the site to ensure everything works"
echo ""
echo "🔒 Security Checklist:"
echo "[ ] Performance debug is disabled"
echo "[ ] Session debug info is hidden"
echo "[ ] Admin routes are IP-restricted"
echo "[ ] Error messages are generic"
echo "[ ] HTTPS is enforced"

View File

@@ -221,4 +221,4 @@ try {
exit(1);
}
echo "\n🎉 Migration script completed!\n";
echo "\n🎉 Migration script completed!\n";

34
scripts/prepare-secrets.sh Executable file
View 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 ""

View File

@@ -1,446 +0,0 @@
#!/bin/bash
# Production Deployment Script for Custom PHP Framework
# Comprehensive deployment automation with zero-downtime strategy
#
# Usage:
# ./scripts/production-deploy.sh [initial|update|rollback]
#
# Modes:
# initial - First-time production deployment
# update - Rolling update with zero downtime
# rollback - Rollback to previous version
set -euo pipefail
# Configuration
DEPLOY_MODE="${1:-update}"
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BACKUP_DIR="${PROJECT_ROOT}/../backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="${BACKUP_DIR}/backup_${TIMESTAMP}"
# Colors
GREEN="\e[32m"
YELLOW="\e[33m"
RED="\e[31m"
BLUE="\e[34m"
RESET="\e[0m"
# Logging functions
log() {
echo -e "${BLUE}[$(date +'%H:%M:%S')]${RESET} $1"
}
success() {
echo -e "${GREEN}$1${RESET}"
}
warning() {
echo -e "${YELLOW}⚠️ $1${RESET}"
}
error() {
echo -e "${RED}$1${RESET}"
cleanup_on_error
exit 1
}
# Cleanup on error
cleanup_on_error() {
log "Cleaning up after error..."
if [[ -d "$BACKUP_PATH" ]]; then
warning "Rolling back to previous version..."
restore_backup "$BACKUP_PATH"
fi
}
# Prerequisites check
check_prerequisites() {
log "Checking prerequisites..."
# Check if running from project root
if [[ ! -f "$PROJECT_ROOT/composer.json" ]]; then
error "Must be run from project root directory"
fi
# Check Docker
if ! command -v docker &> /dev/null; then
error "Docker is not installed"
fi
# Check Docker Compose
if ! docker compose version &> /dev/null; then
error "Docker Compose is not installed"
fi
# Check .env.production exists
if [[ ! -f "$PROJECT_ROOT/.env.production" ]]; then
error ".env.production not found - copy from .env.example and configure"
fi
# Check docker-compose.production.yml exists
if [[ ! -f "$PROJECT_ROOT/docker-compose.production.yml" ]]; then
error "docker-compose.production.yml not found"
fi
# Verify VAULT_ENCRYPTION_KEY is set
if ! grep -q "VAULT_ENCRYPTION_KEY=" "$PROJECT_ROOT/.env.production" || \
grep -q "VAULT_ENCRYPTION_KEY=CHANGE_ME" "$PROJECT_ROOT/.env.production"; then
error "VAULT_ENCRYPTION_KEY not configured in .env.production"
fi
success "Prerequisites check passed"
}
# Create backup
create_backup() {
log "Creating backup..."
mkdir -p "$BACKUP_DIR"
# Backup database
if docker compose ps db | grep -q "Up"; then
log "Backing up database..."
docker compose exec -T db pg_dump -U postgres michaelschiemer_prod | \
gzip > "${BACKUP_PATH}_database.sql.gz"
success "Database backup created"
fi
# Backup .env
if [[ -f "$PROJECT_ROOT/.env" ]]; then
cp "$PROJECT_ROOT/.env" "${BACKUP_PATH}_env"
success ".env backup created"
fi
# Backup docker volumes (important directories)
if [[ -d "$PROJECT_ROOT/storage" ]]; then
tar -czf "${BACKUP_PATH}_storage.tar.gz" -C "$PROJECT_ROOT" storage
success "Storage backup created"
fi
success "Backup completed: $BACKUP_PATH"
}
# Restore from backup
restore_backup() {
local backup_path="$1"
log "Restoring from backup: $backup_path"
# Restore database
if [[ -f "${backup_path}_database.sql.gz" ]]; then
log "Restoring database..."
gunzip -c "${backup_path}_database.sql.gz" | \
docker compose exec -T db psql -U postgres michaelschiemer_prod
success "Database restored"
fi
# Restore .env
if [[ -f "${backup_path}_env" ]]; then
cp "${backup_path}_env" "$PROJECT_ROOT/.env"
success ".env restored"
fi
# Restore storage
if [[ -f "${backup_path}_storage.tar.gz" ]]; then
tar -xzf "${backup_path}_storage.tar.gz" -C "$PROJECT_ROOT"
success "Storage restored"
fi
# Restart services
docker compose -f docker-compose.yml \
-f docker-compose.production.yml \
--env-file .env.production \
restart
success "Backup restored successfully"
}
# Build Docker images
build_images() {
log "Building Docker images..."
cd "$PROJECT_ROOT"
docker compose -f docker-compose.yml \
-f docker-compose.production.yml \
--env-file .env.production \
build --no-cache
success "Docker images built"
}
# Run database migrations
run_migrations() {
log "Running database migrations..."
cd "$PROJECT_ROOT"
# Check migration status first
docker compose exec -T php php console.php db:status || true
# Run migrations
if ! docker compose exec -T php php console.php db:migrate; then
error "Database migrations failed"
fi
success "Database migrations completed"
}
# Initialize SSL certificates
init_ssl() {
log "Initializing SSL certificates..."
cd "$PROJECT_ROOT"
# Check if SSL is enabled
if grep -q "SSL_ENABLED=true" .env.production; then
log "SSL is enabled, checking certificate status..."
# Check certificate status
if docker compose exec -T php php console.php ssl:status 2>/dev/null | grep -q "Certificate is valid"; then
success "SSL certificate already exists and is valid"
else
warning "SSL certificate not found or invalid, initializing..."
if ! docker compose exec -T php php console.php ssl:init; then
error "SSL initialization failed"
fi
success "SSL certificate initialized"
fi
else
warning "SSL is disabled in .env.production"
fi
}
# Verify Vault configuration
verify_vault() {
log "Verifying Vault configuration..."
cd "$PROJECT_ROOT"
# Test Vault access
if ! docker compose exec -T php php console.php vault:list &>/dev/null; then
error "Vault not accessible - check VAULT_ENCRYPTION_KEY"
fi
success "Vault is configured correctly"
}
# Health check with retries
health_check() {
local max_retries=30
local retry_count=0
log "Running health checks..."
while [[ $retry_count -lt $max_retries ]]; do
if curl -f -s -k -H "User-Agent: Mozilla/5.0 (Deployment Health Check)" "https://localhost/health" > /dev/null 2>&1; then
success "Health check passed"
return 0
fi
retry_count=$((retry_count + 1))
log "Health check attempt $retry_count/$max_retries..."
sleep 2
done
error "Health check failed after $max_retries attempts"
}
# Initial deployment
initial_deployment() {
log "🚀 Starting initial production deployment..."
check_prerequisites
cd "$PROJECT_ROOT"
# 1. Generate Vault encryption key if not exists
if grep -q "VAULT_ENCRYPTION_KEY=CHANGE_ME" .env.production; then
log "Generating Vault encryption key..."
warning "Make sure to backup this key securely!"
# Key generation is done manually for security
error "Please generate VAULT_ENCRYPTION_KEY with: docker exec php php console.php vault:generate-key"
fi
# 2. Build images
build_images
# 3. Start services
log "Starting Docker services..."
docker compose -f docker-compose.yml \
-f docker-compose.production.yml \
--env-file .env.production \
up -d
# 4. Wait for services to be ready
log "Waiting for services to be ready..."
sleep 20
# 5. Run migrations
run_migrations
# 6. Initialize SSL
init_ssl
# 7. Verify Vault
verify_vault
# 8. Health check
health_check
# 9. Display summary
deployment_summary
success "🎉 Initial deployment completed successfully!"
}
# Update deployment (zero-downtime)
update_deployment() {
log "🔄 Starting rolling update deployment..."
check_prerequisites
create_backup
cd "$PROJECT_ROOT"
# 1. Pull latest images (if using registry)
log "Pulling latest images..."
docker compose -f docker-compose.yml \
-f docker-compose.production.yml \
--env-file .env.production \
pull || warning "Pull failed (not critical if building locally)"
# 2. Build new images
build_images
# 3. Run migrations (if any)
log "Running database migrations..."
docker compose exec -T php php console.php db:migrate || warning "No new migrations"
# 4. Rolling restart with health checks
log "Performing rolling restart..."
# Restart PHP-FPM first
docker compose -f docker-compose.yml \
-f docker-compose.production.yml \
--env-file .env.production \
up -d --no-deps --force-recreate php
sleep 10
# Restart web server
docker compose -f docker-compose.yml \
-f docker-compose.production.yml \
--env-file .env.production \
up -d --no-deps --force-recreate web
sleep 5
# Restart queue workers (graceful shutdown via stop_grace_period)
docker compose -f docker-compose.yml \
-f docker-compose.production.yml \
--env-file .env.production \
up -d --no-deps --force-recreate --scale queue-worker=2 queue-worker
# 5. Health check
health_check
# 6. Cleanup old images
log "Cleaning up old Docker images..."
docker image prune -f
# 7. Display summary
deployment_summary
success "🎉 Update deployment completed successfully!"
}
# Rollback deployment
rollback_deployment() {
log "⏪ Starting rollback..."
# Find latest backup
local latest_backup=$(find "$BACKUP_DIR" -name "backup_*_database.sql.gz" | sort -r | head -1)
if [[ -z "$latest_backup" ]]; then
error "No backup found for rollback"
fi
local backup_prefix="${latest_backup%_database.sql.gz}"
warning "Rolling back to: $backup_prefix"
read -p "Continue? (yes/no): " confirm
if [[ "$confirm" != "yes" ]]; then
log "Rollback cancelled"
exit 0
fi
restore_backup "$backup_prefix"
health_check
success "🎉 Rollback completed successfully!"
}
# Deployment summary
deployment_summary() {
echo ""
echo -e "${GREEN}========================================${RESET}"
echo -e "${GREEN} Deployment Summary${RESET}"
echo -e "${GREEN}========================================${RESET}"
echo ""
echo "📋 Mode: $DEPLOY_MODE"
echo "⏰ Timestamp: $(date)"
echo "📁 Project: $PROJECT_ROOT"
echo "💾 Backup: $BACKUP_PATH"
echo ""
echo "🐳 Docker Services:"
docker compose ps
echo ""
echo "🔒 Security Checks:"
echo " [ ] APP_ENV=production in .env.production"
echo " [ ] APP_DEBUG=false in .env.production"
echo " [ ] VAULT_ENCRYPTION_KEY configured"
echo " [ ] ADMIN_ALLOWED_IPS configured"
echo " [ ] SSL certificates valid"
echo ""
echo "📊 Health Check:"
echo " ✅ Application: https://localhost/health"
echo ""
echo "📝 Next Steps:"
echo " 1. Verify all services are running"
echo " 2. Check logs: docker compose logs -f --tail=100"
echo " 3. Test critical user flows"
echo " 4. Monitor error rates"
echo ""
echo -e "${GREEN}========================================${RESET}"
}
# Main deployment logic
main() {
case "$DEPLOY_MODE" in
initial)
initial_deployment
;;
update)
update_deployment
;;
rollback)
rollback_deployment
;;
*)
error "Invalid deployment mode: $DEPLOY_MODE. Use: initial|update|rollback"
;;
esac
}
# Trap errors
trap cleanup_on_error ERR
# Run main
main "$@"

View File

@@ -1,240 +0,0 @@
#!/bin/bash
# Server-side Deployment Script für Custom PHP Framework
# Läuft auf dem Production-Server (94.16.110.151)
set -euo pipefail # Exit on any error
DEPLOY_TAG="$1"
DEPLOY_PATH="$2"
BACKUP_PATH="${DEPLOY_PATH}-backup-$(date +%Y%m%d-%H%M%S)"
TEMP_PATH="${DEPLOY_PATH}-deploying"
# Farben
GREEN="\e[32m"
YELLOW="\e[33m"
RED="\e[31m"
BLUE="\e[34m"
RESET="\e[0m"
log() {
echo -e "${BLUE}[SERVER $(date +'%H:%M:%S')]${RESET} $1"
}
success() {
echo -e "${GREEN}$1${RESET}"
}
error() {
echo -e "${RED}$1${RESET}"
cleanup_on_error
exit 1
}
cleanup_on_error() {
log "Cleanup nach Fehler..."
[[ -d "$TEMP_PATH" ]] && rm -rf "$TEMP_PATH"
[[ -d "$BACKUP_PATH" ]] && {
log "Stelle vorherige Version wieder her..."
[[ -d "$DEPLOY_PATH" ]] && rm -rf "$DEPLOY_PATH"
mv "$BACKUP_PATH" "$DEPLOY_PATH"
cd "$DEPLOY_PATH" && docker compose restart
}
}
# Atomic Deployment mit Git
atomic_git_deployment() {
log "Starte atomic git deployment..."
# 1. Backup der aktuellen Version erstellen
if [[ -d "$DEPLOY_PATH" ]]; then
log "Erstelle Backup der aktuellen Version..."
cp -r "$DEPLOY_PATH" "$BACKUP_PATH"
success "Backup erstellt: $BACKUP_PATH"
fi
# 2. Neue Version in temporäres Verzeichnis clonen
log "Clone neue Version mit Tag: $DEPLOY_TAG"
if [[ -d "$TEMP_PATH" ]]; then
rm -rf "$TEMP_PATH"
fi
# Git Repository klonen oder pullen
if [[ -d "$DEPLOY_PATH/.git" ]]; then
# Existierendes Repository - fetch und checkout
log "Update existierendes Repository..."
cd "$DEPLOY_PATH"
git fetch --tags origin
git checkout "$DEPLOY_TAG"
success "Git checkout zu $DEPLOY_TAG erfolgreich"
else
# Neues Repository klonen
log "Klone Repository neu..."
git clone --depth 1 --branch "$DEPLOY_TAG" "$(git -C . remote get-url origin)" "$TEMP_PATH" || {
error "Git clone fehlgeschlagen"
}
# Atomic Switch: Temp → Live
if [[ -d "$DEPLOY_PATH" ]]; then
mv "$DEPLOY_PATH" "${DEPLOY_PATH}-old"
fi
mv "$TEMP_PATH" "$DEPLOY_PATH"
fi
}
# Framework-spezifische Deployment-Schritte
framework_deployment() {
log "Führe Framework-Deployment durch..."
cd "$DEPLOY_PATH"
# 1. Environment Setup
if [[ ! -f .env ]]; then
if [[ -f .env.production ]]; then
log "Kopiere .env.production zu .env"
cp .env.production .env
else
error ".env.production nicht gefunden"
fi
fi
# 2. Composer Dependencies (Production)
log "Installiere Composer Dependencies..."
if ! composer install --no-dev --optimize-autoloader --no-interaction; then
error "Composer Install fehlgeschlagen"
fi
# 3. Framework Cache warming (falls implementiert)
if [[ -f console.php ]] && php console.php list | grep -q "cache:warm"; then
log "Wärme Framework Caches auf..."
php console.php cache:warm || warning "Cache warming fehlgeschlagen"
fi
# 4. Database Migrations
log "Führe Database Migrations durch..."
if php console.php list | grep -q "db:migrate"; then
php console.php db:migrate || error "Database Migration fehlgeschlagen"
else
warning "Keine Database Migrations gefunden"
fi
# 5. Framework optimizations
if php console.php list | grep -q "framework:optimize"; then
log "Optimiere Framework..."
php console.php framework:optimize || warning "Framework Optimization fehlgeschlagen"
fi
success "Framework-Deployment abgeschlossen"
}
# Docker Services Management
manage_docker_services() {
log "Manage Docker Services..."
cd "$DEPLOY_PATH"
# Prüfe ob docker-compose.yml existiert
if [[ ! -f docker-compose.yml ]]; then
error "docker-compose.yml nicht gefunden"
fi
# Services neu starten mit minimaler Downtime
log "Starte Services neu..."
# Rolling Update Strategy
docker compose pull --quiet || warning "Docker Pull Warnings (nicht kritisch)"
# Restart mit Health Checks
if docker compose up -d --force-recreate --remove-orphans; then
success "Docker Services erfolgreich neu gestartet"
else
error "Docker Restart fehlgeschlagen"
fi
# Warte auf Service-Start
log "Warte auf Service-Start..."
sleep 10
}
# Health Checks
health_checks() {
log "Führe Health Checks durch..."
cd "$DEPLOY_PATH"
# 1. Framework Health Check
if php console.php health:check; then
success "Framework Health Check OK"
else
error "Framework Health Check fehlgeschlagen"
fi
# 2. Docker Services Check
if ! docker compose ps | grep -q "Up"; then
error "Docker Services nicht verfügbar"
fi
success "Docker Services OK"
# 3. MCP Server Test (optional)
if timeout 5 php console.php mcp:server --test 2>/dev/null; then
success "MCP Server OK"
else
log "MCP Server Test übersprungen (optional)"
fi
# 4. Web Response Test
sleep 5
if curl -f -s -H "User-Agent: Mozilla/5.0 (Deployment Health Check)" "http://localhost" > /dev/null; then
success "HTTP Response OK"
else
warning "HTTP Response Test fehlgeschlagen (möglicherweise nginx-Problem)"
fi
}
# Cleanup alte Backups (behalte nur die letzten 5)
cleanup_old_backups() {
log "Räume alte Backups auf..."
# Finde alle Backup-Ordner und behalte nur die 5 neuesten
find "$(dirname "$DEPLOY_PATH")" -maxdepth 1 -name "*-backup-*" -type d | \
sort -r | \
tail -n +6 | \
xargs -r rm -rf
success "Backup-Cleanup abgeschlossen"
}
# Deployment-Summary
deployment_summary() {
echo -e "${GREEN}"
echo "🎉 Server-Deployment erfolgreich!"
echo "📋 Tag: $DEPLOY_TAG"
echo "📁 Path: $DEPLOY_PATH"
echo "💾 Backup: $BACKUP_PATH"
echo "⏰ Zeit: $(date)"
echo -e "${RESET}"
}
# Hauptprogramm
main() {
log "🚀 Server-side Deployment gestartet"
log "📦 Tag: $DEPLOY_TAG"
log "📁 Path: $DEPLOY_PATH"
atomic_git_deployment
framework_deployment
manage_docker_services
health_checks
cleanup_old_backups
deployment_summary
# Cleanup erfolgreicher Deployment
[[ -d "${DEPLOY_PATH}-old" ]] && rm -rf "${DEPLOY_PATH}-old"
}
# Error Handling
trap cleanup_on_error ERR
# Script ausführen
main "$@"

View 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 ""

View 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/setup-gitea-secrets.sh Executable file
View 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 ""

View 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 ""