Files
michaelschiemer/docs/deployment/DEPLOYMENT_WORKFLOW.md
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

17 KiB

Concrete Deployment Workflow

Schritt-für-Schritt Anleitung für das Production Deployment mit und ohne Ansible.

Deployment-Optionen

Das Framework bietet zwei Deployment-Strategien:

  1. Manual/Script-Based (einfach, für Single-Server)
  2. Ansible-Based (automatisiert, für Multi-Server)

Beide Strategien nutzen Docker Compose als Container-Orchestrierung.


Option 1: Manual/Script-Based Deployment (Empfohlen für Start)

Voraussetzungen

  • Server mit Ubuntu 22.04 LTS
  • SSH-Zugriff mit sudo-Rechten
  • Domain mit DNS konfiguriert
  • Git Repository Access

Phase 1: Initiales Server Setup (Einmalig)

1.1 Server vorbereiten

# SSH-Verbindung zum Server
ssh user@your-server.com

# System aktualisieren
sudo apt update && sudo apt upgrade -y

# Docker installieren
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

# Docker Compose installieren
sudo apt install -y docker-compose-plugin

# Neuanmeldung für Docker-Gruppe
exit
ssh user@your-server.com

# Verify
docker --version
docker compose version

1.2 Projektverzeichnisse erstellen

# Verzeichnisstruktur anlegen
sudo mkdir -p /var/www/app
sudo mkdir -p /var/log/app
sudo mkdir -p /opt/vault
sudo mkdir -p /etc/ssl/app
sudo mkdir -p /backups/database
sudo mkdir -p /backups/volumes

# Berechtigungen setzen
sudo chown -R $USER:$USER /var/www/app
sudo chown -R www-data:www-data /var/log/app
sudo chown -R www-data:www-data /opt/vault
sudo chmod 755 /var/www/app
sudo chmod 755 /var/log/app
sudo chmod 700 /opt/vault

1.3 Repository klonen

cd /var/www
git clone git@github.com:yourusername/app.git
cd app

# Production branch
git checkout production

# Scripts ausführbar machen
chmod +x scripts/deployment/*.sh

1.4 SSL-Zertifikat einrichten

# Nginx für Certbot installieren
sudo apt install -y nginx certbot python3-certbot-nginx

# Temporäre Nginx-Config für Certbot
sudo tee /etc/nginx/sites-available/temp-certbot > /dev/null <<'EOF'
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/temp-certbot /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

# Zertifikat holen
sudo certbot certonly --webroot \
    -w /var/www/certbot \
    -d yourdomain.com \
    -d www.yourdomain.com \
    --email your-email@example.com \
    --agree-tos \
    --no-eff-email

# Zertifikate für Container verfügbar machen
sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem /etc/ssl/app/cert.pem
sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem /etc/ssl/app/key.pem
sudo chmod 644 /etc/ssl/app/cert.pem
sudo chmod 600 /etc/ssl/app/key.pem

# Auto-Renewal einrichten
echo "0 3 * * * root certbot renew --quiet && cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem /etc/ssl/app/cert.pem && cp /etc/letsencrypt/live/yourdomain.com/privkey.pem /etc/ssl/app/key.pem && docker compose -f /var/www/app/docker-compose.production.yml restart nginx" | sudo tee -a /etc/crontab

1.5 Vault Encryption Key generieren

cd /var/www/app

# Key generieren
php scripts/deployment/generate-vault-key.php

# Output kopieren (sicher speichern!):
# VAULT_ENCRYPTION_KEY=base64encodedkey...

# In 1Password, Bitwarden, oder AWS Secrets Manager speichern

1.6 Environment File erstellen

cd /var/www/app

# Template kopieren
cp .env.example .env.production

# Mit echten Production-Werten füllen
nano .env.production

Minimal erforderliche Werte:

# Application
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com

# Database
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=app_production
DB_USERNAME=app_user
DB_PASSWORD=<strong-database-password>

# Cache & Queue
CACHE_DRIVER=redis
QUEUE_DRIVER=redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=<strong-redis-password>

# Vault
VAULT_ENCRYPTION_KEY=<from-generate-vault-key>

# Admin Access
ADMIN_ALLOWED_IPS=your.ip.address.here

# Logging
LOG_PATH=/var/log/app
LOG_LEVEL=info

1.7 Secrets in Vault speichern

# Secrets-Setup Script ausführen
php scripts/deployment/setup-production-secrets.php

# Manuelle Secrets hinzufügen
docker compose -f docker-compose.production.yml run --rm php php -r "
require 'vendor/autoload.php';
\$vault = new App\Framework\Vault\EncryptedVault(
    \$_ENV['VAULT_ENCRYPTION_KEY'],
    '/opt/vault/production.vault'
);

// API Keys
\$vault->set(
    App\Framework\Vault\SecretKey::from('stripe_secret_key'),
    App\Framework\Vault\SecretValue::from('sk_live_...')
);

// Mail Password
\$vault->set(
    App\Framework\Vault\SecretKey::from('mail_password'),
    App\Framework\Vault\SecretValue::from('your-mail-password')
);

echo 'Secrets stored successfully\n';
"

Phase 2: Initiales Deployment

2.1 Dependencies installieren

cd /var/www/app

# Composer Dependencies
docker compose -f docker-compose.production.yml run --rm php composer install --no-dev --optimize-autoloader

# NPM Dependencies und Build
docker compose -f docker-compose.production.yml run --rm nodejs npm ci
docker compose -f docker-compose.production.yml run --rm nodejs npm run build

2.2 Container starten

# Docker Images bauen
docker compose -f docker-compose.production.yml build

# Container starten
docker compose -f docker-compose.production.yml up -d

# Logs verfolgen
docker compose -f docker-compose.production.yml logs -f

2.3 Datenbank initialisieren

# Warten bis MySQL ready ist
sleep 30

# Migrations ausführen
docker compose -f docker-compose.production.yml exec php php console.php db:migrate

# Verify
docker compose -f docker-compose.production.yml exec php php console.php db:status

2.4 Health Checks verifizieren

# Health Check (sollte 200 zurückgeben)
curl -f http://localhost/health || echo "Health check failed"

# Detailed Health Report
curl -s http://localhost/health/detailed | jq

# Alle Checks sollten "healthy" sein
curl -s http://localhost/health/summary | jq '.summary'

2.5 Nginx Reverse Proxy konfigurieren

# System Nginx als Reverse Proxy
sudo tee /etc/nginx/sites-available/app > /dev/null <<'EOF'
upstream app_backend {
    server localhost:8080;
}

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    ssl_certificate /etc/ssl/app/cert.pem;
    ssl_certificate_key /etc/ssl/app/key.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Security Headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Proxy to Docker container
    location / {
        proxy_pass http://app_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # Increase timeouts for long-running requests
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
}
EOF

# Enable site
sudo ln -sf /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo rm -f /etc/nginx/sites-enabled/temp-certbot

# Test config
sudo nginx -t

# Reload
sudo systemctl reload nginx

2.6 Finaler Test

# HTTPS Health Check
curl -f https://yourdomain.com/health || echo "HTTPS health check failed"

# SSL Test
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com < /dev/null

# Metrics
curl https://yourdomain.com/metrics | head -20

# Homepage
curl -I https://yourdomain.com

Phase 3: Laufendes Deployment (Updates)

3.1 Automatisches Deployment Script nutzen

cd /var/www/app

# Standard Deployment
./scripts/deployment/deploy-production.sh

# Mit spezifischem Branch
./scripts/deployment/deploy-production.sh --branch production-v2.1.0

# Dry-Run (keine Änderungen)
./scripts/deployment/deploy-production.sh --dry-run

Das Script führt automatisch aus:

  1. Pre-deployment Checks
  2. Backup Erstellung
  3. Git Pull
  4. Composer/NPM Install
  5. Docker Image Build
  6. Database Migrations
  7. Container Restart
  8. Health Checks
  9. Smoke Tests

3.2 Zero-Downtime Deployment (Blue-Green)

# Blue-Green Deployment für Zero-Downtime
./scripts/deployment/blue-green-deploy.sh

# Bei Problemen: Rollback
./scripts/deployment/blue-green-rollback.sh

3.3 Manuelles Deployment (wenn Scripts nicht verfügbar)

cd /var/www/app

# 1. Pre-Deployment Backup
docker compose -f docker-compose.production.yml exec db \
    mysqldump -u app_user -p<password> app_production \
    > /backups/database/backup_$(date +%Y%m%d_%H%M%S).sql

# 2. Git Pull
git fetch origin production
git checkout production
git pull origin production

# 3. Dependencies aktualisieren
docker compose -f docker-compose.production.yml run --rm php \
    composer install --no-dev --optimize-autoloader

# 4. Frontend Build (falls geändert)
docker compose -f docker-compose.production.yml run --rm nodejs npm ci
docker compose -f docker-compose.production.yml run --rm nodejs npm run build

# 5. Images neu bauen
docker compose -f docker-compose.production.yml build

# 6. Migrations ausführen
docker compose -f docker-compose.production.yml exec php php console.php db:migrate

# 7. Container neu starten
docker compose -f docker-compose.production.yml up -d --no-deps --build php nginx

# 8. Health Check
curl -f https://yourdomain.com/health/summary

# 9. Logs prüfen
docker compose -f docker-compose.production.yml logs -f --tail=100 php

Phase 4: Monitoring Setup

4.1 Prometheus (Optional)

# docker-compose.monitoring.yml erstellen
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=<strong-password>
    restart: unless-stopped

volumes:
  prometheus-data:
  grafana-data:
# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'app'
    static_configs:
      - targets: ['app-nginx:80']
    metrics_path: '/metrics'
# Monitoring starten
docker compose -f docker-compose.monitoring.yml up -d

# Grafana öffnen: http://your-server:3000
# Login: admin / <strong-password>
# Dashboard importieren: docs/deployment/grafana-dashboard.json

4.2 Alerting (Optional)

# Simple Alert Script für kritische Health Checks
tee /opt/health-check-alert.sh > /dev/null <<'EOF'
#!/bin/bash
HEALTH=$(curl -s http://localhost/health/summary | jq -r '.overall_healthy')

if [ "$HEALTH" != "true" ]; then
    # Alert senden (Email, Slack, PagerDuty, etc.)
    curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
        -H 'Content-Type: application/json' \
        -d '{"text":"🚨 Production Health Check FAILED!"}'
fi
EOF

chmod +x /opt/health-check-alert.sh

# Crontab: Jede 5 Minuten prüfen
echo "*/5 * * * * /opt/health-check-alert.sh" | crontab -

Option 2: Ansible-Based Deployment (Multi-Server)

Wann Ansible verwenden?

Verwende Ansible wenn:

  • Mehrere Production Server (Load Balancing)
  • Staging + Production Environments
  • Infrastructure as Code gewünscht
  • Wiederholbare, idempotente Deployments
  • Team-basierte Deployments

Ansible NICHT notwendig wenn:

  • Einzelner Production Server
  • Einfache Infrastruktur
  • Kleine Team-Größe
  • Docker Compose Scripts ausreichend

Ansible Setup

Siehe separate Dokumentation: ANSIBLE_DEPLOYMENT.md

Kurzübersicht:

# Ansible installieren
pip install ansible

# Playbooks ausführen
cd ansible
ansible-playbook -i inventory/production site.yml

# Spezifische Playbooks
ansible-playbook -i inventory/production playbooks/deploy.yml
ansible-playbook -i inventory/production playbooks/rollback.yml

Deployment-Checkliste

Pre-Deployment

  • Server vorbereitet und zugänglich
  • Domain DNS konfiguriert
  • SSL-Zertifikat vorhanden
  • Vault Encryption Key generiert und sicher gespeichert
  • Environment File .env.production erstellt
  • Secrets in Vault gespeichert
  • Docker und Docker Compose installiert
  • Nginx Reverse Proxy konfiguriert

Initial Deployment

  • Repository geklont
  • Dependencies installiert
  • Docker Images gebaut
  • Container gestartet
  • Datenbank migriert
  • Health Checks grün
  • HTTPS funktioniert
  • Monitoring konfiguriert (optional)

Laufendes Deployment

  • Backup erstellt
  • Git Pull erfolgreich
  • Dependencies aktualisiert
  • Frontend gebaut (falls nötig)
  • Images neu gebaut
  • Migrations ausgeführt
  • Container neu gestartet
  • Health Checks grün
  • Smoke Tests erfolgreich
  • Logs geprüft

Post-Deployment

  • Application erreichbar
  • Alle Features funktional
  • Performance akzeptabel
  • Monitoring aktiv
  • Logs rotieren
  • Backups funktionieren
  • Rollback-Plan getestet

Rollback-Prozedur

Quick Rollback

cd /var/www/app

# 1. Zu vorherigem Commit
git log --oneline -10  # Vorherigen Commit finden
git checkout <previous-commit>

# 2. Dependencies (falls nötig)
docker compose -f docker-compose.production.yml run --rm php \
    composer install --no-dev --optimize-autoloader

# 3. Migrations rückgängig
docker compose -f docker-compose.production.yml exec php \
    php console.php db:rollback 3

# 4. Container neu starten
docker compose -f docker-compose.production.yml up -d --build

# 5. Health Check
curl -f https://yourdomain.com/health/summary

Database Rollback

# Datenbank aus Backup wiederherstellen
docker compose -f docker-compose.production.yml exec -T db \
    mysql -u app_user -p<password> app_production \
    < /backups/database/backup_20250115_120000.sql

# Verify
docker compose -f docker-compose.production.yml exec php \
    php console.php db:status

Troubleshooting Deployment

Container starten nicht

# Logs prüfen
docker compose -f docker-compose.production.yml logs

# Port-Konflikte prüfen
sudo netstat -tulpn | grep -E ':(80|443|3306|6379)'

# Container Status
docker compose -f docker-compose.production.yml ps

# Neustart
docker compose -f docker-compose.production.yml down
docker compose -f docker-compose.production.yml up -d

Health Checks schlagen fehl

# Detailed Health Report
curl http://localhost/health/detailed | jq

# Spezifische Checks
curl http://localhost/health/category/database | jq
curl http://localhost/health/category/security | jq

# Container-Logs
docker compose -f docker-compose.production.yml logs php
docker compose -f docker-compose.production.yml logs nginx

Migrations schlagen fehl

# Migration Status
docker compose -f docker-compose.production.yml exec php \
    php console.php db:status

# Migrations rollback
docker compose -f docker-compose.production.yml exec php \
    php console.php db:rollback 1

# Database Connection testen
docker compose -f docker-compose.production.yml exec php \
    php -r "new PDO('mysql:host=db;dbname=app_production', 'app_user', '<password>');"

Empfohlener Workflow für dein Projekt

Für Initial Setup und kleine Deployments:

Verwende Script-Based Deployment:

  1. Server Setup (einmalig): Siehe Phase 1
  2. Initial Deployment: Siehe Phase 2
  3. Updates: ./scripts/deployment/deploy-production.sh
  4. Zero-Downtime: ./scripts/deployment/blue-green-deploy.sh

Für Skalierung und Multiple Environments:

Ergänze mit Ansible:

  1. Server Provisioning automatisieren
  2. Multi-Server Deployments orchestrieren
  3. Konsistente Configuration Management
  4. Infrastructure as Code

Siehe nächstes Dokument: ANSIBLE_DEPLOYMENT.md


Nächste Schritte

  1. Server vorbereiten (Phase 1)
  2. Initial Deployment durchführen (Phase 2)
  3. Monitoring einrichten (Phase 4)
  4. 📝 Deployment dokumentieren
  5. 🔄 Ansible evaluieren (optional, wenn Multi-Server)

Für detaillierte Ansible-Integration siehe nächstes Dokument!