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

- 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:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

View File

@@ -0,0 +1,161 @@
# Ansible vs. Bash-Scripts: Empfehlung
## Aktuelle Situation
### Bash-Scripts (Quick-Start)
-`deployment/scripts/staging-quick-start.sh`
-`deployment/scripts/production-quick-start.sh`
- **Zweck**: Schnelle, interaktive Tests und Verifikationen
### Ansible (Deployment)
-`deployment/ansible/playbooks/setup-staging.yml`
-`deployment/ansible/playbooks/setup-infrastructure.yml`
-`deployment/ansible/playbooks/backup.yml`
- **Zweck**: Strukturierte Deployments, Wartung, Automatisierung
## Vergleich
### Bash-Scripts
**Vorteile:**
-**Einfach**: Keine Dependencies, direkt ausführbar
-**Schnell**: Sofortige Ausführung, kein Setup nötig
-**Interaktiv**: Menü-basiert, benutzerfreundlich
-**Flexibel**: Einfache Anpassungen möglich
-**Debugging**: Einfach zu debuggen, direkte Ausgabe
**Nachteile:**
-**Nicht idempotent**: Mehrfache Ausführung kann Probleme verursachen
-**Wartung**: Schwerer zu warten bei komplexen Logiken
-**Fehlerbehandlung**: Manuelle Fehlerbehandlung nötig
-**Dokumentation**: Code als Dokumentation, weniger strukturiert
-**Wiederverwendbarkeit**: Schwerer in andere Kontexte zu integrieren
### Ansible
**Vorteile:**
-**Idempotent**: Mehrfache Ausführung sicher
-**Strukturiert**: Klare Rollen, Tasks, Variablen
-**Wartbar**: Einfacher zu erweitern und zu warten
-**Fehlerbehandlung**: Integrierte Retry-Logik, bessere Fehlermeldungen
-**Dokumentation**: Selbst-dokumentierend durch Tasks
-**Wiederverwendbar**: Tasks können in verschiedenen Playbooks genutzt werden
-**Konsistent**: Gleiche Tools wie für Deployment
-**Testing**: Ansible-Lint, Syntax-Checks, etc.
**Nachteile:**
-**Setup**: Ansible muss installiert sein
-**Komplexität**: Etwas komplexer für einfache Tasks
-**Interaktivität**: Weniger interaktiv (aber möglich mit `ansible-prompt`)
## Empfehlung: Hybrid-Ansatz
### Für was Bash-Scripts nutzen?
**Gut für:**
-**Schnelle Verifikationen**: Container-Status, Logs anzeigen
-**Interaktive Tests**: Menü-basierte Auswahl
-**Debugging**: Ad-hoc-Tasks während Problemlösung
-**Entwickler-Freundlich**: Keine Ansible-Kenntnisse nötig
**Beispiele:**
- Container-Status prüfen
- Logs anzeigen
- Health-Checks durchführen
- Netzwerk-Verbindungen testen
### Für was Ansible nutzen?
**Gut für:**
-**Deployments**: Strukturierte, wiederholbare Deployments
-**Setup**: Initiales Setup von Stacks
-**Wartung**: Regelmäßige Wartungsaufgaben
-**Backups**: Automatisierte Backup-Prozesse
-**CI/CD-Integration**: In Pipelines integrierbar
**Beispiele:**
- Stack-Deployment
- Konfiguration-Management
- Backup-Automatisierung
- System-Updates
## Langfristige Strategie
### Phase 1: Aktuell (Hybrid)
- **Bash-Scripts**: Für schnelle Verifikationen und interaktive Tests
- **Ansible**: Für Deployments und Wartung
### Phase 2: Erweiterung (Empfohlen)
- **Ansible-Playbooks erweitern**: Mehr Verifikations-Tasks
- **Bash-Scripts behalten**: Für interaktive, ad-hoc-Tasks
### Phase 3: Konsolidierung (Optional)
- **Ansible als primäres Tool**: Alle Tasks als Ansible-Playbooks
- **Bash-Scripts als Wrapper**: Dünne Wrapper um Ansible-Playbooks
## Konkrete Empfehlung
### Kurzfristig (Jetzt)
**Beide behalten**:
- Bash-Scripts für schnelle, interaktive Tests
- Ansible für strukturierte Deployments
### Mittelfristig (3-6 Monate)
**Ansible erweitern**:
- Verifikations-Playbooks erstellen
- Health-Check-Playbooks
- Monitoring-Playbooks
### Langfristig (6+ Monate)
**Ansible als Standard**:
- Alle wiederholbaren Tasks als Ansible-Playbooks
- Bash-Scripts nur für sehr spezifische, einmalige Tasks
## Beispiel: Ansible-Verifikations-Playbook
Statt Bash-Script könnte man auch ein Ansible-Playbook erstellen:
```yaml
# deployment/ansible/playbooks/verify-staging.yml
---
- name: Verify Staging Environment
hosts: production
tasks:
- name: Check PostgreSQL-Staging Stack
community.docker.docker_compose_v2:
project_src: "{{ postgresql_staging_stack_path }}"
state: present
register: postgresql_staging_status
- name: Verify PostgreSQL-Staging Connection
uri:
url: "postgresql://postgres:{{ vault_db_password_staging }}@postgres-staging:5432/michaelschiemer_staging"
method: GET
- name: Check Staging Application Stack
community.docker.docker_compose_v2:
project_src: "{{ staging_stack_path }}"
state: present
- name: Health Check
uri:
url: "https://staging.michaelschiemer.de/health"
method: GET
status_code: [200]
```
**Vorteil**: Idempotent, strukturiert, in CI/CD integrierbar
## Fazit
**Aktuell**: Hybrid-Ansatz ist optimal
- Bash-Scripts für schnelle, interaktive Tests ✅
- Ansible für strukturierte Deployments ✅
**Langfristig**: Ansible ausbauen
- Mehr Verifikations-Playbooks
- Bash-Scripts nur für sehr spezifische Tasks
- Konsistente Tool-Nutzung
**Empfehlung**: Beide behalten, aber Ansible schrittweise erweitern für wiederholbare Tasks.

View File

@@ -0,0 +1,362 @@
# Backup & Rollback Guide
**Stand:** 2025-11-07
**Status:** Vollständige Dokumentation der Backup- und Rollback-Strategie
---
## Übersicht
Dieses Dokument erklärt die Backup- und Rollback-Strategie für das Deployment. Backups werden automatisch erstellt und können für Rollbacks verwendet werden.
**📖 Verwandte Dokumentation:**
- [Deployment Commands](./deployment-commands.md) - Command-Referenz
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Ablauf
---
## Backup-Strategie
### Backup-Playbook
**Datei:** `deployment/ansible/playbooks/backup.yml`
**Zweck:** Erstellt vollständige Backups aller kritischen Daten
**Backup-Ziele:**
- ✅ PostgreSQL Datenbanken (Production + Staging)
- ✅ Application Code (Git Repository)
- ✅ Application Storage (Logs, Cache, etc.)
- ✅ Gitea Data
- ✅ Docker Registry Images (optional)
### Backup ausführen
**Mit Test-Script (Empfohlen):**
```bash
cd /home/michael/dev/michaelschiemer
./deployment/scripts/test-backup.sh
```
**Manuell:**
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/backup.yml \
--vault-password-file secrets/.vault_pass
```
**Mit Optionen:**
```bash
# Nur PostgreSQL Backup
ansible-playbook -i inventory/production.yml \
playbooks/backup.yml \
-e "backup_postgresql=true" \
-e "backup_application_data=false" \
-e "backup_gitea=false" \
--vault-password-file secrets/.vault_pass
# Retention Policy anpassen (Standard: 7 Tage)
ansible-playbook -i inventory/production.yml \
playbooks/backup.yml \
-e "backup_retention_days=14" \
--vault-password-file secrets/.vault_pass
```
### Backup-Struktur
**Backup-Verzeichnis:** `/home/deploy/deployment/backups/`
**Struktur:**
```
backups/
├── backup_2025-11-07_14-30-00/
│ ├── postgresql_michaelschiemer_2025-11-07_14-30-00.sql.gz
│ ├── application_storage_2025-11-07_14-30-00.tar.gz
│ ├── application_logs_2025-11-07_14-30-00.tar.gz
│ ├── application_env_2025-11-07_14-30-00.env
│ ├── gitea_data_2025-11-07_14-30-00.tar.gz
│ └── backup_metadata.txt
└── backup_2025-11-06_14-30-00/
└── ...
```
### Backup-Komponenten
**PostgreSQL Backup:**
- Format: `postgresql_<database>_<date>_<time>.sql.gz`
- Inhalt: Vollständiger Database Dump
- Komprimierung: Gzip
**Application Storage:**
- Format: `application_storage_<date>_<time>.tar.gz`
- Inhalt: `storage/` Verzeichnis
- Komprimierung: Tar + Gzip
**Application Logs:**
- Format: `application_logs_<date>_<time>.tar.gz`
- Inhalt: `storage/logs/` Verzeichnis
- Komprimierung: Tar + Gzip
**Application .env:**
- Format: `application_env_<date>_<time>.env`
- Inhalt: Environment-Variablen
**Gitea Data:**
- Format: `gitea_data_<date>_<time>.tar.gz`
- Inhalt: Gitea Volume
- Komprimierung: Tar + Gzip
### Retention Policy
**Standard:** 7 Tage
**Konfiguration:**
- Backups älter als `backup_retention_days` werden automatisch gelöscht
- Retention kann via `-e backup_retention_days=14` angepasst werden
**Beispiel:**
```bash
# 14 Tage Retention
ansible-playbook -i inventory/production.yml \
playbooks/backup.yml \
-e "backup_retention_days=14" \
--vault-password-file secrets/.vault_pass
```
### Backup-Verifikation
**Automatisch:**
- Playbook prüft ob Backup-Dateien erstellt wurden
- Dateigrößen werden angezeigt
- Fehler wenn keine Backups erstellt wurden
**Manuell auf Server:**
```bash
# Auf Server prüfen
ssh deploy@94.16.110.151
ls -lh ~/deployment/backups/backup_*/
# Backup-Metadaten anzeigen
cat ~/deployment/backups/backup_*/backup_metadata.txt
# Backup-Dateien auflisten
find ~/deployment/backups/backup_* -type f -ls
```
**Backup-Test durchführen:**
```bash
# Test-Backup mit Verifikation
cd /home/michael/dev/michaelschiemer
./deployment/scripts/test-backup.sh
# Danach auf Server verifizieren
ssh deploy@94.16.110.151
ls -lh ~/deployment/backups/backup_*/
cat ~/deployment/backups/backup_*/backup_metadata.txt
```
---
## Rollback-Strategie
### Rollback-Playbook
**Datei:** `deployment/ansible/playbooks/rollback.yml`
**Zweck:** Rollback zu vorheriger Version
**Rollback-Optionen:**
- Image Rollback (Docker Image)
- Code Rollback (Git Repository)
- Database Rollback (PostgreSQL)
### Rollback ausführen
**Zu letzter Version:**
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/rollback.yml \
--vault-password-file secrets/.vault_pass
```
**Zu spezifischer Version:**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/rollback.yml \
-e "rollback_to_version=backup_2025-11-06_14-30-00" \
--vault-password-file secrets/.vault_pass
```
### Rollback-Szenarien
#### 1. Image Rollback
**Zweck:** Rollback zu vorherigem Docker Image
**Prozess:**
1. Vorheriges Image wird identifiziert
2. `docker-compose.production.yml` wird aktualisiert
3. Container werden neu gestartet
**Beispiel:**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/rollback.yml \
-e "rollback_type=image" \
--vault-password-file secrets/.vault_pass
```
#### 2. Code Rollback
**Zweck:** Rollback zu vorherigem Git Commit
**Prozess:**
1. Vorheriger Git Commit wird identifiziert
2. Repository wird auf vorherigen Commit zurückgesetzt
3. Container werden neu gestartet
**Beispiel:**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/rollback.yml \
-e "rollback_type=code" \
--vault-password-file secrets/.vault_pass
```
#### 3. Database Rollback
**Zweck:** Rollback zu vorherigem Database Backup
**Prozess:**
1. Vorheriges Database Backup wird identifiziert
2. Database wird aus Backup wiederhergestellt
3. Verifikation wird durchgeführt
**Wichtig:** Database Rollback sollte nur bei kritischen Problemen verwendet werden.
**Beispiel:**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/rollback.yml \
-e "rollback_type=database" \
-e "rollback_to_version=backup_2025-11-06_14-30-00" \
--vault-password-file secrets/.vault_pass
```
---
## Automatisierung
### Geplante Backups
**Empfohlen:** Tägliche Backups via Cron oder Systemd Timer
**Cron-Beispiel:**
```bash
# Täglich um 2:00 Uhr
0 2 * * * cd /path/to/deployment/ansible && ansible-playbook -i inventory/production.yml playbooks/backup.yml --vault-password-file secrets/.vault_pass
```
**Systemd Timer (Empfohlen):**
- Erstellt Systemd Service und Timer
- Bessere Logging-Integration
- Bessere Fehlerbehandlung
### Backup-Monitoring
**Empfohlen:** Alerts bei Backup-Fehlern
**Methoden:**
- Email-Benachrichtigungen
- Monitoring-Integration (Grafana/Prometheus)
- Log-Analyse
---
## Best Practices
### 1. Regelmäßige Backups
**Empfohlen:** Täglich
**Vorteile:**
- Minimale Datenverluste
- Schneller Rollback möglich
- Compliance-Anforderungen
### 2. Backup-Verifikation
**Empfohlen:** Regelmäßige Restore-Tests
**Vorteile:**
- Sicherstellung dass Backups funktionieren
- Vertrautheit mit Restore-Prozess
- Identifikation von Problemen
### 3. Retention Policy
**Empfohlen:** 7-30 Tage
**Abwägung:**
- Längere Retention = Mehr Speicherplatz
- Kürzere Retention = Weniger Speicherplatz, aber weniger Rollback-Optionen
### 4. Offsite Backups
**Empfohlen:** Wichtige Backups extern speichern
**Methoden:**
- S3-compatible Storage (MinIO)
- SFTP/SCP zu externem Server
- Cloud Storage (optional)
---
## Troubleshooting
### Problem: Backup schlägt fehl
**Ursachen:**
- Container laufen nicht
- Speicherplatz voll
- Berechtigungen fehlen
**Lösung:**
- Prüfe Container Status
- Prüfe verfügbaren Speicherplatz
- Prüfe Berechtigungen
### Problem: Rollback schlägt fehl
**Ursachen:**
- Backup existiert nicht
- Backup ist korrupt
- Container laufen nicht
**Lösung:**
- Prüfe ob Backup existiert
- Prüfe Backup-Integrität
- Prüfe Container Status
### Problem: Database Restore schlägt fehl
**Ursachen:**
- Database läuft nicht
- Backup ist korrupt
- Berechtigungen fehlen
**Lösung:**
- Prüfe Database Status
- Prüfe Backup-Integrität
- Prüfe Database-Berechtigungen
---
## Referenz
- [Deployment Commands](./deployment-commands.md) - Command-Referenz
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Ablauf
- [CI/CD Workflow Guide](./cicd-workflow-guide.md) - CI/CD Workflows

View File

@@ -0,0 +1,347 @@
# CI/CD Workflow Guide
**Stand:** 2025-11-07
**Status:** Vollständige Dokumentation der CI/CD Workflows
---
## Übersicht
Dieses Dokument erklärt die CI/CD Workflows und wie sie funktionieren. Die Workflows verwenden Ansible Playbooks für Deployment, um Idempotenz, bessere Fehlerbehandlung und konsistente Logs zu gewährleisten.
**📖 Verwandte Dokumentation:**
- [Code Deployment Workflow](./code-deployment-workflow.md) - Unterschiede zwischen Rsync und Git
- [Initial Deployment Guide](./initial-deployment-guide.md) - Initial Deployment Anleitung
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Ablauf
- [CI/CD Status](../status/ci-cd-status.md) - Aktueller Status
---
## Workflow-Übersicht
### Automatische Workflows
**`.gitea/workflows/build-image.yml`**
- **Trigger:** Push zu `staging` oder `main` Branch
- **Jobs:**
1. **changes** - Prüft ob Build notwendig ist
2. **test** - Führt Tests aus (PHP, Pest, PHPStan, Code Style)
3. **build** - Baut Docker Image und pusht zur Registry
4. **deploy-staging** - Auto-Deploy zu Staging (nur bei `staging` Branch)
5. **deploy-production** - Auto-Deploy zu Production (nur bei `main` Branch)
### Manuelle Workflows
**`.gitea/workflows/manual-deploy.yml`**
- **Trigger:** Manuell via `workflow_dispatch`
- **Inputs:**
- `environment`: staging oder production
- `image_tag`: Optional, Image Tag zum Deployen
- `branch`: Optional, Branch zum Checkout
- **Jobs:**
1. **determine-image** - Bestimmt Image zum Deployen
2. **deploy-staging** - Deploy zu Staging
3. **deploy-production** - Deploy zu Production
---
## Deployment-Prozess
### Staging Auto-Deploy (build-image.yml)
**Trigger:** Push zu `staging` Branch
**Ablauf:**
1. **Code-Deployment** (`deploy-application-code.yml`)
- Git Repository wird auf Server aktualisiert
- Branch: `staging`
- Ziel: `/home/deploy/michaelschiemer/current`
2. **Composer Dependencies** (`install-composer-dependencies.yml`)
- `composer install --no-dev --optimize-autoloader`
- Im `php` Container ausgeführt
- `queue-worker` und `scheduler` werden neu gestartet
3. **Image-Deployment** (`deploy-image.yml`)
- Docker Image wird zur Registry gepusht
- Image wird auf Server gepullt
- `docker-compose.production.yml` wird aktualisiert
- Container werden neu gestartet
4. **Health-Check**
- Prüft `https://staging.michaelschiemer.de/health`
- Wartet bis zu 10 Versuche (100 Sekunden)
### Production Auto-Deploy (build-image.yml)
**Trigger:** Push zu `main` Branch
**Ablauf:**
1. **Code-Deployment** (`deploy-application-code.yml`)
- Git Repository wird auf Server aktualisiert
- Branch: `main`
- Ziel: `/home/deploy/michaelschiemer/current`
2. **Composer Dependencies** (`install-composer-dependencies.yml`)
- Gleicher Prozess wie Staging
3. **Image-Deployment** (`deploy-image.yml`)
- Gleicher Prozess wie Staging
- Environment: `production`
4. **Health-Check**
- Prüft `https://michaelschiemer.de/health`
- Wartet bis zu 10 Versuche (100 Sekunden)
---
## Ansible Playbooks in Workflows
### deploy-application-code.yml
**Zweck:** Code-Deployment via Git
**Parameter:**
- `deployment_environment`: `staging` oder `production`
- `deployment_hosts`: `production` (Inventory Group)
- `git_branch`: Branch zum Deployen (`staging` oder `main`)
**Was passiert:**
- Git Repository wird geklont (falls nicht vorhanden)
- Repository wird aktualisiert (`git pull`)
- Executable Permissions werden gesetzt
- Verifikation: Prüft ob `worker.php`, `console.php`, `composer.json` existieren
### install-composer-dependencies.yml
**Zweck:** Composer Dependencies Installation
**Parameter:**
- `deployment_environment`: `staging` oder `production`
**Was passiert:**
- `composer install --no-dev --optimize-autoloader` im PHP Container
- Verifikation: Prüft ob `vendor/autoload.php` existiert
- Restart: `queue-worker` und `scheduler` (nur Production)
### deploy-image.yml
**Zweck:** Docker Image Deployment
**Parameter:**
- `deployment_environment`: `staging` oder `production`
- `image_tag`: Image Tag (z.B. `latest`, `git-abc1234`)
- `docker_registry`: Registry URL
- `docker_registry_username`: Registry Username
- `docker_registry_password`: Registry Password
**Was passiert:**
- Docker Registry Login
- Image Pull
- `docker-compose.production.yml` wird aktualisiert
- Container werden neu gestartet
- Container Status wird angezeigt
---
## Secrets Konfiguration
### Erforderliche Secrets
**REGISTRY_USER**
- Docker Registry Benutzername
- Standard: `admin`
**REGISTRY_PASSWORD**
- Docker Registry Passwort
- Zu finden in: `deployment/stacks/registry/auth/htpasswd`
**SSH_PRIVATE_KEY**
- SSH Private Key für Production-Server-Zugriff
- Kompletter Inhalt inkl. `-----BEGIN OPENSSH PRIVATE KEY-----`
**ANSIBLE_VAULT_PASSWORD**
- Ansible Vault Password für verschlüsselte Secrets
- Optional: Falls nicht gesetzt, wird leeres Password File verwendet
**GITEA_TOKEN** (optional)
- Gitea Personal Access Token
- Für automatische Issue-Erstellung bei Security-Scans
### Secrets konfigurieren
```bash
# In Gitea UI:
https://git.michaelschiemer.de/michael/michaelschiemer/settings/secrets/actions
# Secrets hinzufügen:
- REGISTRY_USER
- REGISTRY_PASSWORD
- SSH_PRIVATE_KEY
- ANSIBLE_VAULT_PASSWORD
```
---
## Workflow-Beispiele
### Staging Deployment (Automatisch)
**Trigger:** Push zu `staging` Branch
```bash
git checkout staging
git add .
git commit -m "feat: Add new feature"
git push origin staging
```
**Was passiert automatisch:**
1. Tests werden ausgeführt
2. Docker Image wird gebaut
3. Image wird zur Registry gepusht
4. Code wird via Git deployt
5. Composer Dependencies werden installiert
6. Image wird deployt
7. Health-Check wird durchgeführt
### Production Deployment (Automatisch)
**Trigger:** Push zu `main` Branch
```bash
git checkout main
git merge staging
git push origin main
```
**Was passiert automatisch:**
- Gleicher Prozess wie Staging, aber auf Production
### Manuelles Deployment
**Via Gitea UI:**
1. Gehe zu: `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
2. Wähle: "Manual Deployment"
3. Klicke: "Run workflow"
4. Wähle:
- Environment: `production` oder `staging`
- Image Tag: Optional (z.B. `git-abc1234`)
- Branch: Optional (Standard: `main` für Production, `staging` für Staging)
---
## Troubleshooting
### Problem: Code-Deployment schlägt fehl
**Ursachen:**
- Git Repository existiert nicht auf Server
- Git Credentials fehlen
- Branch existiert nicht
**Lösung:**
- Prüfe `deploy-application-code.yml` Logs
- Prüfe ob Git Repository auf Server existiert
- Prüfe Branch-Name
### Problem: Composer Dependencies Installation schlägt fehl
**Ursachen:**
- `composer.json` fehlt
- PHP Container läuft nicht
- Netzwerk-Probleme
**Lösung:**
- Prüfe ob `composer.json` existiert
- Prüfe PHP Container Status
- Prüfe `install-composer-dependencies.yml` Logs
### Problem: Image-Deployment schlägt fehl
**Ursachen:**
- Registry Login fehlgeschlagen
- Image existiert nicht in Registry
- Docker Compose Dateien fehlen
**Lösung:**
- Prüfe Registry Credentials
- Prüfe ob Image in Registry existiert
- Prüfe `deploy-image.yml` Logs
### Problem: Health-Check schlägt fehl
**Ursachen:**
- Container starten nicht
- Application hat Fehler
- Health-Check Endpoint nicht erreichbar
**Lösung:**
- Prüfe Container Status: `docker compose ps`
- Prüfe Container Logs: `docker compose logs`
- Prüfe Health-Check Endpoint manuell: `curl https://michaelschiemer.de/health`
---
## Best Practices
### 1. Staging First
**Empfohlen:** Immer zuerst auf Staging deployen, dann auf Production
```bash
# 1. Staging
git push origin staging # → Auto-Deploy zu Staging
# 2. Testen auf Staging
# ... Tests durchführen ...
# 3. Production
git checkout main
git merge staging
git push origin main # → Auto-Deploy zu Production
```
### 2. Image Tags
**Empfohlen:** Spezifische Image Tags verwenden statt `latest`
**Vorteile:**
- Rollback möglich
- Nachvollziehbarkeit
- Reproduzierbarkeit
**Beispiel:**
```bash
# Manuelles Deployment mit spezifischem Tag
# Image Tag: git-abc1234
```
### 3. Vault Password
**Empfohlen:** `ANSIBLE_VAULT_PASSWORD` als Secret konfigurieren
**Vorteile:**
- Automatisiertes Deployment
- Keine manuelle Eingabe nötig
- Sicherer als manuelle Eingabe
### 4. Monitoring
**Empfohlen:** Pipeline-Status überwachen
**Methoden:**
- Gitea Actions UI
- Health-Check Endpoints
- Container Status
---
## Referenz
- [Code Deployment Workflow](./code-deployment-workflow.md) - Code-Deployment-Methoden
- [Initial Deployment Guide](./initial-deployment-guide.md) - Initial Deployment
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Ablauf
- [CI/CD Status](../status/ci-cd-status.md) - Aktueller Status
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Probleme und Lösungen

View File

@@ -284,7 +284,7 @@ https://git.michaelschiemer.de/michael/michaelschiemer/actions
ssh deploy@94.16.110.151
# Container-Status prüfen
cd ~/deployment/stacks/application
cd ~/deployment/stacks/production
docker compose ps
# Logs ansehen
@@ -489,7 +489,7 @@ git push origin main
ssh deploy@94.16.110.151
# Logs prüfen
cd ~/deployment/stacks/application
cd ~/deployment/stacks/production
docker compose logs app
# Manuell rollback
@@ -535,7 +535,7 @@ git push origin feature/my-feature
# → https://git.michaelschiemer.de/michael/michaelschiemer/actions
# Application-Status prüfen
ssh deploy@94.16.110.151 "cd ~/deployment/stacks/application && docker compose ps"
ssh deploy@94.16.110.151 "cd ~/deployment/stacks/production && docker compose ps"
```
### Deployment-Zeit

View File

@@ -0,0 +1,339 @@
# Code Deployment Workflow
**Stand:** 2025-11-07
**Status:** Vollständige Dokumentation der Code-Deployment-Methoden
---
## Übersicht
Dieses Dokument erklärt die beiden verfügbaren Methoden für Code-Deployment:
1. **Rsync-basiert** - Für Initial Deployment
2. **Git-basiert** - Für CI/CD und zukünftige Deployments
**📖 Verwandte Dokumentation:**
- [Initial Deployment Guide](./initial-deployment-guide.md) - Schritt-für-Schritt Initial Deployment
- [Deployment Commands](./deployment-commands.md) - Command-Referenz
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Ablauf
---
## Deployment-Methoden im Vergleich
### Methode 1: Rsync-basiert (`sync-application-code.yml`)
**Verwendung:** Initial Deployment (einmalig)
**Vorteile:**
- ✅ Funktioniert ohne Git Repository auf Server
- ✅ Schnell für einmaliges Setup
- ✅ Exakte Kontrolle über synchronisierte Dateien
- ✅ Funktioniert auch wenn Git nicht verfügbar ist
**Nachteile:**
- ❌ Erfordert lokales Repository
- ❌ Nicht für CI/CD geeignet
- ❌ Manueller Prozess
**Playbook:** `deployment/ansible/playbooks/sync-application-code.yml`
**Was wird synchronisiert:**
- Alle PHP-Dateien
- Konfigurationsdateien
- Assets (wenn nicht excluded)
**Was wird NICHT synchronisiert:**
- `vendor` (wird im Container installiert)
- `node_modules`
- `.env` Dateien
- `deployment/`, `docker/`, `docs/`, `tests/`
---
### Methode 2: Git-basiert (`deploy-application-code.yml`)
**Verwendung:** CI/CD und zukünftige Deployments
**Vorteile:**
- ✅ Automatisierbar via CI/CD
- ✅ Version Control Integration
- ✅ Git Commit History verfügbar
- ✅ Branch-basierte Deployments möglich
- ✅ Rollback einfach (Git Checkout)
**Nachteile:**
- ❌ Erfordert Git Repository auf Server
- ❌ Erfordert Git Credentials (Token/SSH Key)
**Playbook:** `deployment/ansible/playbooks/deploy-application-code.yml`
**Was passiert:**
- Git Repository wird geklont (falls nicht vorhanden)
- Repository wird aktualisiert (`git pull`)
- Branch kann spezifiziert werden
- Executable Permissions werden gesetzt
---
## Workflow-Diagramme
### Initial Deployment (Rsync)
```
Local Repository
rsync (via Ansible)
Server: /home/deploy/michaelschiemer/current
Docker Volume Mount
Container: /var/www/html
```
### Normal Deployment (Git)
```
Git Repository (Gitea)
Git Clone/Pull (via Ansible)
Server: /home/deploy/michaelschiemer/current
Docker Volume Mount
Container: /var/www/html
```
### CI/CD Deployment (Git)
```
Developer → git push
Gitea Actions Trigger
Build Docker Image
Push to Registry
Ansible: deploy-application-code.yml
Git Pull auf Server
Docker Compose Restart
```
---
## Wann welche Methode verwenden?
### Initial Deployment → Rsync
**Verwendung:**
- ✅ Erstes Setup des Servers
- ✅ Server hat noch kein Git Repository
- ✅ Lokales Repository ist verfügbar
- ✅ Manuelles Deployment gewünscht
**Beispiel:**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/sync-application-code.yml \
--vault-password-file secrets/.vault_pass
```
### Normal Deployment → Git
**Verwendung:**
- ✅ CI/CD Pipeline
- ✅ Regelmäßige Deployments
- ✅ Branch-basierte Deployments (staging, production)
- ✅ Automatisierung gewünscht
**Beispiel:**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/deploy-application-code.yml \
-e "git_branch=main" \
--vault-password-file secrets/.vault_pass
```
---
## Detaillierte Workflows
### Initial Deployment Workflow (Rsync)
**Schritt 1: Code synchronisieren**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/sync-application-code.yml \
--vault-password-file secrets/.vault_pass
```
**Schritt 2: Composer Dependencies installieren**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/install-composer-dependencies.yml \
--vault-password-file secrets/.vault_pass
```
**Schritt 3: Application Stack deployen**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml \
--tags application \
--vault-password-file secrets/.vault_pass
```
**Siehe auch:** [Initial Deployment Guide](./initial-deployment-guide.md)
---
### Normal Deployment Workflow (Git)
**Schritt 1: Code deployen**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/deploy-application-code.yml \
-e "git_branch=main" \
--vault-password-file secrets/.vault_pass
```
**Schritt 2: Composer Dependencies aktualisieren (falls nötig)**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/install-composer-dependencies.yml \
--vault-password-file secrets/.vault_pass
```
**Schritt 3: Container neu starten (falls nötig)**
```bash
# Auf Server
cd ~/deployment/stacks/production
docker compose -f docker-compose.base.yml -f docker-compose.production.yml restart
```
---
### CI/CD Deployment Workflow (Git)
**Automatisch via Gitea Actions:**
1. **Developer pusht Code:**
```bash
git push origin main
```
2. **Gitea Actions Pipeline:**
- Tests ausführen
- Docker Image bauen
- Image zur Registry pushen
- Ansible Playbook ausführen
3. **Ansible Playbook (`deploy-application-code.yml`):**
- Git Repository auf Server aktualisieren
- Composer Dependencies installieren (falls `composer.json` geändert)
- Container neu starten
**Siehe auch:** [Application Stack Deployment](../reference/application-stack.md)
---
## Best Practices
### Code-Synchronisation
1. **Immer `vendor` ausschließen**
- Dependencies werden im Container installiert
- Verhindert Platform-spezifische Probleme
2. **`.env` niemals synchronisieren**
- Environment-spezifische Konfiguration
- Wird von Ansible generiert
3. **Executable Permissions setzen**
- `worker.php` und `console.php` müssen ausführbar sein
- Playbooks setzen automatisch `0755`
### Git-Deployment
1. **Branch-spezifische Deployments**
```bash
# Staging
-e "git_branch=staging"
# Production
-e "git_branch=main"
```
2. **Git Credentials**
- SSH Keys für private Repositories
- Git Tokens für HTTPS
- Credentials werden via Ansible Vault verwaltet
3. **Rollback**
```bash
# Auf Server
cd /home/deploy/michaelschiemer/current
git checkout <previous-commit-hash>
docker compose restart
```
---
## Troubleshooting
### Problem: Rsync synchronisiert nicht alle Dateien
**Lösung:** Excludes in `sync-application-code.yml` prüfen
### Problem: Git Pull schlägt fehl
**Ursachen:**
- Git Credentials fehlen
- Repository existiert nicht
- Branch existiert nicht
**Lösung:** Siehe [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)
### Problem: Code-Änderungen werden nicht erkannt
**Lösung:** Container neu starten
```bash
docker compose -f docker-compose.base.yml -f docker-compose.production.yml restart
```
---
## Migration: Rsync → Git
Nach Initial Deployment kann auf Git-Deployment umgestellt werden:
**Schritt 1: Git Repository auf Server initialisieren**
```bash
# Auf Server
cd /home/deploy/michaelschiemer/current
git init
git remote add origin https://git.michaelschiemer.de/michael/michaelschiemer.git
git fetch
git checkout main
```
**Schritt 2: Zukünftige Deployments via Git**
```bash
ansible-playbook -i inventory/production.yml \
playbooks/deploy-application-code.yml \
-e "git_branch=main" \
--vault-password-file secrets/.vault_pass
```
---
## Referenz
- [Initial Deployment Guide](./initial-deployment-guide.md) - Initial Deployment Anleitung
- [Deployment Commands](./deployment-commands.md) - Command-Referenz
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Ablauf
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Probleme und Lösungen

View File

@@ -1,30 +1,172 @@
# Deployment Commands - Quick Reference
Alle Deployment-Operationen werden über **Ansible Playbooks** durchgeführt.
## 🚀 Automatisches Deployment (Empfohlen)
### Standard-Workflow: Staging → Production
**Empfohlener Workflow für sichere Deployments:**
1. **Push auf `staging` Branch** (Standard für Entwicklung)
```bash
git add .
git commit -m "feat: Add new feature"
git push origin staging # → Automatisches Deployment zu Staging
```
2. **Testen auf Staging**
- Staging URL: `https://staging.michaelschiemer.de`
- Tests durchführen und verifizieren
3. **Merge nach `main`** (nur nach erfolgreichem Test)
```bash
git checkout main
git merge staging
git push origin main # → Automatisches Deployment zu Production
```
**Was passiert automatisch:**
**Bei Push auf `staging` Branch:**
- ✅ Tests werden ausgeführt
- ✅ Docker Image wird gebaut
- ✅ Image wird zur Registry gepusht
- ✅ Deployment auf Staging Server via SSH/SCP
- ✅ Staging Stack wird aktualisiert
**Bei Push auf `main` Branch:**
- ✅ Tests werden ausgeführt
- ✅ Docker Image wird gebaut
- ✅ Image wird zur Registry gepusht
- ✅ Deployment auf Production Server via SSH/SCP
- ✅ Production Stack wird aktualisiert
**Pipeline Status:** `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
**Wichtig:**
- ⚠️ **Niemals direkt auf `main` pushen** - immer erst auf `staging` testen
-**Staging ist der Standard-Branch** für alle Entwicklungsarbeit
-**Production-Deployment** erfolgt nur nach erfolgreichem Test auf Staging
---
## 🚀 Häufig verwendete Commands
## 🔧 Initial Deployment (Einmalig)
### Code deployen (Image-basiert)
### Schritt 1: Code synchronisieren (Rsync)
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/deploy-update.yml \
-e "image_tag=abc1234-1696234567" \
-e "git_commit_sha=$(git rev-parse HEAD)"
playbooks/sync-application-code.yml \
--vault-password-file secrets/.vault_pass
```
### Code synchen (Git-basiert)
**Was passiert:**
- Code wird vom lokalen Repository zum Server synchronisiert
- Ziel: `/home/deploy/michaelschiemer/current`
- Excludes: `vendor`, `node_modules`, `.env`, `deployment`, `docker`, `docs`, `tests`
### Schritt 2: Composer Dependencies installieren
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/sync-code.yml \
-e "git_branch=main"
playbooks/install-composer-dependencies.yml \
--vault-password-file secrets/.vault_pass
```
**Was passiert:**
- `composer install --no-dev --optimize-autoloader` im PHP Container
- `queue-worker` und `scheduler` werden neu gestartet
### Schritt 3: Application Stack deployen
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml \
--tags application \
--vault-password-file secrets/.vault_pass
```
**Siehe auch:** [Initial Deployment Guide](./initial-deployment-guide.md)
---
## 🔧 Manuelle Deployment-Operationen
### Code deployen (Git-basiert)
**Für zukünftige Deployments (nach Initial Setup):**
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/deploy-application-code.yml \
-e "git_branch=main" \
--vault-password-file secrets/.vault_pass
```
**Was passiert:**
- Git Repository wird auf Server aktualisiert (`git pull`)
- Branch kann spezifiziert werden
- Executable Permissions werden gesetzt
**Siehe auch:** [Code Deployment Workflow](./code-deployment-workflow.md)
### Code deployen (Manuell via SSH)
Falls ein manuelles Deployment nötig ist:
**Staging:**
```bash
# Auf Staging Server
ssh deploy@94.16.110.151
# 1. PostgreSQL Staging Stack (falls noch nicht laufend)
cd ~/deployment/stacks/postgresql-staging
docker compose up -d
# 2. Staging Application Stack
cd ~/deployment/stacks/staging
# Docker Registry Login
echo "$REGISTRY_PASSWORD" | docker login registry.michaelschiemer.de \
-u "$REGISTRY_USER" --password-stdin
# Image pullen
docker pull registry.michaelschiemer.de/framework:git-abc1234
# Stack aktualisieren
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml up -d
```
**Hinweis**: Staging verwendet eine separate PostgreSQL-Datenbank (`postgres-staging`) im `postgresql-staging` Stack.
**Production:**
```bash
# Auf Production Server
ssh deploy@94.16.110.151
# 1. PostgreSQL Production Stack (falls noch nicht laufend)
cd ~/deployment/stacks/postgresql-production
docker compose up -d
# 2. Production Application Stack
cd ~/deployment/stacks/production
# Docker Registry Login
echo "$REGISTRY_PASSWORD" | docker login registry.michaelschiemer.de \
-u "$REGISTRY_USER" --password-stdin
# Image pullen
docker pull registry.michaelschiemer.de/framework:git-abc1234
# Stack aktualisieren
docker compose -f docker-compose.base.yml -f docker-compose.production.yml up -d
```
**Hinweis**: Production verwendet eine separate PostgreSQL-Datenbank (`postgres-production`) im `postgresql-production` Stack.
### Rollback zu vorheriger Version
```bash
@@ -41,6 +183,56 @@ ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml
```
### Quick-Start Scripts
Für schnelle Tests und Verifikationen:
**Staging**:
```bash
cd ~/deployment
./scripts/staging-quick-start.sh
```
**Production**:
```bash
cd ~/deployment
./scripts/production-quick-start.sh
```
Die Scripts bieten ein interaktives Menü für:
- PostgreSQL-Stacks starten
- Networks verifizieren
- Container-Status prüfen
- Datenbank-Verbindungen testen
- Health-Checks durchführen
- Logs anzeigen
Siehe auch: `deployment/scripts/README.md`
### Verifikation mit Ansible (Empfohlen für CI/CD)
**Staging**:
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/verify-staging.yml
```
**Production**:
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/verify-production.yml
```
Die Ansible-Playbooks bieten:
- Idempotente Verifikationen
- Strukturierte Ausgabe
- CI/CD-Integration möglich
- Automatische Fehlerbehandlung
**Vergleich Bash vs. Ansible**: Siehe `deployment/docs/guides/ansible-vs-bash-scripts.md`
### System Maintenance (regelmäßig)
```bash
@@ -51,23 +243,18 @@ ansible-playbook -i inventory/production.yml \
---
## 📋 Alle verfügbaren Playbooks
### Deployment & Updates
- **`playbooks/deploy-update.yml`** - Deployt neues Docker Image
- **`playbooks/sync-code.yml`** - Synchronisiert Code aus Git Repository
- **`playbooks/rollback.yml`** - Rollback zu vorheriger Version
## 📋 Verfügbare Ansible Playbooks
### Infrastructure Setup
- **`playbooks/setup-infrastructure.yml`** - Deployed alle Stacks (Traefik, PostgreSQL, Registry, Gitea, Monitoring, Application)
- **`playbooks/setup-infrastructure.yml`** - Deployed alle Stacks (Traefik, PostgreSQL, Registry, Gitea, Monitoring, Production)
- **`playbooks/setup-production-secrets.yml`** - Deployed Secrets zu Production
- **`playbooks/setup-ssl-certificates.yml`** - SSL Certificate Setup
- **`playbooks/sync-stacks.yml`** - Synchronisiert Stack-Konfigurationen
### Troubleshooting & Maintenance
- **`playbooks/rollback.yml`** - Rollback zu vorheriger Version
- **`playbooks/troubleshoot.yml`** - Unified Troubleshooting Playbook mit Tags
```bash
# Nur Diagnose

View File

@@ -0,0 +1,94 @@
# Health Checks - Dokumentation
## Verfügbare Health-Check-Endpoints
### Basis Health-Check
- **URL**: `/health`
- **Methode**: GET
- **Zweck**: Einfacher Health-Check für Load Balancer und Monitoring
- **Response**: HTTP 200 wenn gesund
### Erweiterte Health-Checks
#### 1. Vollständiger System-Status
- **URL**: `/admin/health/api/status`
- **Methode**: GET
- **Zweck**: Vollständiger Health-Report mit allen Checks
- **Response**: JSON mit allen Health-Check-Ergebnissen
#### 2. Health-Summary
- **URL**: `/admin/health/api/summary`
- **Methode**: GET
- **Zweck**: Zusammenfassung des System-Status
- **Response**: JSON mit Overall-Status und Quick-Stats
#### 3. Einzelner Health-Check
- **URL**: `/admin/health/api/check/{name}`
- **Methode**: GET
- **Zweck**: Spezifischen Health-Check ausführen
- **Response**: JSON mit Check-Ergebnis
#### 4. Health-Checks nach Kategorie
- **URL**: `/admin/health/api/category/{category}`
- **Methode**: GET
- **Zweck**: Alle Checks einer Kategorie ausführen
- **Response**: JSON mit Category-Report
## Verfügbare Health-Checks
Das Framework unterstützt verschiedene Health-Checks:
- **Database**: PostgreSQL Verbindung und Query-Test
- **Redis**: Cache/Session/Queue Backend Verbindung
- **Queue**: Queue Worker Status
- **Logging**: Log-System Status
- **Discovery**: Service Discovery Status
## Verwendung in CI/CD
Der Workflow führt automatisch Health-Checks nach Deployment durch:
1. **Basic Health Check**: `/health` Endpoint
2. **Extended Health Check**: `/admin/health/api/summary` (falls verfügbar)
Bei fehlgeschlagenem Health-Check schlägt das Deployment fehl.
## Automatischer Rollback
**Geplant**: Automatischer Rollback bei fehlgeschlagenem Health-Check ist noch nicht implementiert.
**Aktuell**: Bei fehlgeschlagenem Health-Check schlägt das Deployment fehl, aber es erfolgt kein automatischer Rollback.
**Zukünftig**:
- Automatischer Rollback bei fehlgeschlagenem Health-Check
- Rollback-Notification (Email/Slack)
- Health-Check-Dashboard in Grafana
## Monitoring Integration
Health-Checks können in Prometheus/Grafana integriert werden:
```yaml
# Prometheus Scrape Config
- job_name: 'application-health'
metrics_path: '/admin/health/api/status'
static_configs:
- targets: ['app:80']
```
## Manuelle Health-Checks
```bash
# Basic Health Check
curl https://michaelschiemer.de/health
# Extended Health Summary
curl https://michaelschiemer.de/admin/health/api/summary
# Specific Check
curl https://michaelschiemer.de/admin/health/api/check/database
# All Checks
curl https://michaelschiemer.de/admin/health/api/status
```

View File

@@ -0,0 +1,238 @@
# Initial Deployment Guide
**Stand:** 2025-11-07
**Status:** Vollständige Anleitung für erstes Deployment
---
## Übersicht
Dieser Guide führt durch das komplette Initial Deployment des Application Stacks. Dieser Prozess wird **einmalig** beim ersten Setup durchgeführt. Für spätere Deployments siehe [Code Deployment Workflow](./code-deployment-workflow.md).
**📖 Verwandte Dokumentation:**
- [Code Deployment Workflow](./code-deployment-workflow.md) - Unterschiede zwischen Initial und normalem Deployment
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Häufige Probleme und Lösungen
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Deployment-Ablauf
---
## Voraussetzungen
Bevor das Initial Deployment startet, müssen folgende Voraussetzungen erfüllt sein:
### 1. Infrastructure Stacks deployed
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml \
--vault-password-file secrets/.vault_pass \
--skip-tags application
```
**Wichtig:** `--skip-tags application` überspringt den Application Stack, da dieser separat deployed wird.
### 2. Docker Image gebaut und gepusht
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/build-initial-image.yml \
--vault-password-file secrets/.vault_pass
```
**Was passiert:**
- `docker/entrypoint.sh` wird auf LF Line Endings konvertiert (CRLF → LF)
- Docker Image wird gebaut (`Dockerfile.production`)
- Image wird zur Registry gepusht (`localhost:5000/framework:latest`)
### 3. Secrets konfiguriert
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/setup-production-secrets.yml \
--vault-password-file secrets/.vault_pass
```
**Erforderliche Secrets im Vault:**
- `vault_db_user_password` - PostgreSQL Passwort
- `vault_redis_password` - Redis Passwort
- `vault_app_key` - Application Encryption Key
- `vault_vault_encryption_key` - Vault Encryption Key
---
## Initial Deployment Workflow
### Schritt 1: Application Code synchronisieren
**Methode:** Rsync-basiertes Sync vom lokalen Repository zum Server
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/sync-application-code.yml \
--vault-password-file secrets/.vault_pass
```
**Was passiert:**
- Zielverzeichnis wird erstellt: `/home/deploy/michaelschiemer/current`
- Alte Dateien werden gelöscht (`.git` wird erhalten falls vorhanden)
- Code wird via `rsync` synchronisiert
- Excludes: `vendor`, `node_modules`, `.env`, `deployment`, `docker`, `docs`, `tests`
- Executable Permissions werden auf `worker.php` und `console.php` gesetzt
- Verifikation: Prüft ob `worker.php`, `console.php`, `composer.json` existieren
**Wichtig:** `vendor` wird **nicht** synchronisiert, da Dependencies im Container installiert werden.
### Schritt 2: Composer Dependencies installieren
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/install-composer-dependencies.yml \
--vault-password-file secrets/.vault_pass
```
**Was passiert:**
- `composer install --no-dev --optimize-autoloader` wird im `php` Container ausgeführt
- `vendor/autoload.php` wird erstellt
- `queue-worker` und `scheduler` werden neu gestartet (um `vendor` zu erkennen)
**Voraussetzung:** `php` Container muss bereits laufen (wird durch `setup-infrastructure.yml` gestartet).
### Schritt 3: Application Stack deployen
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml \
--vault-password-file secrets/.vault_pass \
--tags application
```
**Was passiert:**
- Docker Compose Stack wird deployed
- Secrets werden erstellt
- `.env` Datei wird generiert
- Container werden gestartet: `php`, `web`, `queue-worker`, `scheduler`
- Health Checks werden durchgeführt
**Container-Konfiguration:**
- `php`: Läuft PHP-FPM und Nginx (via `entrypoint.sh`)
- `web`: Nginx Reverse Proxy
- `queue-worker`: PHP CLI Worker (ohne entrypoint, direkter `php worker.php` Aufruf)
- `scheduler`: PHP CLI Scheduler (ohne entrypoint, direkter `php console.php scheduler:run` Aufruf)
---
## Verifikation
### Container Status prüfen
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/check-final-status.yml \
--vault-password-file secrets/.vault_pass
```
**Erwartetes Ergebnis:**
```
NAME STATUS
production-php-1 Up X minutes (healthy)
production-web-1 Up X minutes (healthy)
production-queue-worker-1 Up X minutes
scheduler Up X minutes
```
### Manuelle Verifikation
```bash
# SSH zum Server
ssh deploy@94.16.110.151
# Container Status
cd ~/deployment/stacks/production
docker compose -f docker-compose.base.yml -f docker-compose.production.yml ps
# Logs prüfen
docker compose -f docker-compose.base.yml -f docker-compose.production.yml logs web
docker compose -f docker-compose.base.yml -f docker-compose.production.yml logs queue-worker
docker compose -f docker-compose.base.yml -f docker-compose.production.yml logs scheduler
# Health Check
curl -k https://localhost/health
```
---
## Häufige Probleme
### Problem: Container starten nicht / sind unhealthy
**Lösung:** Siehe [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)
**Häufige Ursachen:**
- Missing Secret Files → `setup-production-secrets.yml` ausführen
- Missing Application Code → `sync-application-code.yml` ausführen
- Missing `vendor/autoload.php``install-composer-dependencies.yml` ausführen
- PHP-FPM Permission Errors → `fix-web-container.yml` ausführen
- Environment Variables fehlen → `recreate-containers-with-env.yml` ausführen
### Problem: Entrypoint Script "no such file or directory"
**Ursache:** CRLF Line Endings im `docker/entrypoint.sh`
**Lösung:**
- `.gitattributes` sollte `*.sh text eol=lf` enthalten
- `build-initial-image.yml` konvertiert automatisch zu LF
### Problem: `worker.php` oder `console.php` fehlen
**Ursache:** Code wurde nicht synchronisiert
**Lösung:** `sync-application-code.yml` erneut ausführen
---
## Unterschiede: Initial vs. Normal Deployment
### Initial Deployment (dieser Guide)
- **Code-Sync:** Rsync vom lokalen Repository
- **Verwendung:** Einmalig beim ersten Setup
- **Playbook:** `sync-application-code.yml`
### Normal Deployment (CI/CD)
- **Code-Sync:** Git Clone/Pull auf dem Server
- **Verwendung:** Regelmäßige Deployments via CI/CD
- **Playbook:** `deploy-application-code.yml`
**Siehe auch:** [Code Deployment Workflow](./code-deployment-workflow.md)
---
## Nächste Schritte
Nach erfolgreichem Initial Deployment:
1. **CI/CD Pipeline konfigurieren**
- Gitea Actions Workflow einrichten
- `deploy-application-code.yml` für zukünftige Deployments verwenden
2. **Monitoring einrichten**
- Health Checks verifizieren
- Logs überwachen
- Alerts konfigurieren
3. **Backup-Strategie**
- Database Backups einrichten
- Application Data Backups konfigurieren
---
## Referenz
- [Application Stack Deployment](../reference/application-stack.md) - Detaillierter Ablauf
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Probleme und Lösungen
- [Code Deployment Workflow](./code-deployment-workflow.md) - Normal Deployment Workflow
- [Deployment Commands](./deployment-commands.md) - Command-Referenz

View File

@@ -0,0 +1,247 @@
# Manuelle Server-Tests - Anleitung
## Voraussetzungen
- SSH-Zugriff auf Production-Server: `ssh production`
- Docker und Docker Compose installiert
- Zugriff auf `~/deployment` Verzeichnis
## Test-Phasen
### Phase 1: PostgreSQL-Stacks prüfen
#### 1.1 PostgreSQL-Production Stack
```bash
# Auf Production-Server
ssh production
# Zum Stack-Verzeichnis wechseln
cd ~/deployment/stacks/postgresql-production
# .env-Datei prüfen/erstellen
cat .env
# Sollte enthalten:
# POSTGRES_DB=michaelschiemer
# POSTGRES_USER=postgres
# POSTGRES_PASSWORD=<password>
# Stack starten
docker compose up -d
# Status prüfen
docker compose ps
# Health-Check
docker exec postgres-production pg_isready -U postgres -d michaelschiemer
# Erwartete Ausgabe: postgres-production:5432 - accepting connections
```
#### 1.2 PostgreSQL-Staging Stack
```bash
# Auf Production-Server
cd ~/deployment/stacks/postgresql-staging
# .env-Datei prüfen/erstellen
cat .env
# Sollte enthalten:
# POSTGRES_DB=michaelschiemer_staging
# POSTGRES_USER=postgres
# POSTGRES_PASSWORD=<password>
# Stack starten
docker compose up -d
# Status prüfen
docker compose ps
# Health-Check
docker exec postgres-staging pg_isready -U postgres -d michaelschiemer_staging
# Erwartete Ausgabe: postgres-staging:5432 - accepting connections
```
### Phase 2: Networks verifizieren
```bash
# Auf Production-Server
docker network ls | grep -E "(traefik-public|staging-internal|postgres-production-internal|postgres-staging-internal|app-internal)"
# Erwartete Ausgabe (alle sollten existieren):
# traefik-public
# staging-internal
# postgres-production-internal
# postgres-staging-internal
# app-internal
```
**Falls Networks fehlen**: Sie werden beim Stack-Start automatisch erstellt.
### Phase 3: Staging-Application-Stack prüfen
```bash
# Auf Production-Server
cd ~/deployment/stacks/staging
# Docker Compose-Dateien prüfen
ls -la docker-compose*.yml
# Stack-Status prüfen
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml ps
# Oder falls im Root-Verzeichnis:
cd ~/deployment
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml ps
```
### Phase 4: Datenbank-Verbindungen testen
#### 4.1 Staging-Datenbank-Verbindung
```bash
# Auf Production-Server
docker exec staging-app php -r "
\$dsn = 'pgsql:host=postgres-staging;port=5432;dbname=michaelschiemer_staging';
\$pass = trim(file_get_contents('/var/www/html/storage/secrets/db_user_password'));
\$pdo = new PDO(\$dsn, 'postgres', \$pass);
echo 'Connection successful: ' . \$pdo->query('SELECT version()')->fetchColumn();
"
```
**Erwartete Ausgabe**: `Connection successful: PostgreSQL 16.x...`
#### 4.2 Production-Datenbank-Verbindung
```bash
# Auf Production-Server
docker exec php php -r "
\$dsn = 'pgsql:host=postgres-production;port=5432;dbname=michaelschiemer';
\$pass = trim(file_get_contents('/var/www/html/storage/secrets/db_user_password'));
\$pdo = new PDO(\$dsn, 'postgres', \$pass);
echo 'Connection successful: ' . \$pdo->query('SELECT version()')->fetchColumn();
"
```
**Erwartete Ausgabe**: `Connection successful: PostgreSQL 16.x...`
### Phase 5: Health-Checks
#### 5.1 Basic Health Check
```bash
# Staging
curl -f -k https://staging.michaelschiemer.de/health
# Production
curl -f -k https://michaelschiemer.de/health
```
**Erwartete Ausgabe**: HTTP 200 OK
#### 5.2 Extended Health Check
```bash
# Staging
curl -f -k https://staging.michaelschiemer.de/admin/health/api/summary | jq .
# Production
curl -f -k https://michaelschiemer.de/admin/health/api/summary | jq .
```
**Erwartete Ausgabe**: JSON mit `"overall_status": "healthy"`
### Phase 6: Quick-Start-Script nutzen
```bash
# Auf Production-Server
cd ~/deployment
# Script ausführbar machen (falls nötig)
chmod +x scripts/staging-quick-start.sh
# Script ausführen
./scripts/staging-quick-start.sh
```
Das Script bietet ein interaktives Menü für alle Tests.
### Phase 7: Ansible-Verifikation (falls Ansible installiert)
```bash
# Auf Control-Node (lokal)
cd ~/dev/michaelschiemer/deployment/ansible
# Staging-Verifikation
ansible-playbook -i inventory/production.yml \
playbooks/verify-staging.yml
# Production-Verifikation
ansible-playbook -i inventory/production.yml \
playbooks/verify-production.yml
```
## Fehlerbehebung
### PostgreSQL-Container startet nicht
```bash
# Logs prüfen
docker logs postgres-production
docker logs postgres-staging
# .env-Datei prüfen
cat ~/deployment/stacks/postgresql-production/.env
cat ~/deployment/stacks/postgresql-staging/.env
# Volumes prüfen
docker volume ls | grep postgres
```
### Network-Verbindung fehlgeschlagen
```bash
# Container-Networks prüfen
docker inspect staging-app | grep -A 10 Networks
docker inspect postgres-staging | grep -A 10 Networks
# Network-Verbindung testen
docker exec staging-app ping -c 2 postgres-staging
```
### Datenbank-Verbindung fehlgeschlagen
```bash
# Secrets prüfen
docker exec staging-app ls -la /var/www/html/storage/secrets/
docker exec staging-app cat /var/www/html/storage/secrets/db_user_password
# Environment-Variablen prüfen
docker exec staging-app env | grep DB_
```
### Health-Check fehlgeschlagen
```bash
# Container-Status prüfen
docker ps | grep staging
# Application-Logs prüfen
docker logs staging-app --tail 50
docker logs staging-nginx --tail 50
```
## Test-Ergebnisse dokumentieren
Nach jedem Test:
- ✅ Erfolgreich
- ❌ Fehlgeschlagen (mit Fehlerbeschreibung)
- ⚠️ Teilweise erfolgreich (mit Details)
## Nächste Schritte
Nach erfolgreichen Tests:
1. CI/CD-Workflow testen (Commit auf `staging`-Branch)
2. Datenbank-Isolation verifizieren
3. Backup-Strategie testen
4. Monitoring einrichten

View File

@@ -0,0 +1,286 @@
# Migration Guide: Separate Database Stacks
## Overview
This guide describes how to migrate from a shared PostgreSQL stack to separate database stacks for Production and Staging.
## Current State (Before Migration)
- Single PostgreSQL stack: `deployment/stacks/postgresql/`
- Both Production and Staging connect to the same database instance
- Database name: `michaelschiemer` (Production) and `michaelschiemer_staging` (Staging) in same instance
## Target State (After Migration)
- **Production Database**: `deployment/stacks/postgresql-production/`
- Container: `postgres-production`
- Network: `postgres-production-internal`
- Database: `michaelschiemer`
- **Staging Database**: `deployment/stacks/postgresql-staging/`
- Container: `postgres-staging`
- Network: `postgres-staging-internal`
- Database: `michaelschiemer_staging`
## Migration Steps
### Phase 1: Backup Existing Database
**CRITICAL**: Create backups before migration!
```bash
# On production server
cd ~/deployment/stacks/postgresql
# Create backup of production database
docker exec postgres-backup /scripts/backup.sh
# Create backup of staging database (if exists in same instance)
docker exec postgres psql -U postgres -d michaelschiemer_staging -c "SELECT 1;" && \
docker exec postgres-backup /scripts/backup.sh || echo "Staging database not found"
# List backups
ls -lh backups/
```
### Phase 2: Deploy New Database Stacks
#### 2.1 Deploy PostgreSQL Production Stack
```bash
# On production server
cd ~/deployment/stacks/postgresql-production
# Create .env file
cat > .env <<EOF
POSTGRES_DB=michaelschiemer
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<same-as-production-password>
BACKUP_RETENTION_DAYS=7
BACKUP_SCHEDULE=0 2 * * *
EOF
# Start PostgreSQL Production
docker compose up -d
# Verify
docker compose ps
docker exec postgres-production pg_isready -U postgres -d michaelschiemer
```
#### 2.2 Deploy PostgreSQL Staging Stack
```bash
# On production server
cd ~/deployment/stacks/postgresql-staging
# Create .env file
cat > .env <<EOF
POSTGRES_DB=michaelschiemer_staging
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<staging-password-can-differ>
BACKUP_RETENTION_DAYS=3
BACKUP_SCHEDULE=0 3 * * *
EOF
# Start PostgreSQL Staging
docker compose up -d
# Verify
docker compose ps
docker exec postgres-staging pg_isready -U postgres -d michaelschiemer_staging
```
### Phase 3: Restore Data to New Stacks
#### 3.1 Restore Production Database
```bash
# Find latest production backup
LATEST_PROD_BACKUP=$(ls -t ~/deployment/stacks/postgresql/backups/postgres_michaelschiemer_*.sql.gz | head -1)
# Copy backup to new stack
cp "$LATEST_PROD_BACKUP" ~/deployment/stacks/postgresql-production/backups/
# Restore to new production database
cd ~/deployment/stacks/postgresql-production
docker exec -it postgres-production-backup /scripts/restore.sh "/backups/$(basename $LATEST_PROD_BACKUP)"
```
#### 3.2 Restore Staging Database (if exists)
```bash
# Find latest staging backup (if exists)
LATEST_STAGING_BACKUP=$(ls -t ~/deployment/stacks/postgresql/backups/postgres_michaelschiemer_staging_*.sql.gz 2>/dev/null | head -1)
if [ -n "$LATEST_STAGING_BACKUP" ]; then
# Copy backup to new stack
cp "$LATEST_STAGING_BACKUP" ~/deployment/stacks/postgresql-staging/backups/
# Restore to new staging database
cd ~/deployment/stacks/postgresql-staging
docker exec -it postgres-staging-backup /scripts/restore.sh "/backups/$(basename $LATEST_STAGING_BACKUP)"
else
echo "No staging backup found - creating empty staging database"
fi
```
### Phase 4: Update Application Stacks
#### 4.1 Update Production Application Stack
The Production Application Stack should already be configured to use `postgres-production` via:
- Environment variable: `DB_HOST=postgres-production`
- Network: Connected to `postgres-production-internal`
**Verify connection**:
```bash
cd ~/deployment/stacks/production
docker compose -f docker-compose.base.yml -f docker-compose.production.yml exec app \
php -r "echo 'DB Connection: '; \$pdo = new PDO('pgsql:host=postgres-production;dbname=michaelschiemer', 'postgres', getenv('DB_PASSWORD')); echo 'OK\n';"
```
#### 4.2 Update Staging Application Stack
The Staging Application Stack should already be configured to use `postgres-staging` via:
- Environment variable: `DB_HOST=postgres-staging`
- Network: Connected to `postgres-staging-internal`
**Verify connection**:
```bash
cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml exec staging-app \
php -r "echo 'DB Connection: '; \$pdo = new PDO('pgsql:host=postgres-staging;dbname=michaelschiemer_staging', 'postgres', getenv('DB_PASSWORD')); echo 'OK\n';"
```
### Phase 5: Verify Migration
#### 5.1 Production Verification
```bash
# Check production database
docker exec postgres-production psql -U postgres -d michaelschiemer -c "\dt"
# Check production application
curl -k https://michaelschiemer.de/health
# Check production logs
cd ~/deployment/stacks/production
docker compose logs app | tail -20
```
#### 5.2 Staging Verification
```bash
# Check staging database
docker exec postgres-staging psql -U postgres -d michaelschiemer_staging -c "\dt"
# Check staging application
curl -k https://staging.michaelschiemer.de/health
# Check staging logs
cd ~/deployment/stacks/staging
docker compose logs staging-app | tail -20
```
### Phase 6: Cleanup (Optional)
**WARNING**: Only remove old stack after successful migration and verification!
```bash
# Stop old PostgreSQL stack
cd ~/deployment/stacks/postgresql
docker compose down
# Keep backups for safety - do NOT delete yet
# Consider keeping for at least 30 days
# Remove old stack (only after 30+ days of successful operation)
# rm -rf ~/deployment/stacks/postgresql
```
## Rollback Plan
If migration fails:
### Rollback to Shared Database
```bash
# 1. Stop new database stacks
cd ~/deployment/stacks/postgresql-production
docker compose down
cd ~/deployment/stacks/postgresql-staging
docker compose down
# 2. Restart old shared stack
cd ~/deployment/stacks/postgresql
docker compose up -d
# 3. Update application stacks to use old database
# Revert DB_HOST changes in docker-compose files
# Restart application stacks
```
## Network Configuration
### Production Application Stack
Must be connected to:
- `traefik-public` (for external access)
- `postgres-production-internal` (for database access)
- `app-internal` (for Redis, if shared)
### Staging Application Stack
Must be connected to:
- `traefik-public` (for external access)
- `postgres-staging-internal` (for database access)
- `staging-internal` (for staging services)
## Backup Strategy
### Production Backups
- **Location**: `~/deployment/stacks/postgresql-production/backups/`
- **Retention**: 7 days
- **Schedule**: Daily at 2:00 AM
### Staging Backups
- **Location**: `~/deployment/stacks/postgresql-staging/backups/`
- **Retention**: 3 days
- **Schedule**: Daily at 3:00 AM
## Troubleshooting
### Database Connection Refused
```bash
# Check if database container is running
docker ps | grep postgres-production
docker ps | grep postgres-staging
# Check network connectivity
docker network inspect postgres-production-internal
docker network inspect postgres-staging-internal
# Test connection from application container
docker exec <app-container> nc -zv postgres-production 5432
docker exec <app-container> nc -zv postgres-staging 5432
```
### Migration Data Loss
If data is missing after migration:
1. **Stop application** to prevent further writes
2. **Restore from backup** (see Phase 3)
3. **Verify data** before restarting application
## Additional Resources
- **PostgreSQL Production Stack**: `deployment/stacks/postgresql-production/README.md`
- **PostgreSQL Staging Stack**: `deployment/stacks/postgresql-staging/README.md`
- **Backup Playbook**: `deployment/ansible/playbooks/backup.yml`

View File

@@ -0,0 +1,144 @@
# Betriebssystem-Auswahl f?r Production-Server
**Status**: ? Aktuell
**Empfehlung**: Ubuntu 22.04 LTS
**Letzte Aktualisierung**: 2025-01-XX
---
## Empfehlung: Ubuntu 22.04 LTS
### Warum Ubuntu?
1. **? Getestet und validiert**
- Alle Ansible-Playbooks sind mit Ubuntu 22.04 LTS getestet
- Docker-Install-Script ist f?r Ubuntu optimiert
2. **? LTS-Support**
- Support bis April 2027
- Regelm??ige Security-Updates
- Stabile Basis f?r Production
3. **? Docker-Kompatibilit?t**
- Offizielle Docker-Repositorys f?r Ubuntu
- Beste Performance und Kompatibilit?t
- Aktuelle Docker-Versionen verf?gbar
4. **? Dokumentation**
- Alle Guides und Scripts sind auf Ubuntu ausgelegt
- Weniger Anpassungen n?tig
5. **? Community & Support**
- Gro?e Community
- Viele Tutorials und L?sungen verf?gbar
- Einfacheres Troubleshooting
---
## Alternative: Debian 12
### Vor- und Nachteile
**Vorteile:**
- ? Minimaler Footprint (weniger Ressourcen)
- ? Sehr stabil und sicher
- ? L?ngere Release-Zyklen
- ? Open-Source pur (keine kommerziellen Komponenten)
**Nachteile:**
- ?? Docker-Install-Script muss angepasst werden
- ?? ?ltere Paket-Versionen (konservativer)
- ?? Weniger getestet mit diesem Setup
### Anpassungen f?r Debian 12
Falls Debian 12 verwendet werden soll, m?ssen folgende Anpassungen vorgenommen werden:
**1. Docker-Install-Script anpassen** (`deployment/ansible/playbooks/install-docker.yml`):
```yaml
# Zeile 25: Ubuntu ? Debian
- name: Add Docker GPG key
ansible.builtin.shell:
cmd: |
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
creates: /etc/apt/keyrings/docker.asc
# Zeile 32: Ubuntu ? Debian
- name: Add Docker repository
ansible.builtin.shell:
cmd: |
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
creates: /etc/apt/sources.list.d/docker.list
```
**2. OS-Detection in Playbooks pr?fen**
Die meisten Ansible-Roles verwenden `ansible_os_family == 'Debian'`, was f?r beide Systeme funktioniert. Aber spezifische Ubuntu-Checks m?ssen angepasst werden.
---
## Vergleich
| Kriterium | Ubuntu 22.04 LTS | Debian 12 |
|-----------|------------------|-----------|
| **Getestet** | ? Ja | ?? Teilweise |
| **Docker-Support** | ? Optimal | ?? Anpassung n?tig |
| **LTS-Support** | ? Bis 2027 | ? Bis 2029 |
| **Ressourcen** | ?? Mehr | ? Weniger |
| **Paket-Versionen** | ? Aktueller | ?? Konservativer |
| **Dokumentation** | ? Vollst?ndig | ?? Anpassung n?tig |
| **Community** | ? Gro? | ? Gro? |
| **Setup-Aufwand** | ? Minimal | ?? Anpassungen n?tig |
---
## Empfehlung f?r dieses Projekt
**Ubuntu 22.04 LTS** ist die beste Wahl, weil:
1. ? Alle Scripts und Playbooks sind darauf ausgelegt
2. ? Docker-Installation funktioniert out-of-the-box
3. ? Vollst?ndig getestet und dokumentiert
4. ? LTS-Support bis 2027 (ausreichend f?r Production)
5. ? Einfacheres Setup und Wartung
**Debian 12** ist m?glich, wenn:
- Minimaler Footprint wichtig ist
- Man bereit ist, das Docker-Install-Script anzupassen
- Man die l?ngere LTS-Periode (bis 2029) bevorzugt
---
## Migration zwischen Systemen
Falls sp?ter von Ubuntu zu Debian (oder umgekehrt) gewechselt werden soll:
1. **Backup erstellen**
- Datenbank-Dumps
- Docker-Volumes
- Konfigurationsdateien
2. **Server neu aufsetzen**
- Neues OS installieren
- Basis-Setup durchf?hren
3. **Ansible-Playbooks anpassen** (falls Debian)
- Docker-Install-Script anpassen
- OS-spezifische Checks pr?fen
4. **Infrastructure deployen**
- Via Ansible alle Stacks deployen
- Datenbank-Dumps wiederherstellen
- Volumes migrieren
---
## Fazit
F?r dieses Projekt: **Ubuntu 22.04 LTS** ist die empfohlene und getestete Wahl. Debian 12 ist m?glich, erfordert aber zus?tzliche Anpassungen.
**N?chste Schritte:**
- Server mit Ubuntu 22.04 LTS installieren
- Setup-Guide befolgen: `deployment/docs/guides/server-rebuild-plan.md`

View File

@@ -0,0 +1,356 @@
# CI/CD Pipeline Test Checklist
**Stand:** 2025-01-XX
**Zweck:** Schritt-für-Schritt Checkliste für End-to-End Pipeline-Tests
---
## Vorbereitung
### Prerequisites Check ausführen
```bash
cd /home/michael/dev/michaelschiemer
./deployment/scripts/test-pipeline-prerequisites.sh
```
**Erwartet:** Alle Checks sollten grün sein (Warnings sind OK)
### Gitea Secrets verifizieren
**URL:** `https://git.michaelschiemer.de/michael/michaelschiemer/settings/secrets/actions`
**Erforderliche Secrets:**
- [ ] `REGISTRY_USER` - Docker Registry Benutzername
- [ ] `REGISTRY_PASSWORD` - Docker Registry Passwort
- [ ] `SSH_PRIVATE_KEY` - SSH Private Key für Production-Server
- [ ] `ANSIBLE_VAULT_PASSWORD` - Ansible Vault Password (optional, falls Vault verschlüsselt)
### Gitea Runner Status prüfen
**URL:** `https://git.michaelschiemer.de/admin/actions/runners`
**Erwartet:**
- [ ] Runner ist sichtbar als "Idle" oder "Active"
- [ ] Runner Name: `dev-runner-01` (oder ähnlich)
- [ ] Runner Labels: `ubuntu-latest`, `ubuntu-22.04`, `debian-latest`
**Lokal prüfen:**
```bash
cd deployment/gitea-runner
docker compose ps
```
**Erwartet:**
- [ ] `gitea-runner`: Up
- [ ] `gitea-runner-dind`: Up
---
## Staging Pipeline Test
### Schritt 1: Test-Commit erstellen
```bash
# Auf staging Branch wechseln
git checkout staging
git pull origin staging
# Kleine Änderung machen
echo "# CI/CD Pipeline Test - $(date)" >> README.md
git add README.md
git commit -m "test: CI/CD pipeline staging test"
git push origin staging
```
**Erwartet:**
- [ ] Push erfolgreich
- [ ] Keine Git-Fehler
### Schritt 2: Pipeline in Gitea Actions beobachten
**URL:** `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
**Erwartete Jobs (in Reihenfolge):**
1. **changes** - Determine Build Necessity
- [ ] Job startet innerhalb von 1-2 Minuten
- [ ] Job läuft erfolgreich durch
- [ ] Output zeigt: `needs_build=true` (oder `false` wenn nur Docs geändert)
2. **runtime-base** - Build Runtime Base Image (nur wenn `needs_runtime_build=true`)
- [ ] Job startet nach `changes`
- [ ] Docker Build läuft erfolgreich
- [ ] Image wird zur Registry gepusht
3. **test** - Run Tests & Quality Checks (nur wenn `needs_build=true`)
- [ ] Job startet nach `changes`
- [ ] Composer Dependencies werden installiert
- [ ] Tests laufen (oder werden übersprungen mit Warnung)
- [ ] Job läuft erfolgreich durch
4. **build** - Build Docker Image (nur wenn `needs_build=true`)
- [ ] Job startet nach `runtime-base` und `test`
- [ ] Docker Build läuft erfolgreich
- [ ] Image wird mit Tags gepusht: `latest`, `git-<sha>`, `<sha>-<timestamp>`
- [ ] Output zeigt Image URL
5. **deploy-staging** - Auto-deploy to Staging
- [ ] Job startet nach `build`
- [ ] SSH-Verbindung zum Server erfolgreich
- [ ] Code-Deployment (`deploy-application-code.yml`) erfolgreich
- [ ] Composer Dependencies Installation erfolgreich
- [ ] Image-Deployment (`deploy-image.yml`) erfolgreich
- [ ] Health-Check erfolgreich
**Gesamtzeit:** ~8-15 Minuten
### Schritt 3: Deployment auf Staging verifizieren
**Code-Deployment:**
```bash
ssh deploy@94.16.110.151
cd /home/deploy/michaelschiemer/current
git log -1 # Sollte Test-Commit zeigen
git branch # Sollte auf staging sein
```
**Erwartet:**
- [ ] Letzter Commit ist der Test-Commit
- [ ] Branch ist `staging`
**Composer Dependencies:**
```bash
cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml \
exec staging-app test -f /var/www/html/vendor/autoload.php && echo "EXISTS"
```
**Erwartet:**
- [ ] Output: `EXISTS`
**Image-Deployment:**
```bash
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml ps
```
**Erwartet:**
- [ ] Alle Container: Up (healthy)
- [ ] Image Tag entspricht dem gebauten Image
**Health-Check:**
```bash
curl -f https://staging.michaelschiemer.de/health
```
**Erwartet:**
- [ ] HTTP 200 OK
- [ ] JSON Response mit Status
**Application Test:**
- [ ] Staging URL erreichbar: `https://staging.michaelschiemer.de`
- [ ] Application läuft korrekt
- [ ] Keine Fehler in Browser Console
### Schritt 4: Fehlerbehebung (falls notwendig)
**Falls Jobs fehlschlagen:**
1. **Logs in Gitea Actions UI prüfen**
- Klicke auf fehlgeschlagenen Job
- Scrolle durch Logs
- Suche nach Fehlermeldungen
2. **Container Logs auf Server prüfen**
```bash
ssh deploy@94.16.110.151
cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml logs
```
3. **Bekannte Probleme:**
- Siehe: `deployment/docs/troubleshooting/initial-deployment-issues.md`
- Siehe: `deployment/docs/guides/pipeline-testing-guide.md`
---
## Production Pipeline Test
**⚠️ WICHTIG:** Nur nach erfolgreichem Staging-Test durchführen!
### Schritt 1: Test-Commit auf main erstellen
```bash
# Auf main Branch wechseln
git checkout main
git pull origin main
# Merge staging (oder direkter Commit für Test)
echo "# CI/CD Pipeline Test Production - $(date)" >> README.md
git add README.md
git commit -m "test: CI/CD pipeline production test"
git push origin main
```
**Erwartet:**
- [ ] Push erfolgreich
- [ ] Keine Git-Fehler
### Schritt 2: Pipeline in Gitea Actions beobachten
**URL:** `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
**Erwartete Jobs (in Reihenfolge):**
1. **changes** - Determine Build Necessity
- [ ] Job startet innerhalb von 1-2 Minuten
- [ ] Job läuft erfolgreich durch
2. **runtime-base** - Build Runtime Base Image (falls notwendig)
- [ ] Job startet nach `changes`
- [ ] Docker Build läuft erfolgreich
3. **test** - Run Tests & Quality Checks
- [ ] Job startet nach `changes`
- [ ] Tests laufen erfolgreich
4. **build** - Build Docker Image
- [ ] Job startet nach `runtime-base` und `test`
- [ ] Docker Build läuft erfolgreich
- [ ] Image wird zur Registry gepusht
5. **deploy-production** - Auto-deploy to Production
- [ ] Job startet nach `build`
- [ ] SSH-Verbindung erfolgreich
- [ ] Code-Deployment erfolgreich
- [ ] Composer Dependencies Installation erfolgreich
- [ ] Image-Deployment erfolgreich
- [ ] Health-Check erfolgreich
**Gesamtzeit:** ~8-15 Minuten
### Schritt 3: Deployment auf Production verifizieren
**Code-Deployment:**
```bash
ssh deploy@94.16.110.151
cd /home/deploy/michaelschiemer/current
git log -1 # Sollte Test-Commit zeigen
git branch # Sollte auf main sein
```
**Erwartet:**
- [ ] Letzter Commit ist der Test-Commit
- [ ] Branch ist `main`
**Composer Dependencies:**
```bash
cd ~/deployment/stacks/production
docker compose -f docker-compose.base.yml -f docker-compose.production.yml \
exec php test -f /var/www/html/vendor/autoload.php && echo "EXISTS"
```
**Erwartet:**
- [ ] Output: `EXISTS`
**Image-Deployment:**
```bash
docker compose -f docker-compose.base.yml -f docker-compose.production.yml ps
```
**Erwartet:**
- [ ] Alle Container: Up (healthy)
- [ ] Image Tag entspricht dem gebauten Image
**Health-Check:**
```bash
curl -f https://michaelschiemer.de/health
```
**Erwartet:**
- [ ] HTTP 200 OK
- [ ] JSON Response mit Status
**Application Test:**
- [ ] Production URL erreichbar: `https://michaelschiemer.de`
- [ ] Application läuft korrekt
- [ ] Keine Fehler in Browser Console
### Schritt 4: Rollback-Test (Optional)
**Falls Deployment fehlschlägt oder Probleme auftreten:**
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/rollback.yml \
--vault-password-file secrets/.vault_pass
```
**Erwartet:**
- [ ] Rollback erfolgreich
- [ ] Vorherige Version läuft wieder
---
## Test-Zusammenfassung
### Staging Test
- [ ] Alle Jobs erfolgreich
- [ ] Code-Deployment erfolgreich
- [ ] Composer Dependencies installiert
- [ ] Image-Deployment erfolgreich
- [ ] Health-Check erfolgreich
- [ ] Application läuft korrekt
### Production Test
- [ ] Alle Jobs erfolgreich
- [ ] Code-Deployment erfolgreich
- [ ] Composer Dependencies installiert
- [ ] Image-Deployment erfolgreich
- [ ] Health-Check erfolgreich
- [ ] Application läuft korrekt
---
## Nächste Schritte nach erfolgreichem Test
1. **Dokumentation aktualisieren**
- Status-Dokumente aktualisieren
- Bekannte Probleme dokumentieren
- Testergebnisse dokumentieren
2. **Backup-Playbook testen**
- Siehe: `deployment/docs/guides/backup-and-rollback-guide.md`
3. **Monitoring verifizieren**
- Health-Checks funktionieren
- Logs sind verfügbar
- Metriken werden gesammelt
---
## Troubleshooting
### Pipeline startet nicht
- Prüfe Gitea Runner Status
- Prüfe Workflow-Datei Syntax
- Prüfe Branch-Trigger
### Registry Login fehlschlägt
- Prüfe `REGISTRY_USER` und `REGISTRY_PASSWORD` Secrets
- Teste Registry-Login manuell
### SSH-Verbindung fehlschlägt
- Prüfe `SSH_PRIVATE_KEY` Secret
- Prüfe SSH-Zugriff manuell
### Health-Check fehlschlägt
- Prüfe Container Status
- Prüfe Container Logs
- Prüfe Application Logs
**Weitere Hilfe:**
- `deployment/docs/troubleshooting/initial-deployment-issues.md`
- `deployment/docs/guides/pipeline-testing-guide.md`

View File

@@ -0,0 +1,214 @@
# CI/CD Pipeline Test - Schritt-für-Schritt Anleitung
**Stand:** 2025-11-07
**Status:** Gemeinsame Test-Anleitung
---
## Vorbereitung
### Schritt 1: Aktuellen Status prüfen
```bash
# Im Repository-Root
cd ~/dev/michaelschiemer # oder dein Repository-Pfad
# Aktuellen Branch prüfen
git branch --show-current
# Status prüfen
git status
```
**Erwartet:**
- Branch: `staging` oder `main` (je nachdem was du testen willst)
- Keine uncommitted Changes (oder committen vorher)
### Schritt 2: Secrets in Gitea prüfen
**Öffne im Browser:**
```
https://git.michaelschiemer.de/michael/michaelschiemer/settings/secrets/actions
```
**Prüfe ob folgende Secrets vorhanden sind:**
-`REGISTRY_USER`
-`REGISTRY_PASSWORD`
-`SSH_PRIVATE_KEY`
-`ANSIBLE_VAULT_PASSWORD`
**Falls `ANSIBLE_VAULT_PASSWORD` fehlt:**
- Erstelle Secret mit dem Vault-Passwort aus `deployment/ansible/secrets/.vault_pass`
### Schritt 3: Gitea Runner Status prüfen
**Im Browser:**
```
https://git.michaelschiemer.de/admin/actions/runners
```
**Erwartet:**
- Runner sollte als "Idle" oder "Active" angezeigt werden
**Oder lokal prüfen:**
```bash
cd deployment/gitea-runner
docker compose ps
```
**Erwartet:**
- `gitea-runner`: Up
- `gitea-runner-dind`: Up
---
## Staging Pipeline Test
### Schritt 1: Auf staging Branch wechseln
```bash
cd ~/dev/michaelschiemer # oder dein Repository-Pfad
git checkout staging
git pull origin staging
```
### Schritt 2: Test-Commit erstellen
```bash
# Kleine Änderung
echo "# Test CI/CD Pipeline - $(date)" >> README.md
# Committen
git add README.md
git commit -m "test: CI/CD pipeline test"
# Pushen (triggert automatisch Pipeline)
git push origin staging
```
### Schritt 3: Pipeline beobachten
**Öffne im Browser:**
```
https://git.michaelschiemer.de/michael/michaelschiemer/actions
```
**Erwartete Jobs:**
1. **changes** - Prüft ob Build notwendig ist
2. **test** - Führt Tests aus (falls changes = true)
3. **build** - Baut Docker Image (falls changes = true)
4. **deploy-staging** - Deploy zu Staging (automatisch bei staging Branch)
**Beobachte jeden Job:**
- Klicke auf den Job
- Prüfe die Logs
- Notiere Fehler falls welche auftreten
### Schritt 4: Verifikation auf Server
**Nach erfolgreichem Pipeline-Lauf:**
```bash
# SSH zum Server
ssh deploy@94.16.110.151
# Code-Deployment prüfen
cd /home/deploy/michaelschiemer/current
git log -1 # Sollte Test-Commit zeigen
# Composer Dependencies prüfen
docker compose -f ~/deployment/stacks/production/docker-compose.base.yml \
-f ~/deployment/stacks/production/docker-compose.production.yml \
exec php test -f /var/www/html/vendor/autoload.php && echo "EXISTS" || echo "MISSING"
# Container Status prüfen
docker compose -f ~/deployment/stacks/production/docker-compose.base.yml \
-f ~/deployment/stacks/production/docker-compose.production.yml ps
# Health-Check
curl -f https://staging.michaelschiemer.de/health
```
---
## Production Pipeline Test
**Wichtig:** Nur nach erfolgreichem Staging-Test!
### Schritt 1: Auf main Branch wechseln
```bash
cd ~/dev/michaelschiemer
git checkout main
git pull origin main
```
### Schritt 2: Test-Commit erstellen
```bash
# Kleine Änderung
echo "# Test CI/CD Pipeline Production - $(date)" >> README.md
# Committen
git add README.md
git commit -m "test: CI/CD pipeline production test"
# Pushen (triggert automatisch Pipeline)
git push origin main
```
### Schritt 3: Pipeline beobachten
**Gleiche Schritte wie Staging:**
- Pipeline in Gitea Actions UI beobachten
- Jobs prüfen
- Logs analysieren
### Schritt 4: Verifikation auf Server
**Gleiche Checks wie Staging, aber Production URL:**
```bash
curl -f https://michaelschiemer.de/health
```
---
## Fehlerbehebung
### Problem: Pipeline startet nicht
**Prüfe:**
1. Runner läuft: `docker compose ps` in `deployment/gitea-runner`
2. Runner in Gitea UI sichtbar
3. Workflow-Datei korrekt
### Problem: Code-Deployment schlägt fehl
**Prüfe:**
1. `deploy-application-code.yml` Logs in Gitea Actions
2. Git Repository existiert auf Server
3. Branch-Name korrekt
### Problem: Image-Deployment schlägt fehl
**Prüfe:**
1. Registry Login erfolgreich
2. Image existiert in Registry
3. `deploy-image.yml` Logs
### Problem: Health-Check schlägt fehl
**Prüfe:**
1. Container Status: `docker compose ps`
2. Container Logs: `docker compose logs`
3. Health-Check Endpoint: `curl https://michaelschiemer.de/health`
---
## Nächste Schritte
Nach erfolgreichem Test:
1. Fehler dokumentieren (falls welche aufgetreten sind)
2. CI/CD Status aktualisieren
3. Production-Deployment für echte Features verwenden

View File

@@ -0,0 +1,298 @@
# CI/CD Pipeline Testing Guide
**Stand:** 2025-11-07
**Status:** Anleitung für End-to-End Pipeline-Tests
---
## Übersicht
Dieses Dokument erklärt, wie die CI/CD Pipeline getestet wird. Die Tests sollten sowohl für Staging als auch für Production durchgeführt werden.
**📖 Verwandte Dokumentation:**
- [Pipeline Test Checklist](./pipeline-test-checklist.md) ⭐ - Detaillierte Schritt-für-Schritt Checkliste
- [CI/CD Workflow Guide](./cicd-workflow-guide.md) - Workflow-Dokumentation
- [CI/CD Status](../status/ci-cd-status.md) - Aktueller Status
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Probleme und Lösungen
**🔧 Test-Scripts:**
- `deployment/scripts/test-pipeline-prerequisites.sh` - Prüft alle Voraussetzungen für Pipeline-Tests
---
## Voraussetzungen prüfen
**Schnellcheck mit Script:**
```bash
cd /home/michael/dev/michaelschiemer
./deployment/scripts/test-pipeline-prerequisites.sh
```
Dieses Script prüft automatisch alle Voraussetzungen und gibt eine Zusammenfassung aus.
### 1. Secrets konfiguriert
**Erforderliche Secrets in Gitea:**
-`REGISTRY_USER` - Docker Registry Benutzername
-`REGISTRY_PASSWORD` - Docker Registry Passwort
-`SSH_PRIVATE_KEY` - SSH Private Key für Production-Server
-`ANSIBLE_VAULT_PASSWORD` - Ansible Vault Password
**Prüfen:**
```
https://git.michaelschiemer.de/michael/michaelschiemer/settings/secrets/actions
```
### 2. Gitea Runner läuft
**Prüfen:**
```bash
cd deployment/gitea-runner
docker compose ps
```
**Erwartet:**
- `gitea-runner`: Up
- `gitea-runner-dind`: Up
**In Gitea UI prüfen:**
```
https://git.michaelschiemer.de/admin/actions/runners
```
Runner sollte als "Idle" oder "Active" angezeigt werden.
### 3. Application Stack läuft
**Prüfen:**
```bash
ssh deploy@94.16.110.151
cd ~/deployment/stacks/production
docker compose -f docker-compose.base.yml -f docker-compose.production.yml ps
```
**Erwartet:**
- Alle Container: Up (healthy)
---
## Staging Pipeline Test
### Schritt 1: Test-Commit erstellen
```bash
# Auf staging Branch
git checkout staging
git pull origin staging
# Kleine Änderung
echo "# Test CI/CD Pipeline - $(date)" >> README.md
git add README.md
git commit -m "test: CI/CD pipeline test"
git push origin staging
```
### Schritt 2: Pipeline beobachten
**Gitea Actions UI:**
```
https://git.michaelschiemer.de/michael/michaelschiemer/actions
```
**Erwartete Jobs:**
1. **changes** - Prüft ob Build notwendig ist
2. **test** - Führt Tests aus
3. **build** - Baut Docker Image
4. **deploy-staging** - Deploy zu Staging
### Schritt 3: Verifikation
**Code-Deployment:**
```bash
ssh deploy@94.16.110.151
cd /home/deploy/michaelschiemer/current
git log -1 # Sollte Test-Commit zeigen
```
**Composer Dependencies:**
```bash
docker compose -f docker-compose.base.yml -f docker-compose.production.yml \
exec php test -f /var/www/html/vendor/autoload.php && echo "EXISTS"
```
**Image-Deployment:**
```bash
docker compose -f docker-compose.base.yml -f docker-compose.production.yml \
ps # Container sollten mit neuem Image laufen
```
**Health-Check:**
```bash
curl -f https://staging.michaelschiemer.de/health
```
### Schritt 4: Fehler beheben
**Falls Fehler auftreten:**
1. Logs in Gitea Actions UI prüfen
2. Container Logs prüfen: `docker compose logs`
3. Siehe [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)
---
## Production Pipeline Test
### Schritt 1: Test-Commit erstellen
**Wichtig:** Nur nach erfolgreichem Staging-Test!
```bash
# Auf main Branch
git checkout main
git pull origin main
# Merge staging (oder direkter Commit für Test)
echo "# Test CI/CD Pipeline Production - $(date)" >> README.md
git add README.md
git commit -m "test: CI/CD pipeline production test"
git push origin main
```
### Schritt 2: Pipeline beobachten
**Gitea Actions UI:**
```
https://git.michaelschiemer.de/michael/michaelschiemer/actions
```
**Erwartete Jobs:**
1. **changes** - Prüft ob Build notwendig ist
2. **test** - Führt Tests aus
3. **build** - Baut Docker Image
4. **deploy-production** - Deploy zu Production
### Schritt 3: Verifikation
**Gleiche Checks wie Staging:**
- Code-Deployment verifizieren
- Composer Dependencies verifizieren
- Image-Deployment verifizieren
- Health-Check durchführen
**Production URL:**
```bash
curl -f https://michaelschiemer.de/health
```
### Schritt 4: Rollback-Test (Optional)
**Falls Deployment fehlschlägt:**
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/rollback.yml \
--vault-password-file secrets/.vault_pass
```
---
## Manueller Workflow-Test
### Via Gitea UI
**Schritte:**
1. Gehe zu: `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
2. Wähle: "Manual Deployment"
3. Klicke: "Run workflow"
4. Wähle:
- Environment: `staging` oder `production`
- Image Tag: Optional (z.B. `latest` oder `git-abc1234`)
- Branch: Optional
5. Klicke: "Run workflow"
6. Beobachte Logs
---
## Checkliste für erfolgreichen Test
### Staging Test
- [ ] Test-Commit gepusht
- [ ] Pipeline gestartet
- [ ] Alle Jobs erfolgreich:
- [ ] changes
- [ ] test
- [ ] build
- [ ] deploy-staging
- [ ] Code-Deployment erfolgreich
- [ ] Composer Dependencies installiert
- [ ] Image-Deployment erfolgreich
- [ ] Health-Check erfolgreich
- [ ] Application läuft korrekt
### Production Test
- [ ] Staging Test erfolgreich
- [ ] Test-Commit auf main gepusht
- [ ] Pipeline gestartet
- [ ] Alle Jobs erfolgreich:
- [ ] changes
- [ ] test
- [ ] build
- [ ] deploy-production
- [ ] Code-Deployment erfolgreich
- [ ] Composer Dependencies installiert
- [ ] Image-Deployment erfolgreich
- [ ] Health-Check erfolgreich
- [ ] Application läuft korrekt
---
## Bekannte Probleme & Workarounds
### Problem: Pipeline startet nicht
**Ursache:** Runner läuft nicht oder ist nicht registriert
**Lösung:**
```bash
cd deployment/gitea-runner
docker compose restart gitea-runner
# Prüfe Runner-Status in Gitea UI
```
### Problem: Code-Deployment schlägt fehl
**Ursache:** Git Repository existiert nicht auf Server
**Lösung:**
```bash
# Initial Deployment durchführen
ansible-playbook -i inventory/production.yml \
playbooks/sync-application-code.yml \
--vault-password-file secrets/.vault_pass
```
### Problem: Image-Deployment schlägt fehl
**Ursache:** Registry Login fehlgeschlagen
**Lösung:**
- Prüfe `REGISTRY_USER` und `REGISTRY_PASSWORD` Secrets
- Teste Registry Login manuell
### Problem: Health-Check schlägt fehl
**Ursache:** Container starten nicht oder Application hat Fehler
**Lösung:**
- Prüfe Container Status
- Prüfe Container Logs
- Siehe [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)
---
## Referenz
- [CI/CD Workflow Guide](./cicd-workflow-guide.md) - Workflow-Dokumentation
- [CI/CD Status](../status/ci-cd-status.md) - Aktueller Status
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Probleme und Lösungen
- [Backup & Rollback Guide](./backup-and-rollback-guide.md) - Rollback-Prozess

View File

@@ -0,0 +1,162 @@
# Production Database Connection Guide
## Übersicht
Die Production-Application verbindet sich mit der separaten PostgreSQL-Production-Datenbank über das `postgres-production-internal` Network.
## Network-Konfiguration
### Production Application Stack
Die Production-Application-Services (`php`, `queue-worker`, `scheduler`) müssen mit dem `postgres-production-internal` Network verbunden sein.
**Konfiguration**:
- **Datei**: `docker-compose.postgres-override.yml`
- **Network**: `postgres-production-internal`
- **Verbindung**: Services werden diesem Network hinzugefügt
### Docker Compose Usage
```bash
# Production Stack mit Datenbank-Verbindung starten
docker compose -f docker-compose.base.yml \
-f docker-compose.production.yml \
-f docker-compose.postgres-override.yml \
up -d
```
## Services
Die folgenden Services werden mit dem `postgres-production-internal` Network verbunden:
1. **php** - PHP-FPM Application Container
2. **queue-worker** - Background Job Processor
3. **scheduler** - Cron Job Executor
## Environment Variables
Die Application verwendet folgende Environment-Variablen für die Datenbank-Verbindung:
```env
DB_HOST=postgres-production
DB_PORT=5432
DB_DATABASE=michaelschiemer
DB_USERNAME=postgres
DB_PASSWORD_FILE=/run/secrets/db_user_password
```
**Wichtig**: `DB_PASSWORD` wird über Docker Secrets geladen (`DB_PASSWORD_FILE`).
## Verifizierung
### 1. Network-Verbindung prüfen
```bash
# Prüfe, ob php-Container im Network ist
docker network inspect postgres-production-internal | grep php
# Erwartet: Container-Name sollte erscheinen
```
### 2. Datenbank-Verbindung testen
```bash
# Von php-Container aus
docker exec php php -r "
\$dsn = 'pgsql:host=postgres-production;port=5432;dbname=michaelschiemer';
\$pdo = new PDO(\$dsn, 'postgres', getenv('DB_PASSWORD'));
echo 'Connection successful: ' . \$pdo->query('SELECT version()')->fetchColumn();
"
```
### 3. Network-Isolation verifizieren
```bash
# Prüfe, ob Production-App NICHT auf Staging-DB zugreifen kann
docker exec php nc -zv postgres-staging 5432
# Erwartet: Connection refused oder timeout (keine Verbindung möglich)
```
## Troubleshooting
### Problem: Container kann Datenbank nicht erreichen
**Lösung**:
1. Prüfe, ob `postgres-production-internal` Network existiert:
```bash
docker network ls | grep postgres-production-internal
```
2. Prüfe, ob Container im Network ist:
```bash
docker network inspect postgres-production-internal
```
3. Prüfe, ob PostgreSQL-Production-Stack läuft:
```bash
docker ps | grep postgres-production
```
### Problem: DB_HOST nicht korrekt
**Lösung**:
1. Prüfe Environment-Variablen:
```bash
docker exec php printenv | grep DB_
```
2. Prüfe `.env`-Datei im Application-Stack:
```bash
cat ~/deployment/stacks/production/.env | grep DB_
```
3. Prüfe Ansible-Template:
- `deployment/ansible/templates/application.env.j2`
- Sollte `DB_HOST=postgres-production` für Production setzen
## Migration von alter Konfiguration
Falls die Production-Application noch die alte `postgres` (geteilte Datenbank) verwendet:
1. **Backup erstellen**:
```bash
cd ~/deployment/stacks/postgresql
docker exec postgres-backup /scripts/backup.sh
```
2. **PostgreSQL-Production-Stack starten**:
```bash
cd ~/deployment/stacks/postgresql-production
docker compose up -d
```
3. **Datenbank migrieren** (siehe `migrate-to-separate-databases.md`)
4. **Application-Stack aktualisieren**:
- `.env`-Datei: `DB_HOST=postgres-production`
- Network: `postgres-production-internal` hinzufügen
5. **Stack neu starten**:
```bash
cd ~/deployment/stacks/production
docker compose -f docker-compose.base.yml \
-f docker-compose.production.yml \
-f docker-compose.postgres-override.yml \
up -d
```
## Ansible-Integration
Das Ansible-Setup konfiguriert die Datenbank-Verbindung automatisch:
- **Template**: `deployment/ansible/templates/application.env.j2`
- **Variable**: `db_host_default: "postgres-production"` (in `group_vars/production/vars.yml`)
- **Network**: Wird über `docker-compose.postgres-override.yml` konfiguriert
## Weitere Ressourcen
- **PostgreSQL-Production-Stack**: `deployment/stacks/postgresql-production/README.md`
- **Migrations-Guide**: `deployment/docs/guides/migrate-to-separate-databases.md`
- **Staging-Datenbank**: `deployment/docs/guides/staging-test-plan.md`

View File

@@ -2,7 +2,34 @@
## 🚀 Schnellstart: Code deployen
### Einfachste Methode
### Initial Deployment (Einmalig - erstes Setup)
**Für erstes Setup des Servers:**
```bash
# 1. Code synchronisieren (Rsync)
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/sync-application-code.yml \
--vault-password-file secrets/.vault_pass
# 2. Composer Dependencies installieren
ansible-playbook -i inventory/production.yml \
playbooks/install-composer-dependencies.yml \
--vault-password-file secrets/.vault_pass
# 3. Application Stack deployen
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml \
--tags application \
--vault-password-file secrets/.vault_pass
```
**Siehe auch:** [Initial Deployment Guide](./initial-deployment-guide.md)
### Normal Deployment (CI/CD)
**Für zukünftige Deployments:**
```bash
# 1. Code ändern
@@ -65,7 +92,7 @@ https://git.michaelschiemer.de/michael/michaelschiemer/actions
ssh deploy@94.16.110.151
# Container-Status
cd ~/deployment/stacks/application
cd ~/deployment/stacks/production
docker compose ps
# Logs ansehen
@@ -90,7 +117,7 @@ curl https://michaelschiemer.de/health
- **`docs/guides/setup-guide.md`** - Kompletter Setup-Guide
- **`ansible/README.md`** - Ansible Playbooks Dokumentation
- **`stacks/application/README.md`** - Application Stack Details
- **`stacks/production/README.md`** - Application Stack Details
### Workflow-Dokumentation
@@ -155,7 +182,7 @@ docker build -f Dockerfile.production -t test .
**Deployment fehlgeschlagen:**
```bash
# Logs prüfen
ssh deploy@94.16.110.151 "cd ~/deployment/stacks/application && docker compose logs"
ssh deploy@94.16.110.151 "cd ~/deployment/stacks/production && docker compose logs"
# Manueller Rollback
cd deployment/ansible

View File

@@ -0,0 +1,143 @@
# Security Hardening - Dokumentation
## Aktuelle Security-Maßnahmen
### 1. Firewall (nftables)
- **Status**: ✅ Implementiert
- **Konfiguration**: `deployment/ansible/templates/wireguard-host-firewall.nft.j2`
- **Features**:
- Admin-Services nur über VPN erreichbar
- Public Services (HTTP, HTTPS, SSH) öffentlich erreichbar
- ICMP (Ping) erlaubt
- Established/Related Connections erlaubt
### 2. WireGuard VPN
- **Status**: ✅ Implementiert
- **Zweck**: Admin-Services isoliert hinter VPN
- **Ports**: 8080 (Traefik), 9090 (Prometheus), 3001 (Grafana), 9000 (Portainer), 8001 (Redis Insight)
- **Konfiguration**: `deployment/ansible/playbooks/setup-wireguard-host.yml`
### 3. Unattended-Upgrades
- **Status**: ✅ Implementiert
- **Konfiguration**: `deployment/ansible/roles/system/tasks/main.yml`
- **Features**:
- Automatische Security-Updates
- Konfigurierbare Reboot-Zeiten
- APT Cache Management
### 4. Security Headers (Traefik)
- **Status**: ✅ Implementiert
- **Konfiguration**: Traefik Dynamic Config
- **Headers**: HSTS, X-Frame-Options, X-Content-Type-Options, etc.
### 5. Docker Secrets
- **Status**: ✅ Implementiert
- **Verwendung**: Secrets werden über Docker Secrets verwaltet
- **Zugriff**: Secrets werden für PHP (www-data) zugänglich gemacht
## Geplante Verbesserungen
### 1. SSH Hardening
**Status**: ⚠️ Noch nicht implementiert
**Geplante Maßnahmen**:
- Key-only Authentication (keine Passwort-Authentifizierung)
- Rate Limiting für SSH
- Disable Root-Login
- SSH-Keys Rotation Policy
**Implementierung**:
```yaml
# deployment/ansible/roles/ssh/tasks/main.yml
- name: Configure SSH hardening
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
- { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
- { regexp: '^#?MaxAuthTries', line: 'MaxAuthTries 3' }
```
### 2. Container Security Scanning
**Status**: ❌ Nicht implementiert
**Geplante Tools**:
- Trivy für Container-Scanning
- Integration in CI/CD Pipeline
- Automatische Scans vor Deployment
### 3. Secrets Rotation Policy
**Status**: ⚠️ Manuell
**Geplante Maßnahmen**:
- Automatische Secrets-Rotation
- Secrets-Versioning
- Secrets-Audit-Logging
### 4. DDoS Protection
**Status**: ⚠️ Teilweise (Traefik Rate Limiting)
**Geplante Maßnahmen**:
- Erweiterte Rate Limiting Rules
- IP-based Rate Limiting
- Geo-blocking für Admin-Endpoints
### 5. Network Isolation Verification
**Status**: ✅ Basis vorhanden
**Aktuell**:
- `traefik-public` und `app-internal` Networks
- WireGuard für Admin Services
**Zu prüfen**:
- Database Network Isolation
- Redis Network Isolation
- Service-to-Service Communication Audit
## Security Checklist
### Vor Production-Deployment
- [ ] Firewall Rules Audit durchgeführt
- [ ] SSH Hardening konfiguriert
- [ ] Container Security Scanning aktiviert
- [ ] Secrets Rotation Policy definiert
- [ ] DDoS Protection konfiguriert
- [ ] Network Isolation verifiziert
- [ ] Security Headers verifiziert
- [ ] SSL/TLS Configuration geprüft
### Regelmäßige Audits
- [ ] Monatliche Security-Updates
- [ ] Quartalsweise Firewall Rules Review
- [ ] Jährliche Secrets Rotation
- [ ] Kontinuierliche Container Scanning
## Security Best Practices
1. **Principle of Least Privilege**: Services haben nur die minimal notwendigen Berechtigungen
2. **Defense in Depth**: Mehrere Security-Layer (Firewall, VPN, Application-Level)
3. **Regular Updates**: Automatische Security-Updates aktiviert
4. **Secrets Management**: Secrets werden sicher verwaltet (Docker Secrets, Ansible Vault)
5. **Network Segmentation**: Admin-Services isoliert hinter VPN
6. **Monitoring**: Security-Events werden geloggt und überwacht
## Incident Response
Bei Security-Incidents:
1. **Isolation**: Betroffene Services isolieren
2. **Investigation**: Logs analysieren
3. **Remediation**: Sicherheitslücken schließen
4. **Documentation**: Incident dokumentieren
5. **Prevention**: Maßnahmen zur Verhinderung zukünftiger Incidents
## Kontakt
Bei Security-Fragen oder Incidents:
- **Email**: kontakt@michaelschiemer.de
- **Documentation**: `deployment/docs/guides/security-hardening.md`

View File

@@ -0,0 +1,428 @@
# Server-Neuaufbau Plan - Debian 13 (Trixie)
## Übersicht
Dieser Plan beschreibt den kompletten Neuaufbau des Production-Servers mit Debian 13 (Trixie) LTS, inklusive aller Infrastructure-Stacks.
## Architektur-Entscheidungen
### Betriebssystem
- **Debian 13 (Trixie) LTS**
- **UEFI-Version** (empfohlen für moderne Server-Hardware)
- Minimale Installation (ohne Desktop)
- SSH-Zugriff konfiguriert
- Firewall (nftables/ufw)
### UEFI vs. BIOS
- **UEFI empfohlen**: Moderner Standard, GPT-Partitionierung, Secure Boot (optional), schnellerer Boot
- **BIOS nur wenn**: Hardware unterstützt kein UEFI oder Legacy-Systeme vorhanden
### Setup-Strategie
- **Ansible-basiert**: Alle Schritte automatisierbar
- **Schrittweise**: Basis-Setup → Docker → Infrastructure
- **Verifikation**: Jeder Schritt wird geprüft
## Implementierungs-Phasen
### Phase 1: Server-Initialisierung (Netcup Control Panel)
#### 1.1 Server zurücksetzen
**Schritte:**
1. Netcup Control Panel öffnen
2. Server zurücksetzen/neu installieren
3. **Debian 13 (Trixie)** auswählen
4. **UEFI-Version** wählen (empfohlen)
5. Root-Passwort notieren (sicher speichern!)
6. SSH-Key-Option prüfen (falls verfügbar)
**Wichtig:**
- Alle Daten werden gelöscht - vorher Backups erstellen!
- Neue Server-IP notieren (falls sich ändert)
- DNS-Records müssen ggf. aktualisiert werden
#### 1.2 Initialer SSH-Zugriff
**Option A: Mit vorkonfiguriertem deploy-User (empfohlen)**
Wenn du beim Server-Setup im Netcup Control Panel:
- Benutzer `deploy` erstellt hast
- SSH-Key (`production.pub`) hinzugefügt hast
Dann kannst du direkt verbinden:
```bash
# Mit deploy-User verbinden (SSH-Key wird automatisch verwendet)
ssh deploy@<server-ip>
# Oder mit SSH-Config:
ssh production
```
**Option B: Mit Root-Zugriff (falls kein deploy-User erstellt wurde)**
```bash
# Mit Root-Zugriff verbinden
ssh root@<server-ip>
# Passwort: <root-password-vom-netcup-panel>
# System aktualisieren
apt update && apt upgrade -y
# Basis-Pakete installieren
apt install -y curl wget git vim sudo
```
**Verifikation:**
- SSH-Verbindung funktioniert
- System ist aktuell
- Basis-Tools verfügbar
### Phase 2: Basis-Setup (Ansible)
#### 2.1 Deploy-User erstellen
**Option A: Vorkonfiguriert (empfohlen, wenn beim Server-Setup erstellt)**
Wenn du beim Server-Setup im Netcup Control Panel:
- Benutzer `deploy` erstellt hast
- SSH-Key (`production.pub`) hinzugefügt hast
Dann kannst du **Phase 2.1 überspringen** und direkt zu **Phase 2.2** gehen!
**Verifikation:**
```bash
# Auf Control-Node
ssh production 'whoami'
# Sollte ausgeben: deploy
```
**Option B: Manuell erstellen (falls nicht beim Setup erstellt)**
**Manuell (auf Server):**
```bash
# User anlegen
adduser deploy
usermod -aG sudo deploy
# SSH-Verzeichnis erstellen
mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
```
**SSH-Key hinzufügen (von Control-Node):**
```bash
# Auf Control-Node
ssh-copy-id -i ~/.ssh/production.pub deploy@<server-ip>
# Oder manuell:
cat ~/.ssh/production.pub | ssh deploy@<server-ip> "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh"
```
**SSH-Config auf Control-Node anpassen:**
```bash
# ~/.ssh/config
Host production
HostName <server-ip>
User deploy
IdentityFile ~/.ssh/production
ServerAliveInterval 60
ServerAliveCountMax 3
```
#### 2.2 Initial Server Setup (Ansible Playbook)
**Auf Control-Node:**
**Mit vorkonfiguriertem deploy-User (empfohlen):**
```bash
cd deployment/ansible
# Initiales Server-Setup ausführen
# Keine zusätzlichen Parameter nötig - deploy-User und SSH-Key sind bereits konfiguriert
ansible-playbook -i inventory/production.yml \
playbooks/initial-server-setup.yml
```
**Mit root-User (falls deploy-User nicht erstellt wurde):**
```bash
cd deployment/ansible
# Initiales Server-Setup ausführen
ansible-playbook -i inventory/production.yml \
playbooks/initial-server-setup.yml \
--ask-pass \
-e "ansible_user=root"
```
**Was das Playbook macht:**
- System-Updates (apt update/upgrade)
- Basis-Pakete installieren (curl, wget, git, vim, sudo, ufw, fail2ban)
- Deploy-User konfigurieren (falls nicht vorhanden)
- SSH-Konfiguration (optional: key-only auth)
- Firewall-Setup (optional, standardmäßig deaktiviert)
- Fail2ban konfigurieren
**Verifikation:**
```bash
# Auf Server
whoami # Sollte ausgeben: deploy
sudo -v # Sudo-Rechte testen
```
#### 2.3 Firewall konfigurieren
**Option 1: ufw (einfacher)**
```bash
# Auf Server
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw allow 51820/udp # WireGuard
sudo ufw enable
sudo ufw status
```
**Option 2: nftables (erweitert)**
- Wird später über WireGuard-Playbook konfiguriert
- Admin-Ports nur über VPN
#### 2.3 System-Härtung
**SSH-Key-only Authentication:**
```bash
# Auf Server
sudo nano /etc/ssh/sshd_config
# Ändern:
PasswordAuthentication no
PubkeyAuthentication yes
# Neu starten
sudo systemctl restart sshd
```
**Unattended-Upgrades (via Ansible):**
- Wird automatisch über `system`-Role konfiguriert
**Optional: Fail2ban**
```bash
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
```
### Phase 3: Docker-Installation
#### 3.1 Docker-Repository anpassen
**Aktuell:** `install-docker.yml` nutzt Ubuntu-Repository (funktioniert auf Debian)
**Optional:** Debian-spezifisches Repository nutzen (siehe `install-docker.yml`)
#### 3.2 Docker installieren (via Ansible)
```bash
# Auf Control-Node
cd ~/dev/michaelschiemer/deployment/ansible
ansible-playbook -i inventory/production.yml playbooks/install-docker.yml
```
**Verifikation:**
```bash
# Auf Server
docker --version
docker compose version
docker run hello-world
```
### Phase 4: Ansible-Setup
#### 4.1 Ansible auf Control-Node
**Installation (falls nicht vorhanden):**
```bash
# Debian/Ubuntu
sudo apt install ansible
# Oder via pip
pip install ansible
```
**Inventory prüfen:**
```bash
# deployment/ansible/inventory/production.yml
# Server-IP und SSH-Config aktualisieren
```
**SSH-Key-Test:**
```bash
ansible production -m ping
# Sollte ausgeben: pong
```
#### 4.2 Ansible-Playbooks anpassen
**Geänderte Dateien:**
- `install-docker.yml`: Debian-Repository prüfen/anpassen (optional)
- `setup-infrastructure.yml`: Verifizieren
- Vault-Secrets prüfen
### Phase 5: Infrastructure-Deployment
#### 5.1 Docker installieren (via Ansible)
```bash
cd ~/dev/michaelschiemer/deployment/ansible
ansible-playbook -i inventory/production.yml playbooks/install-docker.yml
```
#### 5.2 Komplettes Infrastructure-Setup
```bash
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml \
--ask-vault-pass
```
**Deployed Stacks:**
- Traefik (Reverse Proxy & SSL)
- PostgreSQL-Production (Database)
- Redis (Cache & Session)
- Docker Registry (Private Registry)
- MinIO (Object Storage)
- Gitea (Git Server)
- Monitoring (Portainer, Grafana, Prometheus)
- Production Application Stack
**Erwartete Dauer:** 10-20 Minuten
#### 5.3 Staging-Setup (optional, nach Production)
```bash
ansible-playbook -i inventory/production.yml \
playbooks/setup-staging.yml \
--ask-vault-pass
```
### Phase 6: Verifikation
#### 6.1 Services prüfen
**Auf Server:**
```bash
# Alle Container laufen
docker ps
# Networks vorhanden
docker network ls
# Health-Checks
curl https://michaelschiemer.de/health
curl https://git.michaelschiemer.de
```
#### 6.2 Ansible-Verifikation
```bash
# Auf Control-Node
ansible-playbook -i inventory/production.yml \
playbooks/verify-production.yml
ansible-playbook -i inventory/production.yml \
playbooks/verify-staging.yml
```
## Checkliste
### Vorbereitung
- [ ] Netcup Control Panel Zugriff
- [ ] Neuer SSH-Key generiert
- [ ] Ansible auf Control-Node installiert
- [ ] Vault-Secrets vorbereitet
- [ ] DNS-Zugriff (für Domain-Updates)
- [ ] Backups erstellt (falls vorhanden)
### Phase 1: Server-Initialisierung
- [ ] Server zurückgesetzt
- [ ] Debian 13 (Trixie) installiert
- [ ] UEFI-Version gewählt
- [ ] Root-Passwort notiert
- [ ] Initialer SSH-Zugriff funktioniert
- [ ] System aktualisiert
### Phase 2: Basis-Setup
- [ ] Deploy-User erstellt
- [ ] SSH-Key hinzugefügt
- [ ] SSH-Config angepasst
- [ ] Firewall konfiguriert
- [ ] System gehärtet
### Phase 3: Docker-Installation
- [ ] Docker installiert
- [ ] Docker Compose installiert
- [ ] Deploy-User in docker-Gruppe
- [ ] Docker-Test erfolgreich
### Phase 4: Ansible-Setup
- [ ] Ansible installiert
- [ ] Inventory aktualisiert
- [ ] SSH-Key-Test erfolgreich
- [ ] Playbooks geprüft
### Phase 5: Infrastructure-Deployment
- [ ] Docker installiert (via Ansible)
- [ ] Infrastructure-Setup erfolgreich
- [ ] Alle Stacks deployed
- [ ] Staging-Setup (optional)
### Phase 6: Verifikation
- [ ] Services laufen
- [ ] Networks vorhanden
- [ ] Health-Checks erfolgreich
- [ ] Ansible-Verifikation erfolgreich
## Wichtige Hinweise
1. **SSH-Key-Sicherheit**: Neuen SSH-Key generieren und sicher speichern
2. **Vault-Secrets**: Alle Secrets in Ansible Vault verschlüsselt
3. **Backup-Strategie**: Vor Neuaufbau alle Daten sichern (falls vorhanden)
4. **DNS-Konfiguration**: Domains müssen auf neue Server-IP zeigen
5. **Rollback-Plan**: Alte Server-Konfiguration dokumentieren
## Troubleshooting
### SSH-Verbindung fehlgeschlagen
- Firewall-Regeln prüfen
- SSH-Key-Berechtigungen prüfen (600)
- SSH-Config prüfen
### Docker-Installation fehlgeschlagen
- Repository-URL prüfen
- GPG-Key prüfen
- Netzwerk-Verbindung prüfen
### Ansible-Playbook fehlgeschlagen
- Inventory-Datei prüfen
- SSH-Zugriff testen: `ansible production -m ping`
- Vault-Passwort prüfen
### Infrastructure-Deployment fehlgeschlagen
- Docker läuft?
- Networks vorhanden?
- Secrets korrekt?
- Logs prüfen: `docker logs <container>`
## Nächste Schritte nach Neuaufbau
1. Monitoring einrichten
2. Backup-Strategie verifizieren
3. Staging-Environment testen
4. CI/CD-Pipeline testen
5. Dokumentation aktualisieren
## Referenzen
- `deployment/docs/guides/ssh-access.md` - SSH-Zugriff Dokumentation
- `deployment/ansible/playbooks/initial-server-setup.yml` - Basis-Setup Playbook
- `deployment/ansible/playbooks/install-docker.yml` - Docker-Installation
- `deployment/ansible/playbooks/setup-infrastructure.yml` - Infrastructure-Setup

View File

@@ -0,0 +1,218 @@
# SSH-Zugriff Dokumentation
## Übersicht
Diese Dokumentation beschreibt die SSH-Zugriffskonfiguration für den Production-Server.
## SSH-Key-Generierung
### Neuen SSH-Key generieren
```bash
# Auf Control-Node (lokal)
ssh-keygen -t ed25519 -C "production-server" -f ~/.ssh/production
# Oder RSA (falls ed25519 nicht unterstützt)
ssh-keygen -t rsa -b 4096 -C "production-server" -f ~/.ssh/production
```
**Wichtig:**
- Passphrase setzen (empfohlen)
- Key sicher speichern
- Private Key niemals teilen
### Key-Berechtigungen
```bash
chmod 600 ~/.ssh/production
chmod 644 ~/.ssh/production.pub
```
## SSH-Config
### Control-Node Konfiguration
**Datei:** `~/.ssh/config`
```ssh-config
Host production
HostName <server-ip>
User deploy
IdentityFile ~/.ssh/production
ServerAliveInterval 60
ServerAliveCountMax 3
StrictHostKeyChecking yes
UserKnownHostsFile ~/.ssh/known_hosts
```
**Wichtig:**
- `<server-ip>` durch tatsächliche IP ersetzen
- `deploy` ist der Standard-User (nach Setup)
### SSH-Config testen
```bash
# Verbindung testen
ssh production 'whoami'
# Sollte ausgeben: deploy
# Ohne Passwort (Key-only)
ssh production
```
## Server-Setup
### Deploy-User erstellen
**Auf Server (als root):**
```bash
# User anlegen
adduser deploy
usermod -aG sudo deploy
# SSH-Verzeichnis erstellen
mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
```
### Public Key hinzufügen
**Option 1: ssh-copy-id (empfohlen)**
```bash
# Auf Control-Node
ssh-copy-id -i ~/.ssh/production.pub deploy@<server-ip>
```
**Option 2: Manuell**
```bash
# Auf Control-Node
cat ~/.ssh/production.pub | ssh deploy@<server-ip> \
"mkdir -p ~/.ssh && \
cat >> ~/.ssh/authorized_keys && \
chmod 600 ~/.ssh/authorized_keys && \
chmod 700 ~/.ssh"
```
**Option 3: Via Ansible (nach initialem Setup)**
```bash
# Wird automatisch über initial-server-setup.yml verwaltet
```
### SSH-Key-only Authentication
**Auf Server:**
```bash
sudo nano /etc/ssh/sshd_config
```
**Ändern:**
```config
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
```
**Neu starten:**
```bash
sudo systemctl restart sshd
```
**Wichtig:** Vorher sicherstellen, dass SSH-Key funktioniert!
## Ansible-Integration
### Inventory-Konfiguration
**Datei:** `deployment/ansible/inventory/production.yml`
```yaml
all:
children:
production:
hosts:
server:
ansible_host: <server-ip>
ansible_user: deploy
ansible_python_interpreter: /usr/bin/python3
ansible_ssh_private_key_file: ~/.ssh/production
```
### Ansible-Verbindung testen
```bash
cd ~/dev/michaelschiemer/deployment/ansible
ansible production -m ping
# Sollte ausgeben: pong
```
## Sicherheit
### Best Practices
1. **SSH-Key mit Passphrase**
- Private Key verschlüsselt
- Passphrase bei jeder Nutzung
2. **Key-Rotation**
- Regelmäßig neue Keys generieren
- Alte Keys entfernen
3. **Fail2ban**
- Automatische Sperrung bei Brute-Force
- Optional, aber empfohlen
4. **SSH-Port ändern (optional)**
- Standard-Port 22 ändern
- Reduziert automatische Angriffe
5. **Root-Login deaktivieren**
- Nur über deploy-User
- Sudo für Admin-Tasks
### Fail2ban Installation
```bash
# Auf Server
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Status prüfen
sudo fail2ban-client status sshd
```
## Troubleshooting
### SSH-Verbindung fehlgeschlagen
**Problem:** `Permission denied (publickey)`
**Lösung:**
1. Key-Berechtigungen prüfen: `chmod 600 ~/.ssh/production`
2. Public Key auf Server prüfen: `cat ~/.ssh/authorized_keys`
3. SSH-Config prüfen: `ssh -v production`
4. Server-Logs prüfen: `sudo tail -f /var/log/auth.log`
### Key-Format-Problem
**Problem:** `error in libcrypto`
**Lösung:**
1. Neuen Key generieren (ed25519 oder RSA)
2. WSL/libcrypto-Kompatibilität prüfen
3. Key-Format prüfen: `file ~/.ssh/production`
### Ansible-Verbindung fehlgeschlagen
**Problem:** `ansible production -m ping` schlägt fehl
**Lösung:**
1. SSH-Verbindung manuell testen: `ssh production`
2. Inventory-Datei prüfen
3. Python-Interpreter prüfen: `ansible production -m raw -a "which python3"`
## Referenzen
- `deployment/docs/guides/server-rebuild-plan.md` - Server-Neuaufbau Plan
- `deployment/ansible/inventory/production.yml` - Ansible Inventory
- `deployment/ansible/playbooks/initial-server-setup.yml` - Basis-Setup Playbook

View File

@@ -0,0 +1,315 @@
# Staging-Setup Test Plan
## Übersicht
Dieser Testplan beschreibt die Schritte zum Testen des neuen Staging-Setups mit separaten Datenbank-Stacks.
## Voraussetzungen
- Ansible installiert und konfiguriert
- SSH-Zugriff auf Production-Server
- Docker und Docker Compose auf Production-Server installiert
- Gitea Actions Runner läuft
## Quick-Start (Empfohlen)
Für schnelle Tests nutze das Quick-Start-Script:
```bash
# Auf Production-Server
cd ~/deployment
./scripts/staging-quick-start.sh
```
Das Script bietet ein interaktives Menü für alle häufigen Aufgaben.
## Test-Phasen
### Phase 1: PostgreSQL-Stacks testen
#### 1.1 PostgreSQL-Production Stack
```bash
# Auf Production-Server
cd ~/deployment/stacks/postgresql-production
# .env-Datei erstellen (falls nicht vorhanden)
cat > .env <<EOF
POSTGRES_DB=michaelschiemer
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<production-password>
BACKUP_RETENTION_DAYS=7
BACKUP_SCHEDULE=0 2 * * *
EOF
# Stack starten
docker compose up -d
# Verifizieren
docker compose ps
docker exec postgres-production pg_isready -U postgres -d michaelschiemer
# Erwartete Ausgabe: postgres-production:5432 - accepting connections
```
#### 1.2 PostgreSQL-Staging Stack
```bash
# Auf Production-Server
cd ~/deployment/stacks/postgresql-staging
# .env-Datei erstellen
cat > .env <<EOF
POSTGRES_DB=michaelschiemer_staging
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<staging-password>
BACKUP_RETENTION_DAYS=3
BACKUP_SCHEDULE=0 3 * * *
EOF
# Stack starten
docker compose up -d
# Verifizieren
docker compose ps
docker exec postgres-staging pg_isready -U postgres -d michaelschiemer_staging
# Erwartete Ausgabe: postgres-staging:5432 - accepting connections
```
### Phase 2: Networks verifizieren
```bash
# Prüfe, ob alle Networks existieren
docker network ls | grep -E "(traefik-public|staging-internal|postgres-staging-internal|postgres-production-internal|app-internal)"
# Erwartete Networks:
# - traefik-public
# - staging-internal
# - postgres-staging-internal
# - postgres-production-internal
# - app-internal
```
### Phase 3: Ansible-Setup testen
#### 3.1 Staging-Setup Playbook
```bash
# Lokal (auf Dev-Machine)
cd deployment/ansible
# Staging-Setup ausführen
ansible-playbook -i inventory/production.yml \
playbooks/setup-staging.yml \
--ask-vault-pass
# Erwartetes Ergebnis:
# - PostgreSQL-Staging Stack deployed
# - Staging Application Stack deployed
# - Alle Container laufen
```
#### 3.2 Verifizierung nach Ansible-Deployment
```bash
# Auf Production-Server
# Prüfe Container-Status
docker ps | grep -E "(staging|postgres-staging)"
# Prüfe Networks
docker network inspect postgres-staging-internal | grep -E "(staging-app|postgres-staging)"
# Prüfe Datenbank-Verbindung von Staging-App
docker exec staging-app php -r "
\$dsn = 'pgsql:host=postgres-staging;port=5432;dbname=michaelschiemer_staging';
\$pdo = new PDO(\$dsn, 'postgres', getenv('DB_PASSWORD'));
echo 'Connection successful: ' . \$pdo->query('SELECT version()')->fetchColumn();
"
```
### Phase 4: CI/CD-Workflow testen
#### 4.1 Test-Commit auf Staging-Branch
```bash
# Lokal
git checkout staging
git pull origin staging
# Kleine Änderung (z.B. Kommentar)
echo "# Test deployment" >> README.md
git add README.md
git commit -m "test: Test staging deployment with separate database"
git push origin staging
```
#### 4.2 Workflow-Verifizierung
1. **Gitea Actions prüfen**:
- Gehe zu: `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
- Prüfe, ob Workflow gestartet wurde
- Prüfe alle Jobs (Tests, Build, Deploy)
2. **Deployment-Verifizierung**:
```bash
# Auf Production-Server
# Prüfe, ob neues Image gepullt wurde
docker images | grep framework | head -5
# Prüfe Staging-Container
cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml ps
# Prüfe Logs
docker compose logs staging-app --tail=50
```
3. **Health-Checks**:
```bash
# Basic Health Check
curl -k https://staging.michaelschiemer.de/health
# Extended Health Check
curl -k https://staging.michaelschiemer.de/admin/health/api/summary
```
### Phase 5: Datenbank-Isolation verifizieren
#### 5.1 Separate Datenbanken testen
```bash
# Production-Datenbank
docker exec postgres-production psql -U postgres -d michaelschiemer -c "\dt"
# Staging-Datenbank
docker exec postgres-staging psql -U postgres -d michaelschiemer_staging -c "\dt"
# Erwartet: Beide Datenbanken existieren unabhängig voneinander
```
#### 5.2 Network-Isolation testen
```bash
# Prüfe, ob Staging-App auf Production-DB zugreifen kann (sollte NICHT möglich sein)
docker exec staging-app nc -zv postgres-production 5432
# Erwartet: Connection refused oder timeout (keine Verbindung möglich)
# Prüfe, ob Staging-App auf Staging-DB zugreifen kann (sollte möglich sein)
docker exec staging-app nc -zv postgres-staging 5432
# Erwartet: Connection successful
```
### Phase 6: Application-Funktionalität testen
#### 6.1 Web-Interface testen
1. **Staging-URL öffnen**: `https://staging.michaelschiemer.de`
2. **Erwartet**: Seite lädt korrekt
3. **Health-Dashboard prüfen**: `https://staging.michaelschiemer.de/admin/system/health`
4. **Erwartet**: Health-Checks zeigen alle Services als gesund
#### 6.2 Datenbank-Operationen testen
```bash
# Von Staging-App aus
docker exec staging-app php console.php db:status
# Erwartet: Migrations-Status wird angezeigt
# Test-Migration (falls nötig)
docker exec staging-app php console.php db:migrate
```
### Phase 7: Backup & Restore testen
#### 7.1 Staging-Backup testen
```bash
# Auf Production-Server
cd ~/deployment/stacks/postgresql-staging
# Manuelles Backup auslösen
docker exec postgres-staging-backup /scripts/backup.sh
# Backup verifizieren
ls -lh backups/
# Erwartet: Backup-Datei erstellt (z.B. postgres_michaelschiemer_staging_*.sql.gz)
```
#### 7.2 Production-Backup testen
```bash
# Auf Production-Server
cd ~/deployment/stacks/postgresql-production
# Manuelles Backup auslösen
docker exec postgres-production-backup /scripts/backup.sh
# Backup verifizieren
ls -lh backups/
```
## Fehlerbehebung
### Problem: Container startet nicht
```bash
# Prüfe Logs
docker compose logs <container-name>
# Prüfe Networks
docker network inspect <network-name>
# Prüfe Volumes
docker volume ls | grep <volume-name>
```
### Problem: Datenbank-Verbindung fehlgeschlagen
```bash
# Prüfe, ob Datenbank läuft
docker compose ps postgres-staging
# Prüfe Network-Verbindung
docker network inspect postgres-staging-internal | grep -A 5 staging-app
# Prüfe Environment-Variablen
docker exec staging-app printenv | grep DB_
```
### Problem: Health-Check fehlgeschlagen
```bash
# Prüfe Application-Logs
docker compose logs staging-app --tail=100
# Prüfe Nginx-Logs
docker compose logs staging-nginx --tail=100
# Prüfe Health-Endpoint direkt
docker exec staging-app curl -f http://localhost/health
```
## Erfolgskriterien
- ✅ PostgreSQL-Production Stack läuft
- ✅ PostgreSQL-Staging Stack läuft
- ✅ Staging-Application Stack läuft
- ✅ Datenbank-Verbindung funktioniert
- ✅ Network-Isolation funktioniert (Staging kann nicht auf Production-DB zugreifen)
- ✅ CI/CD-Workflow deployed erfolgreich
- ✅ Health-Checks erfolgreich
- ✅ Web-Interface funktioniert
- ✅ Backups funktionieren
## Nächste Schritte nach erfolgreichem Test
1. Production-Migration planen (falls nötig)
2. Monitoring für beide Datenbanken einrichten
3. Backup-Strategie verifizieren
4. Dokumentation finalisieren

View File

@@ -0,0 +1,299 @@
# Test Execution Plan - Staging Setup
## Übersicht
Dieser Plan beschreibt die schrittweise Ausführung der Tests für das neue Staging-Setup mit separaten Datenbank-Stacks.
## Voraussetzungen prüfen
### 1. Lokale Verifikation (WSL/Local)
```bash
# Syntax-Checks
cd /home/michael/dev/michaelschiemer
# Ansible-Playbook-Syntax (falls Ansible installiert)
ansible-playbook --syntax-check deployment/ansible/playbooks/verify-staging.yml
# Docker Compose-Syntax
docker compose -f deployment/stacks/postgresql-production/docker-compose.yml config > /dev/null
docker compose -f deployment/stacks/postgresql-staging/docker-compose.yml config > /dev/null
docker compose -f deployment/stacks/staging/docker-compose.base.yml -f deployment/stacks/staging/docker-compose.staging.yml config > /dev/null
```
### 2. Server-Verfügbarkeit
- SSH-Zugriff auf Production-Server
- Docker und Docker Compose installiert
- Ansible auf Control-Node installiert (optional)
## Test-Phasen
### Phase 1: Lokale Syntax-Verifikation
**Ziel**: Sicherstellen, dass alle Konfigurationsdateien syntaktisch korrekt sind.
**Schritte**:
1. ✅ Ansible-Playbook-Syntax prüfen
2. ✅ Docker Compose-Syntax prüfen
3. ✅ YAML-Validierung
4. ✅ Template-Syntax prüfen
**Erwartetes Ergebnis**: Alle Syntax-Checks erfolgreich
### Phase 2: PostgreSQL-Stacks testen (auf Server)
**Ziel**: Separate PostgreSQL-Stacks funktionieren korrekt.
#### 2.1 PostgreSQL-Production Stack
**Schritte**:
```bash
# Auf Production-Server
cd ~/deployment/stacks/postgresql-production
# .env-Datei prüfen/erstellen
cat .env # Sollte POSTGRES_PASSWORD enthalten
# Stack starten
docker compose up -d
# Status prüfen
docker compose ps
# Health-Check
docker exec postgres-production pg_isready -U postgres -d michaelschiemer
```
**Erwartetes Ergebnis**:
- Container läuft
- PostgreSQL akzeptiert Verbindungen
- Datenbank `michaelschiemer` existiert
#### 2.2 PostgreSQL-Staging Stack
**Schritte**:
```bash
# Auf Production-Server
cd ~/deployment/stacks/postgresql-staging
# .env-Datei prüfen/erstellen
cat .env # Sollte POSTGRES_PASSWORD enthalten
# Stack starten
docker compose up -d
# Status prüfen
docker compose ps
# Health-Check
docker exec postgres-staging pg_isready -U postgres -d michaelschiemer_staging
```
**Erwartetes Ergebnis**:
- Container läuft
- PostgreSQL akzeptiert Verbindungen
- Datenbank `michaelschiemer_staging` existiert
### Phase 3: Networks verifizieren
**Ziel**: Alle benötigten Docker-Networks existieren.
**Schritte**:
```bash
# Auf Production-Server
docker network ls | grep -E "(traefik-public|staging-internal|postgres-production-internal|postgres-staging-internal|app-internal)"
```
**Erwartetes Ergebnis**: Alle Networks existieren
**Falls fehlend**: Networks werden beim Stack-Start automatisch erstellt
### Phase 4: Ansible-Setup testen
**Ziel**: Ansible-Playbooks funktionieren korrekt.
#### 4.1 Staging-Setup ausführen
**Schritte**:
```bash
# Auf Control-Node (lokal in WSL)
cd ~/dev/michaelschiemer/deployment/ansible
# Dry-Run (Check-Mode)
ansible-playbook -i inventory/production.yml \
playbooks/setup-staging.yml \
--check \
--ask-vault-pass
# Echt ausführen
ansible-playbook -i inventory/production.yml \
playbooks/setup-staging.yml \
--ask-vault-pass
```
**Erwartetes Ergebnis**:
- Playbook läuft durch ohne Fehler
- PostgreSQL-Staging Stack deployed
- Staging Application Stack deployed
- Alle Services laufen
#### 4.2 Verifikations-Playbook ausführen
**Schritte**:
```bash
# Auf Control-Node
cd ~/dev/michaelschiemer/deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/verify-staging.yml
```
**Erwartetes Ergebnis**:
- Alle Verifikationen erfolgreich
- PostgreSQL-Staging: RUNNING
- staging-app: RUNNING
- Health-Checks: SUCCESS
### Phase 5: Datenbank-Verbindungen testen
**Ziel**: Application-Container können auf ihre jeweiligen Datenbanken zugreifen.
#### 5.1 Staging-Datenbank-Verbindung
**Schritte**:
```bash
# Auf Production-Server
docker exec staging-app php -r "
\$dsn = 'pgsql:host=postgres-staging;port=5432;dbname=michaelschiemer_staging';
\$pdo = new PDO(\$dsn, 'postgres', trim(file_get_contents('/var/www/html/storage/secrets/db_user_password')));
echo 'Connection successful: ' . \$pdo->query('SELECT version()')->fetchColumn();
"
```
**Erwartetes Ergebnis**: Connection successful mit PostgreSQL-Version
#### 5.2 Production-Datenbank-Verbindung
**Schritte**:
```bash
# Auf Production-Server
docker exec php php -r "
\$dsn = 'pgsql:host=postgres-production;port=5432;dbname=michaelschiemer';
\$pdo = new PDO(\$dsn, 'postgres', trim(file_get_contents('/var/www/html/storage/secrets/db_user_password')));
echo 'Connection successful: ' . \$pdo->query('SELECT version()')->fetchColumn();
"
```
**Erwartetes Ergebnis**: Connection successful mit PostgreSQL-Version
### Phase 6: Health-Checks
**Ziel**: Application-Endpoints sind erreichbar und funktionieren.
#### 6.1 Basic Health Check
**Schritte**:
```bash
# Staging
curl -f -k https://staging.michaelschiemer.de/health
# Production
curl -f -k https://michaelschiemer.de/health
```
**Erwartetes Ergebnis**: HTTP 200 OK
#### 6.2 Extended Health Check
**Schritte**:
```bash
# Staging
curl -f -k https://staging.michaelschiemer.de/admin/health/api/summary | jq .
# Production
curl -f -k https://michaelschiemer.de/admin/health/api/summary | jq .
```
**Erwartetes Ergebnis**: JSON mit `"overall_status": "healthy"`
### Phase 7: CI/CD-Workflow testen
**Ziel**: Automatisches Deployment funktioniert.
**Schritte**:
1. Kleine Änderung im Code vornehmen
2. Commit auf `staging`-Branch pushen
3. Gitea Actions Workflow beobachten
4. Nach erfolgreichem Deployment:
- Health-Check prüfen
- Code-Änderung verifizieren
**Erwartetes Ergebnis**:
- Workflow läuft erfolgreich durch
- Deployment erfolgreich
- Health-Checks bestehen
### Phase 8: Datenbank-Isolation testen
**Ziel**: Staging und Production haben getrennte Datenbanken.
**Schritte**:
```bash
# Auf Production-Server
# Test-Daten in Staging-DB schreiben
docker exec staging-app php -r "
\$dsn = 'pgsql:host=postgres-staging;port=5432;dbname=michaelschiemer_staging';
\$pdo = new PDO(\$dsn, 'postgres', trim(file_get_contents('/var/www/html/storage/secrets/db_user_password')));
\$pdo->exec('CREATE TABLE IF NOT EXISTS test_isolation (id SERIAL PRIMARY KEY, env VARCHAR(50))');
\$pdo->exec('INSERT INTO test_isolation (env) VALUES (\'staging\')');
echo 'Staging data inserted.';
"
# Prüfen, dass Test-Daten NICHT in Production-DB sind
docker exec postgres-production psql -U postgres -d michaelschiemer -c "SELECT * FROM test_isolation;" || echo "✅ Isolation confirmed: test_isolation table not in production"
```
**Erwartetes Ergebnis**:
- Test-Daten in Staging-DB vorhanden
- Test-Daten NICHT in Production-DB vorhanden
## Fehlerbehebung
### Häufige Probleme
1. **PostgreSQL-Container startet nicht**
- Prüfe `.env`-Datei (POSTGRES_PASSWORD gesetzt?)
- Prüfe Logs: `docker logs postgres-production` oder `docker logs postgres-staging`
- Prüfe Volumes: `docker volume ls`
2. **Network-Verbindung fehlgeschlagen**
- Prüfe Networks: `docker network ls`
- Prüfe Container-Networks: `docker inspect <container> | grep -A 10 Networks`
- Stelle sicher, dass Container im richtigen Network sind
3. **Datenbank-Verbindung fehlgeschlagen**
- Prüfe DB_HOST in Application-Container
- Prüfe DB_PASSWORD (Docker Secret)
- Prüfe Network-Verbindung (siehe oben)
4. **Health-Check fehlgeschlagen**
- Prüfe Container-Status: `docker ps`
- Prüfe Application-Logs: `docker logs staging-app`
- Prüfe Nginx-Logs: `docker logs staging-nginx`
## Test-Ergebnisse dokumentieren
Nach jedem Test:
- ✅ Erfolgreich
- ❌ Fehlgeschlagen (mit Fehlerbeschreibung)
- ⚠️ Teilweise erfolgreich (mit Details)
## Nächste Schritte nach erfolgreichen Tests
1. ✅ Alle Tests bestanden
2. Dokumentation aktualisieren (falls nötig)
3. Production-Deployment vorbereiten
4. Monitoring einrichten

View File

@@ -2,16 +2,40 @@
## Übersicht
Dieses Dokument erklärt, wie genau das Deployment in den Application Stack abläuft, wenn die CI/CD Pipeline ausgeführt wird.
Dieses Dokument erklärt, wie genau das Deployment in den Application Stack abläuft. Es gibt zwei Deployment-Szenarien:
1. **Initial Deployment** - Erstes Setup des Servers (Rsync-basiert)
2. **Normal Deployment** - Regelmäßige Deployments via CI/CD (Git-basiert)
**📖 Verwandte Dokumentation:**
- **[Initial Deployment Guide](../guides/initial-deployment-guide.md)** - Schritt-für-Schritt Initial Deployment
- **[Code Deployment Workflow](../guides/code-deployment-workflow.md)** - Unterschiede zwischen Rsync und Git
- **[Code Changes Workflow](../guides/code-change-workflow.md)** - Wie Codeänderungen gepusht werden
- **[CI/CD Status](../status/ci-cd-status.md)** - Aktueller Status der Pipeline
- **[Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)** - Häufige Probleme und Lösungen
---
## Deployment-Flow
### Initial Deployment (Rsync-basiert)
```
Local Repository
1. Code Sync via rsync (sync-application-code.yml)
2. Composer Dependencies installieren (install-composer-dependencies.yml)
3. Docker Image Build & Push (build-initial-image.yml)
4. Application Stack deployen (setup-infrastructure.yml)
5. Container starten und verifizieren
```
### Normal Deployment (Git-basiert / CI/CD)
```
CI/CD Pipeline (Gitea Actions)
@@ -19,9 +43,11 @@ CI/CD Pipeline (Gitea Actions)
2. Docker Image Build & Push zur Registry
3. Ansible Playbook ausführen
3. Code deployen via Git (deploy-application-code.yml)
4. Application Stack aktualisieren
4. Ansible Playbook ausführen (deploy-update.yml)
5. Application Stack aktualisieren
```
### Secret Handling für Redis
@@ -30,7 +56,7 @@ CI/CD Pipeline (Gitea Actions)
unter dem Schlüssel `vault_redis_password`.
- Die Application-Rolle (`roles/application/tasks/sync.yml`) bricht den Deploy ab,
wenn kein Passwort aus dem Vault oder via `-e redis_password=...` vorhanden ist.
- Während des Deployments wird das Passwort in `stacks/application/.env` geschrieben
- Während des Deployments wird das Passwort in `stacks/production/.env` geschrieben
und steht damit allen PHP-Containern über `REDIS_PASSWORD` zur Verfügung.
- Docker Secrets mit `REDIS_PASSWORD_FILE` werden weiterhin unterstützt, da der
Entry-Point das Secret lädt bevor PHP-FPM startet.
@@ -117,7 +143,7 @@ Das Ansible Playbook führt folgende Schritte auf dem Production-Server aus:
**3. Verzeichnisse erstellen**
```yaml
- Application Stack Path: ~/deployment/stacks/application
- Application Stack Path: ~/deployment/stacks/production
- Backup Verzeichnis: ~/deployment/backups/<timestamp>/
```
@@ -387,7 +413,7 @@ docker pull registry.michaelschiemer.de/framework:abc1234-1696234567
# Nachher: image: registry.michaelschiemer.de/framework:abc1234-1696234567
# 5. Stack neu starten
cd ~/deployment/stacks/application
cd ~/deployment/stacks/production
docker compose up -d --pull always --force-recreate --remove-orphans
# 6. Health-Checks warten
@@ -526,7 +552,7 @@ ansible-playbook -i inventory/production.yml \
```bash
# Logs prüfen
docker compose -f ~/deployment/stacks/application/docker-compose.yml logs
docker compose -f ~/deployment/stacks/production/docker-compose.yml logs
# Health-Check-Status prüfen
docker compose ps

View File

@@ -0,0 +1,493 @@
# Docker Compose Production Configuration
**Stand:** 2025-11-07
**Status:** Vollständige Dokumentation der Production-Konfiguration
---
## Übersicht
Dieses Dokument erklärt die Production-spezifische Docker Compose Konfiguration (`docker-compose.production.yml`). Diese Datei überschreibt die Basis-Konfiguration (`docker-compose.base.yml`) mit Production-spezifischen Einstellungen.
**📖 Verwandte Dokumentation:**
- [Application Stack Deployment](./application-stack.md) - Detaillierter Deployment-Ablauf
- [Initial Deployment Guide](../guides/initial-deployment-guide.md) - Schritt-für-Schritt Anleitung
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Häufige Probleme und Lösungen
---
## Verwendung
```bash
# Production Stack starten
docker compose -f docker-compose.base.yml -f docker-compose.production.yml up -d
# Mit .env Datei
docker compose -f docker-compose.base.yml -f docker-compose.production.yml --env-file .env up -d
```
**Wichtig:** Die Production-Konfiguration wird immer zusammen mit der Basis-Konfiguration verwendet.
---
## Security Settings
### Capabilities
**Web Container:**
```yaml
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- NET_BIND_SERVICE # Required for binding to ports 80/443
- SETGID # Required for PHP-FPM to switch to www-data
- SETUID # Required for PHP-FPM to switch to www-data
```
**PHP Container:**
```yaml
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
```
**Wichtig:** `SETGID` und `SETUID` sind für den `web` Container erforderlich, damit PHP-FPM zum `www-data` User (UID 33) wechseln kann.
**Trade-off:** `no-new-privileges: true` ist für den `web` Container **deaktiviert**, um PHP-FPM User Switching zu ermöglichen. Dies ist ein bewusster Security Trade-off.
### no-new-privileges
**Web Container:**
```yaml
# security_opt:
# - no-new-privileges:true # ← Kommentiert
```
**PHP Container:**
```yaml
security_opt:
- no-new-privileges:true # ← Aktiv
```
**Grund:** Der `web` Container benötigt Privilege Escalation für PHP-FPM, während der `php` Container nach dem User Switch (`gosu`) keine weiteren Privileges benötigt.
---
## Environment Variables
### env_file vs. environment
**env_file (Empfohlen):**
```yaml
env_file:
- /home/deploy/deployment/stacks/production/.env # ← Absoluter Pfad
```
**Wichtig:** **Immer absolute Pfade verwenden**, um sicherzustellen, dass die `.env` Datei gefunden wird, unabhängig vom Working Directory.
**environment (Override):**
```yaml
environment:
- APP_ENV=production
- APP_DEBUG=false
- PHP_MEMORY_LIMIT=512M
```
**Reihenfolge:** `env_file` wird zuerst geladen, dann werden `environment` Variablen als Override angewendet.
### Docker Secrets Integration
**Pattern:** `*_FILE` Environment Variables
```yaml
environment:
- DB_PASSWORD_FILE=/run/secrets/db_user_password
- REDIS_PASSWORD_FILE=/run/secrets/redis_password
- APP_KEY_FILE=/run/secrets/app_key
- VAULT_ENCRYPTION_KEY_FILE=/run/secrets/vault_encryption_key
secrets:
- db_user_password
- redis_password
- app_key
- vault_encryption_key
```
**Funktionsweise:**
1. Docker Secrets werden in `/run/secrets/<secret-name>` gemountet
2. Framework liest automatisch `*_FILE` Variablen und lädt den Inhalt
3. Secrets werden nie als Environment Variables exponiert
**Siehe auch:** [Application Stack Deployment](./application-stack.md) - Secret Handling
---
## Entrypoint Overrides
### Queue Worker
```yaml
queue-worker:
entrypoint: "" # ← Leerer Entrypoint überschreibt Image Entrypoint
command: ["php", "/var/www/html/worker.php"]
```
**Grund:** Der Image Entrypoint (`/usr/local/bin/entrypoint.sh`) startet PHP-FPM und Nginx. Der Queue Worker benötigt nur PHP CLI.
### Scheduler
```yaml
scheduler:
entrypoint: "" # ← Leerer Entrypoint überschreibt Image Entrypoint
command: php console.php scheduler:run
```
**Grund:** Gleicher Grund wie Queue Worker - nur PHP CLI erforderlich.
**Siehe auch:** [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Container Entrypoint Override
---
## Health Checks
### Web Container
```yaml
healthcheck:
test: ["CMD", "curl", "-f", "https://localhost/health"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
```
**Funktionsweise:**
- Prüft `/health` Endpoint via HTTPS
- Startet nach 30 Sekunden (Container Startup Time)
- Prüft alle 15 Sekunden
- 5 Retries bei Fehlschlag
### PHP Container
```yaml
healthcheck:
test: ["CMD", "php", "-v"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
```
**Funktionsweise:**
- Prüft PHP Verfügbarkeit
- Einfacher Check für Container-Health
### Scheduler
```yaml
healthcheck:
test: ["CMD-SHELL", "php -r 'exit(0);' && test -f /var/www/html/console.php || exit 1"]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
```
**Funktionsweise:**
- Prüft PHP Verfügbarkeit und `console.php` Existenz
- Längeres Interval (60s) da Scheduler weniger kritisch
---
## Volume Mounts
### Application Code
```yaml
volumes:
- /home/deploy/michaelschiemer/current:/var/www/html:rw
```
**Wichtig:**
- **Absoluter Pfad** auf dem Host
- **Read-Write** für `storage/` und `var/` Verzeichnisse
- Code wird via `rsync` oder `git` synchronisiert
**Siehe auch:** [Code Deployment Workflow](../guides/code-deployment-workflow.md)
### Certbot Volumes
```yaml
volumes:
- certbot-conf:/etc/letsencrypt:ro
- certbot-www:/var/www/certbot:ro
```
**Funktionsweise:**
- `certbot-conf`: SSL Zertifikate (Read-Only für Web Container)
- `certbot-www`: Webroot für Let's Encrypt Challenge
---
## Resource Limits
### Web Container
```yaml
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.5'
```
**Grund:** Nginx ist leichtgewichtig, benötigt wenig Ressourcen.
### PHP Container
```yaml
deploy:
resources:
limits:
memory: 1G
cpus: '2.0'
reservations:
memory: 512M
cpus: '1.0'
```
**Grund:** PHP-FPM benötigt mehr Ressourcen für Request-Verarbeitung.
### Queue Worker
```yaml
deploy:
resources:
limits:
memory: 2G
cpus: '2.0'
reservations:
memory: 1G
cpus: '1.0'
```
**Grund:** Queue Worker verarbeitet lange Jobs, benötigt mehr Memory.
### Scheduler
```yaml
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'
```
**Grund:** Scheduler läuft periodisch, benötigt wenig Ressourcen.
---
## Logging
### JSON Logging mit Rotation
```yaml
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
compress: "true"
labels: "service,environment"
```
**Funktionsweise:**
- **max-size:** Maximale Größe pro Log-Datei
- **max-file:** Anzahl der Log-Dateien (Rotation)
- **compress:** Komprimierung alter Log-Dateien
- **labels:** Metadaten für Log-Aggregation
**Beispiel:** Bei 5 Dateien à 10MB = max. 50MB Log-Speicher pro Container.
---
## Restart Policies
```yaml
restart: always
```
**Funktionsweise:**
- Container wird automatisch neu gestartet bei:
- Container Exit (auch bei Fehlern)
- Docker Daemon Restart
- System Reboot
**Alternative Policies:**
- `no`: Kein automatischer Restart
- `on-failure`: Nur bei Fehlern
- `unless-stopped`: Immer, außer manuell gestoppt
---
## Dependencies
### Service Dependencies
```yaml
depends_on:
php:
condition: service_healthy
certbot:
condition: service_started
```
**Funktionsweise:**
- `service_healthy`: Wartet auf erfolgreichen Health Check
- `service_started`: Wartet nur auf Container Start
**Wichtig:** `queue-worker` und `scheduler` warten auf `php` Container Health, da sie die gleiche Codebase verwenden.
---
## External Services
### PostgreSQL
```yaml
# Database service removed - using external PostgreSQL Stack
# Connection via app-internal network using docker-compose.postgres-override.yml
```
**Grund:** PostgreSQL läuft in separatem Stack (`deployment/stacks/postgresql/`) für bessere Isolation.
### Redis
```yaml
# Redis service removed - using external Redis Stack
# Connection via app-internal network using docker-compose.redis-override.yml
```
**Grund:** Redis läuft in separatem Stack (`deployment/stacks/redis/`) für bessere Isolation.
**Verbindung:** Via `app-internal` Network (siehe `docker-compose.base.yml`).
---
## Networks
### Cache Network
```yaml
networks:
cache:
internal: true # Cache network is internal in production
```
**Funktionsweise:**
- **Internal:** Keine externe Verbindung möglich
- Nur für Container-zu-Container Kommunikation
- Erhöht Security (Redis nicht von außen erreichbar)
---
## Best Practices
### 1. Absolute Pfade für env_file
**✅ Richtig:**
```yaml
env_file:
- /home/deploy/deployment/stacks/production/.env
```
**❌ Falsch:**
```yaml
env_file:
- .env # Relativer Pfad - funktioniert nur im richtigen Verzeichnis
```
### 2. Entrypoint Override für CLI-Container
**✅ Richtig:**
```yaml
queue-worker:
entrypoint: ""
command: ["php", "/var/www/html/worker.php"]
```
**❌ Falsch:**
```yaml
queue-worker:
# Kein Entrypoint Override - startet PHP-FPM/Nginx unnötig
```
### 3. Capabilities für PHP-FPM
**✅ Richtig:**
```yaml
web:
cap_add:
- SETGID
- SETUID
```
**❌ Falsch:**
```yaml
web:
security_opt:
- no-new-privileges:true # Verhindert PHP-FPM User Switching
```
---
## Troubleshooting
### Problem: Container startet nicht / unhealthy
**Lösung:** Siehe [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)
**Häufige Ursachen:**
- Missing Environment Variables → `env_file` mit absolutem Pfad prüfen
- PHP-FPM Permission Errors → Capabilities (SETGID/SETUID) prüfen
- Missing Application Code → Code-Sync prüfen
### Problem: Environment Variables werden nicht geladen
**Ursache:** Relativer Pfad in `env_file`
**Lösung:** Absoluten Pfad verwenden:
```yaml
env_file:
- /home/deploy/deployment/stacks/production/.env
```
### Problem: Queue Worker startet PHP-FPM
**Ursache:** Entrypoint Override fehlt
**Lösung:**
```yaml
queue-worker:
entrypoint: ""
command: ["php", "/var/www/html/worker.php"]
```
---
## Referenz
- [Application Stack Deployment](./application-stack.md) - Detaillierter Ablauf
- [Initial Deployment Guide](../guides/initial-deployment-guide.md) - Schritt-für-Schritt Anleitung
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Probleme und Lösungen
- [Code Deployment Workflow](../guides/code-deployment-workflow.md) - Code-Synchronisation

View File

@@ -0,0 +1,220 @@
# Server-Verzeichnisstruktur
## Übersicht
Auf dem Production-Server (`deploy@michaelschiemer`) existieren zwei Hauptverzeichnisse im Home-Verzeichnis:
```
/home/deploy/
├── deployment/ # Infrastructure-as-Code (24M)
└── michaelschiemer/ # Application Code (491M)
```
## Verzeichnis-Details
### `/home/deploy/deployment/` - Infrastructure Repository
**Zweck**: Enthält alle Deployment-Infrastruktur-Konfigurationen
**Inhalt**:
```
deployment/
├── stacks/ # Docker Compose Stacks
│ ├── traefik/ # Reverse Proxy & SSL
│ ├── gitea/ # Git Repository Server
│ ├── postgresql-production/
│ ├── postgresql-staging/
│ ├── production/ # Production Application Stack
│ ├── staging/ # Staging Application Stack
│ └── ...
└── backups/ # Backup-Dateien
```
**Verwendet von**:
- Ansible Playbooks für Infrastructure-Deployment
- Docker Compose für Container-Orchestrierung
- Traefik für Service Discovery
**Ansible Variable**:
```yaml
stacks_base_path: "/home/deploy/deployment/stacks"
```
**Verwendung in Playbooks**:
- `setup-infrastructure.yml` - Deployt alle Docker Stacks
- `backup.yml` - Erstellt Backups
- `sync-stacks.yml` - Synchronisiert Stack-Konfigurationen
---
### `/home/deploy/michaelschiemer/` - Application Repository
**Zweck**: Enthält den eigentlichen Application-Code (PHP, Composer, etc.)
**Inhalt**:
```
michaelschiemer/
├── current/ # Symlink → Aktuelle deployed Version
│ ├── src/ # PHP Source Code
│ ├── vendor/ # Composer Dependencies
│ ├── composer.json
│ ├── worker.php
│ └── console.php
├── .archive/ # Alte Versionen (Rollback)
├── backups/ # Application-spezifische Backups
└── ...
```
**Verwendet von**:
- Ansible Playbooks für Application-Deployment
- Docker Container (gemountet als Volume)
- PHP-FPM, Queue Workers, etc.
**Ansible Variable**:
```yaml
application_code_dest: "/home/deploy/michaelschiemer/current"
```
**Verwendung in Playbooks**:
- `deploy-application-code.yml` - Deployt neuen Application Code
- `sync-application-code.yml` - Synchronisiert Code
- `install-composer-dependencies.yml` - Installiert Dependencies
---
## Warum zwei Verzeichnisse?
### Trennung von Concerns
1. **Infrastructure** (`deployment/`)
- Ändert sich selten
- Wird von DevOps verwaltet
- Enthält Docker, Traefik, Datenbanken, etc.
2. **Application** (`michaelschiemer/`)
- Ändert sich häufig (bei jedem Deployment)
- Wird von Entwicklern verwaltet
- Enthält Business-Logic, PHP-Code, etc.
### Vorteile
- **Klarere Verantwortlichkeiten**: Infrastructure vs. Application
- **Einfacheres Backup**: Separate Backups für Infrastructure und Code
- **Bessere Skalierung**: Infrastructure kann unabhängig vom Code aktualisiert werden
- **Rollback-Möglichkeiten**: Alte Application-Versionen in `.archive/`
---
## Deployment-Workflow
### Infrastructure Deployment
```bash
# Infrastructure wird aus lokalem Repository deployed
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml \
--vault-password-file secrets/.vault_pass
```
**Was passiert**:
1. Ansible kopiert `deployment/stacks/` auf den Server
2. Docker Compose startet Container basierend auf Stack-Konfigurationen
3. Traefik entdeckt Services via Docker Labels
### Application Deployment
```bash
# Application Code wird aus Gitea deployed
ansible-playbook -i inventory/production.yml \
playbooks/deploy-application-code.yml \
--vault-password-file secrets/.vault_pass
```
**Was passiert**:
1. Ansible klont/pullt Code aus Gitea
2. Code wird nach `~/michaelschiemer/current/` deployed
3. Composer installiert Dependencies
4. Docker Container werden neu gestartet (mit neuem Code)
---
## Verzeichnis-Größen
```bash
# Aktuelle Größen (Stand: 2025-11-08)
24M /home/deploy/deployment # Infrastructure
491M /home/deploy/michaelschiemer # Application Code
```
**Hinweis**: Die Application ist größer, da sie Composer Dependencies (`vendor/`) enthält.
---
## Wartung
### Prüfen, ob beide Verzeichnisse existieren
```bash
ssh deploy@michaelschiemer.de
ls -la ~/deployment ~/michaelschiemer
```
### Prüfen, ob `current/` Symlink existiert
```bash
ls -la ~/michaelschiemer/current
# Sollte zeigen: current -> /path/to/version
```
### Verzeichnis-Größen prüfen
```bash
du -sh ~/deployment ~/michaelschiemer
```
---
## Troubleshooting
### Problem: `current/` Symlink fehlt
**Lösung**:
```bash
# Manuell erstellen oder Playbook ausführen
ansible-playbook -i inventory/production.yml \
playbooks/deploy-application-code.yml
```
### Problem: Verzeichnis zu groß
**Lösung**:
```bash
# Alte Versionen aufräumen
rm -rf ~/michaelschiemer/.archive/*
# Composer Cache leeren
rm -rf ~/michaelschiemer/cache/*
```
### Problem: Beide Verzeichnisse fehlen
**Lösung**:
```bash
# Infrastructure deployen
ansible-playbook -i inventory/production.yml \
playbooks/setup-infrastructure.yml
# Application deployen
ansible-playbook -i inventory/production.yml \
playbooks/deploy-application-code.yml
```
---
## Siehe auch
- [Deployment README](../README.md) - Übersicht über Deployment-Prozess
- [Ansible Playbooks](../ansible/playbooks/README.md) - Liste aller Playbooks
- [Backup Guide](guides/backup-and-rollback-guide.md) - Backup-Strategie

View File

@@ -90,20 +90,35 @@ Die Logs zeigen einige Verbindungsfehler (connection refused, 502 Bad Gateway),
### 3. Ansible Vault Password Handling
**Status**: ⚠️ Workflow nutzt Vault, aber kein Secret dafür
**Status**: Workflows verwenden ANSIBLE_VAULT_PASSWORD Secret
**Problem:**
- Der Workflow `update-production-secrets.yml` benötigt ein Vault-Passwort
- Aktuell wird es als Workflow-Input eingegeben (manuell)
- Für automatisiertes Deployment sollte es als Secret vorliegen
**Implementiert:**
- `ANSIBLE_VAULT_PASSWORD` wird als Gitea Secret verwendet
- ✅ Workflows erstellen automatisch Vault Password File aus Secret
- ✅ Fallback: Leeres Password File wenn Secret nicht gesetzt ist
**Lösung:**
- [ ] Optional: `ANSIBLE_VAULT_PASSWORD` als Secret hinzufügen (nur wenn automatisiert)
- [ ] Oder: Manuelles Eingeben beim Workflow-Trigger ist ausreichend
**Konfiguration:**
- Secret Name: `ANSIBLE_VAULT_PASSWORD`
- Verwendung: Workflows erstellen `/tmp/vault_pass` aus Secret
- Optional: Falls Secret nicht gesetzt, wird leeres Password File verwendet (für nicht-verschlüsselte Vaults)
---
### 4. Pipeline End-to-End testen
### 4. Code-Deployment Integration
**Status**: ✅ Code-Deployment via Ansible in Workflows integriert
**Implementiert:**
-`deploy-application-code.yml` wird in Workflows verwendet
-`install-composer-dependencies.yml` wird nach Code-Deployment ausgeführt
-`deploy-image.yml` wird für Image-Deployment verwendet
- ✅ Production Deployment Workflow verwendet Ansible statt direkter SSH-Befehle
**Workflows aktualisiert:**
-`.gitea/workflows/build-image.yml` - Staging & Production Auto-Deploy
-`.gitea/workflows/manual-deploy.yml` - Manuelles Deployment
### 5. Pipeline End-to-End testen
**Status**: ⚠️ Pipeline ist definiert, aber noch nicht getestet
@@ -144,6 +159,7 @@ Die Logs zeigen einige Verbindungsfehler (connection refused, 502 Bad Gateway),
- [x] `REGISTRY_USER` ✅
- [x] `REGISTRY_PASSWORD` ✅
- [x] `SSH_PRIVATE_KEY` ✅
- [x] `ANSIBLE_VAULT_PASSWORD` ✅ (für automatisiertes Deployment)
- [ ] `GITEA_TOKEN` (optional)
### Gitea Runner
@@ -153,14 +169,22 @@ Die Logs zeigen einige Verbindungsfehler (connection refused, 502 Bad Gateway),
- [x] Runner läuft (`docker compose up -d`) ✅
- [ ] Runner sichtbar in Gitea UI als "Idle" oder "Active" (bitte manuell prüfen)
### Code-Deployment Integration
- [x] `deploy-application-code.yml` in Workflows integriert ✅
- [x] `install-composer-dependencies.yml` in Workflows integriert ✅
- [x] `deploy-image.yml` in Workflows integriert ✅
- [x] Production Deployment Workflow auf Ansible umgestellt ✅
### Pipeline-Test
- [ ] Test-Commit gepusht oder Workflow manuell getriggert
- [ ] Alle Jobs erfolgreich:
- [ ] Tests
- [ ] Build
- [ ] Deploy
- [ ] Code-Deployment (Git)
- [ ] Composer Dependencies
- [ ] Image-Deployment
- [ ] Health-Check
- [ ] Deployment erfolgreich auf Production
- [ ] Health-Check erfolgreich
- [ ] Application läuft korrekt
### Dokumentation
@@ -180,7 +204,13 @@ Die Logs zeigen einige Verbindungsfehler (connection refused, 502 Bad Gateway),
**Status:** ✅ Abgeschlossen
- Runner läuft und ist registriert
### Phase 3: Pipeline-Test (NÄCHSTER SCHRITT)
### Phase 3: Code-Deployment Integration
**Status:** ✅ Abgeschlossen
- Code-Deployment via Ansible in Workflows integriert
- Production Deployment Workflow auf Ansible umgestellt
- Ansible Vault Password Handling implementiert
### Phase 4: Pipeline-Test (NÄCHSTER SCHRITT)
**Status:** ⚠️ Ausstehend
1. Test-Workflow ausführen
2. Fehler beheben falls notwendig
@@ -205,14 +235,25 @@ cp .env.example .env
docker compose up -d
```
### Pipeline manuell triggern (NÄCHSTER SCHRITT)
### Pipeline testen (NÄCHSTER SCHRITT)
**Vorbereitung:**
```bash
# Prüfe alle Voraussetzungen
./deployment/scripts/test-pipeline-prerequisites.sh
```
**Detaillierte Test-Anleitung:**
Siehe [Pipeline Test Checklist](../guides/pipeline-test-checklist.md) für Schritt-für-Schritt Anleitung.
**Pipeline manuell triggern:**
```
1. Gehe zu: https://git.michaelschiemer.de/michael/michaelschiemer/actions
2. Wähle: "Production Deployment Pipeline"
2. Wähle: "Build & Deploy Image"
3. Klicke: "Run workflow"
4. Wähle Branch: main
4. Wähle Branch: staging (für Staging-Test) oder main (für Production-Test)
5. Optionale Einstellungen:
- skip_tests: false (Tests sollen laufen)
- force_build: false (nur bei Bedarf)
6. Klicke: "Run workflow"
7. Beobachte Logs und prüfe jeden Schritt
```
@@ -228,12 +269,15 @@ https://git.michaelschiemer.de/admin/actions/runners
## ✅ Aktueller Status
**CI/CD Pipeline ist vollständig konfiguriert!**
**CI/CD Pipeline ist vollständig konfiguriert und integriert!**
- ✅ Secrets konfiguriert
- ✅ Runner läuft und ist registriert
- ✅ Workflows sind vorhanden
- ⚠️ **Nächster Schritt:** Pipeline testen!
- ✅ Code-Deployment via Ansible integriert
- ✅ Production Deployment Workflow auf Ansible umgestellt
- ✅ Ansible Vault Password Handling implementiert
- ⚠️ **Nächster Schritt:** Pipeline testen! (siehe [Pipeline Testing Guide](../guides/pipeline-testing-guide.md))
**Ready to Deploy:** Die Pipeline kann jetzt getestet werden. Alle Voraussetzungen sind erfüllt.

View File

@@ -0,0 +1,124 @@
# Gitea Cache Aktivierung - Status
**Datum:** 2025-01-XX
**Status:** ✅ Konfiguration abgeschlossen, Deployment ausstehend
## Durchgeführte Änderungen
### 1. docker-compose.yml angepasst
**Datei:** `deployment/stacks/gitea/docker-compose.yml`
**Änderungen:**
- `GITEA__cache__ENABLED=false``GITEA__cache__ENABLED=true`
- `GITEA__cache__ADAPTER=memory``GITEA__cache__ADAPTER=redis`
- Cache-spezifische Redis-Konfiguration hinzugefügt:
- `GITEA__cache__HOST=redis:6379`
- `GITEA__cache__PASSWORD=${REDIS_PASSWORD:-gitea_redis_password}`
- `GITEA__cache__DB=0`
**Vorher:**
```yaml
# Cache temporarily disabled (using memory) to debug Redis connection issue
- GITEA__cache__ENABLED=false
- GITEA__cache__ADAPTER=memory
```
**Nachher:**
```yaml
- GITEA__cache__ENABLED=true
- GITEA__cache__ADAPTER=redis
- GITEA__cache__HOST=redis:6379
- GITEA__cache__PASSWORD=${REDIS_PASSWORD:-gitea_redis_password}
- GITEA__cache__DB=0
```
### 2. Ansible Playbook erstellt
**Datei:** `deployment/ansible/playbooks/restart-gitea-with-cache.yml`
Das Playbook:
- Prüft ob Gitea Container existiert
- Erstellt Gitea Container mit neuer Cache-Konfiguration neu
- Wartet auf Gitea Health-Check
- Zeigt Erfolgsmeldung
## Nächste Schritte
### 1. Dateien auf Server synchronisieren
Die geänderte `docker-compose.yml` muss auf den Server synchronisiert werden:
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/sync-stacks.yml \
--vault-password-file secrets/.vault_pass
```
### 2. Gitea Container neu starten
Nach der Synchronisation Gitea mit neuer Cache-Konfiguration neu starten:
**Option A: Via Ansible Playbook**
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/restart-gitea-with-cache.yml \
--vault-password-file secrets/.vault_pass
```
**Option B: Manuell auf Server**
```bash
ssh deploy@94.16.110.151
cd ~/deployment/stacks/gitea
docker compose up -d --force-recreate gitea
```
### 3. Cache-Verbindung verifizieren
Nach dem Neustart prüfen:
```bash
# Gitea Logs prüfen
docker compose logs gitea | grep -i cache
# Redis-Verbindung testen
docker exec gitea-redis redis-cli -a $REDIS_PASSWORD ping
# Gitea Health-Check
curl -f https://git.michaelschiemer.de/api/healthz
```
## Erwartetes Ergebnis
Nach erfolgreichem Neustart sollte Gitea:
- ✅ Redis für Caching verwenden (statt Memory)
- ✅ Bessere Performance durch persistentes Caching
- ✅ Cache überlebt Container-Neustarts
- ✅ Keine Timeout-Probleme mehr durch Runner ohne Token
## Gitea Runner Status
**Wichtig:** Der Gitea Runner ist registriert, aber aktuell nicht gestartet. Das ist korrekt, da:
- Runner ohne Registration Token in Dauerschleife läuft
- Runner Gitea mit Requests bombardiert → Timeouts
- Runner sollte nur gestartet werden, wenn Token konfiguriert ist
**Status:**
- ✅ Runner ist registriert (`data/.runner` existiert)
- ✅ Registration Token ist in `.env` konfiguriert
- ⏸️ Runner Container sind gestoppt (korrekt, bis Deployment abgeschlossen)
**Runner starten (nach Cache-Aktivierung):**
```bash
cd deployment/gitea-runner
docker compose up -d
```
## Referenz
- [Gitea Cache Configuration](https://docs.gitea.io/en-us/config-cheat-sheet/#cache-cache)
- [Redis Configuration](https://docs.gitea.io/en-us/config-cheat-sheet/#cache-cache)
- [Gitea Runner Setup](../gitea-runner/README.md)

View File

@@ -0,0 +1,141 @@
# Implementation Summary - Pre-Deployment Checklist
## ✅ Abgeschlossen
### 1. Backup-Playbook
- **Status**: ✅ Implementiert
- **Datei**: `deployment/ansible/playbooks/backup.yml`
- **Features**:
- PostgreSQL Backup
- Application Data Backup (Storage, Logs)
- Gitea Data Backup
- Docker Registry Images Backup (optional)
- Automatische Backup-Rotation
- Backup-Verifizierung
### 2. Legacy-Cleanup
- **Status**: ✅ Abgeschlossen
- **Entfernt**:
- `deployment/wireguard-old/` - Alte WireGuard Playbooks
- `deployment/ansible/playbooks/build-and-push.yml` - Wird durch CI/CD ersetzt
- `deployment/ansible/playbooks/remove-framework-production-stack.yml` - Temporär
- `deployment/ansible/playbooks/remove-temporary-grafana-ip.yml` - Temporär
- **Dokumentiert**: `deployment/ansible/playbooks/README.md`
### 3. Dokumentations-Cleanup
- **Status**: ✅ Abgeschlossen
- **Erstellt**: `deployment/docs/tests/README.md` - Dokumentiert veraltete Test-Docs
- **Konsolidiert**: Test-Dokumentationen als historisch markiert
### 4. Health Checks erweitert
- **Status**: ✅ Implementiert
- **Workflow**: Erweiterte Health-Checks in CI/CD Pipeline
- **Endpoints**:
- `/health` - Basic Health Check
- `/admin/health/api/summary` - Extended Health Summary
- **Dokumentation**: `deployment/docs/guides/health-checks.md`
### 5. Security Hardening dokumentiert
- **Status**: ✅ Dokumentiert
- **Dokumentation**: `deployment/docs/guides/security-hardening.md`
- **Aktuell**: Firewall, WireGuard VPN, Unattended-Upgrades, Security Headers
- **Geplant**: SSH Hardening, Container Scanning, Secrets Rotation
## ⚠️ Ausstehend / Geplant
### 1. Pipeline End-to-End testen
- **Status**: ⚠️ Vorbereitet - Bereit zum Testen
- **Priorität**: KRITISCH
- **Test-Ressourcen erstellt:**
-`deployment/scripts/test-pipeline-prerequisites.sh` - Prüft alle Voraussetzungen
-`deployment/docs/guides/pipeline-test-checklist.md` - Detaillierte Schritt-für-Schritt Checkliste
- ✅ Dokumentation aktualisiert
- **Was zu tun**:
- Test-Commit auf `staging` Branch pushen
- Alle Workflow-Jobs verifizieren
- Deployment auf Staging verifizieren
- Health-Checks prüfen
- Application funktioniert korrekt
### 2. Zero-Downtime Deployment
- **Status**: ⚠️ Nicht implementiert
- **Priorität**: HOCH
- **Geplant**: Blue-Green oder Rolling Updates mit Health-Checks
### 3. Automatische Rollbacks
- **Status**: ⚠️ Rollback-Playbook vorhanden, aber nicht automatisch
- **Priorität**: HOCH
- **Geplant**: Automatischer Rollback bei fehlgeschlagenem Health-Check
### 4. Resource Limits & Performance
- **Status**: ⚠️ Teilweise vorhanden
- **Priorität**: MITTEL
- **Geplant**: Container Resource Limits, Performance Monitoring, Load Testing
### 5. Network Isolation & Segmentation
- **Status**: ⚠️ Basis vorhanden
- **Priorität**: MITTEL
- **Geplant**: Network Policy Verification, Service Communication Audit
### 6. SSL/TLS Configuration
- **Status**: ✅ Basis vorhanden
- **Priorität**: MITTEL
- **Zu prüfen**: Certificate Auto-Renewal, TLS Version Audit, Cipher Suite Audit
### 7. Monitoring & Alerting verbessern
- **Status**: ⚠️ Basis vorhanden
- **Priorität**: MITTEL
- **Geplant**: Application-Metriken, Custom Dashboards, Alerting Rules
### 8. Zentralisiertes Logging
- **Status**: ⚠️ Basis vorhanden
- **Priorität**: MITTEL
- **Geplant**: ELK/Loki Stack, Log-Aggregation, Search Interface
### 9. Secrets Management verbessern
- **Status**: ⚠️ Basis vorhanden
- **Priorität**: MITTEL
- **Geplant**: Rotation Policy, Audit Logging, Backup
## Nächste Schritte
### Vor erstem Production-Deployment
1. **Pipeline End-to-End testen** (KRITISCH)
- Prerequisites prüfen: `./deployment/scripts/test-pipeline-prerequisites.sh`
- Test-Commit auf `staging` pushen
- Alle Jobs verifizieren (siehe: `deployment/docs/guides/pipeline-test-checklist.md`)
- Health-Checks prüfen
2. **Backup-Playbook testen**
- Test-Backup ausführen: `./deployment/scripts/test-backup.sh`
- Backup-Verifizierung prüfen
- Restore-Test durchführen (optional)
3. **Security Audit**
- Firewall Rules prüfen
- SSH Hardening implementieren
- Container Scanning aktivieren
### Langfristige Verbesserungen
- Zero-Downtime Deployment
- Automatische Rollbacks
- Erweiterte Monitoring & Alerting
- Zentralisiertes Logging
- Secrets Rotation
## Zusammenfassung
**Abgeschlossen**: 5 von 15 geplanten Aufgaben
**In Arbeit**: 0 von 15 Aufgaben
**Ausstehend**: 10 von 15 Aufgaben
**Kritische Aufgaben vor Deployment**:
1. ✅ Backup-Playbook (abgeschlossen)
2. ✅ Health Checks erweitert (abgeschlossen)
3. ⚠️ Pipeline End-to-End testen (ausstehend)
4. ⚠️ Zero-Downtime Deployment (geplant)
**Status**: Bereit für Staging-Tests, Production-Deployment erfordert noch End-to-End-Tests.

View File

@@ -0,0 +1,114 @@
# CI/CD Pipeline Test Status
**Datum:** 2025-01-XX
**Status:** ⚠️ Teilweise abgeschlossen - Push fehlgeschlagen
## Durchgeführte Schritte
### ✅ Phase 0: Gitea Caching aktivieren
- **Status:** ✅ Abgeschlossen
- **Änderungen:** `deployment/stacks/gitea/docker-compose.yml` angepasst
- **Cache-Konfiguration:** Redis aktiviert (statt Memory)
- **Playbook erstellt:** `deployment/ansible/playbooks/restart-gitea-with-cache.yml`
- **Nächster Schritt:** Dateien auf Server synchronisieren und Gitea neu starten
### ✅ Phase 1: Prerequisites prüfen
- **Status:** ✅ Abgeschlossen
- **Prerequisites Script:** Ausgeführt
- **Gitea Runner:** Registriert, aber nicht gestartet (korrekt, da Token konfiguriert ist)
- **Gitea Secrets:** Laut Dokumentation bereits konfiguriert
### ⚠️ Phase 2: Staging Pipeline Test
- **Status:** ⚠️ Teilweise abgeschlossen
- **Test-Commit:** ✅ Erstellt (`test: CI/CD pipeline staging test`)
- **Push:** ❌ Fehlgeschlagen (504 Error)
- **Fehler:** `fatal: unable to access 'https://git.michaelschiemer.de/admin/michaelschiemer.git/': The requested URL returned error: 504`
## Bekannte Probleme
### 1. Git Push 504 Error
**Symptom:**
```
fatal: unable to access 'https://git.michaelschiemer.de/admin/michaelschiemer.git/': The requested URL returned error: 504
```
**Mögliche Ursachen:**
1. **Gitea-Überlastung:** Runner ohne Token bombardiert Gitea mit Requests
2. **Server-Überlastung:** Server ist temporär überlastet
3. **Netzwerk-Problem:** Verbindungsprobleme zum Server
**Lösungsansätze:**
1. **Gitea Caching aktivieren:** Redis-Cache sollte Performance verbessern
2. **Runner Status prüfen:** Sicherstellen, dass Runner nur mit Token läuft
3. **Gitea Logs prüfen:** Server-Logs auf Fehler prüfen
4. **Retry:** Push später erneut versuchen
### 2. Gitea Runner ohne Token
**Problem:** Runner ohne Registration Token läuft in Dauerschleife und bombardiert Gitea mit Requests, was zu Timeouts führt.
**Lösung:**
- ✅ Runner ist registriert (`data/.runner` existiert)
- ✅ Registration Token ist in `.env` konfiguriert
- ⏸️ Runner Container sind gestoppt (korrekt, bis Deployment abgeschlossen)
**Runner starten (nach Cache-Aktivierung):**
```bash
cd deployment/gitea-runner
docker compose up -d
```
## Nächste Schritte
### 1. Gitea Caching aktivieren (Priorität: Hoch)
Die geänderte `docker-compose.yml` muss auf den Server synchronisiert werden:
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/sync-stacks.yml \
--vault-password-file secrets/.vault_pass
```
Dann Gitea neu starten:
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/restart-gitea-with-cache.yml \
--vault-password-file secrets/.vault_pass
```
### 2. Git Push erneut versuchen
Nach erfolgreicher Cache-Aktivierung und Gitea-Neustart:
```bash
cd /home/michael/dev/michaelschiemer
git push origin staging
```
### 3. Pipeline beobachten
Nach erfolgreichem Push:
- Gitea Actions UI: `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
- Jobs beobachten: `changes`, `test`, `build`, `deploy-staging`
- Deployment verifizieren
### 4. Production Pipeline Test
Nach erfolgreichem Staging-Test:
- Test-Commit auf `main` Branch erstellen
- Push zu `main`
- Production Pipeline beobachten
- Deployment verifizieren
## Referenz
- [Gitea Cache Aktivierung](./gitea-cache-activation.md)
- [Pipeline Test Checklist](../guides/pipeline-test-checklist.md)
- [Pipeline Testing Guide](../guides/pipeline-testing-guide.md)
- [CI/CD Status](./ci-cd-status.md)

View File

@@ -0,0 +1,168 @@
# Staging-Implementation Status
**Datum**: 2025-01-31
**Status**: ✅ Implementierung abgeschlossen - Bereit für Tests
## ✅ Abgeschlossene Aufgaben
### Phase 1: Separate Datenbank-Stacks ✅
-`deployment/stacks/postgresql-production/` erstellt
- `docker-compose.yml` mit postgres-production Container
- `README.md` mit vollständiger Dokumentation
- Separate Networks (`postgres-production-internal`)
- Separate Volumes (`postgres-production-data`)
- Backup-Konfiguration
-`deployment/stacks/postgresql-staging/` erstellt
- `docker-compose.yml` mit postgres-staging Container
- `README.md` mit vollständiger Dokumentation
- Separate Networks (`postgres-staging-internal`)
- Separate Volumes (`postgres-staging-data`)
- Backup-Konfiguration (kürzere Retention: 3 Tage)
### Phase 2: Application-Stacks angepasst ✅
-`docker-compose.staging.yml` aktualisiert
- `DB_HOST=postgres-staging`
- Network `postgres-staging-internal` hinzugefügt
- Alle Services (staging-app, staging-queue-worker, staging-scheduler) verbunden
-`docker-compose.postgres-override.yml` aktualisiert
- Network `postgres-production-internal` für Production
- Services (php, queue-worker, scheduler) verbunden
-`docker-compose.staging-postgres-override.yml` aktualisiert
- Network `postgres-staging-internal` für Staging
### Phase 3: Ansible-Integration ✅
-`deployment/ansible/roles/postgresql-production/` erstellt
- Tasks für Production-Datenbank-Deployment
- Separate Variablen und Defaults
-`deployment/ansible/roles/postgresql-staging/` erstellt
- Tasks für Staging-Datenbank-Deployment
- Separate Variablen und Defaults
-`deployment/ansible/playbooks/setup-staging.yml` erstellt
- Deployed PostgreSQL-Staging Stack
- Deployed Staging Application Stack
- Verifizierung und Health-Checks
-`deployment/ansible/inventory/group_vars/staging/vars.yml` erstellt
- Staging-spezifische Variablen
- `db_host_default: "postgres-staging"`
- `db_name_default: "michaelschiemer_staging"`
-`deployment/ansible/playbooks/setup-infrastructure.yml` erweitert
- Production-Stack-Deployment mit korrekten Variablen
- Nutzt `postgresql-production` Role
### Phase 4: CI/CD-Workflow ✅
- ✅ Workflow bereits vorhanden (`.gitea/workflows/build-image.yml`)
- ✅ Health-Checks erweitert für beide Environments
- ✅ Keine Änderungen nötig - nutzt bereits korrekte Konfiguration
### Phase 5: Dokumentation ✅
-`deployment/stacks/postgresql-production/README.md` erstellt
-`deployment/stacks/postgresql-staging/README.md` erstellt
-`deployment/stacks/staging/README.md` aktualisiert
-`deployment/stacks/production/README.md` aktualisiert
-`deployment/docs/guides/migrate-to-separate-databases.md` erstellt
-`deployment/docs/guides/staging-test-plan.md` erstellt
-`deployment/docs/guides/production-database-connection.md` erstellt
-`deployment/docs/guides/deployment-commands.md` aktualisiert
### Phase 6: Code-Anpassungen ✅
-`deployment/ansible/templates/application.env.j2` aktualisiert
- Automatische DB_HOST-Erkennung basierend auf `app_env`
- Unterstützt `db_host_default` Variable
-`deployment/ansible/roles/application/tasks/sync.yml` erweitert
- Separate Passwort-Extraktion für Production/Staging
- `db_host` und `app_env` Variablen für Template
-`deployment/ansible/inventory/group_vars/production/vars.yml` erweitert
- `db_host_default: "postgres-production"` hinzugefügt
## ⚠️ Ausstehend: Testing
### Phase 6: Testing & Verifikation
-**Staging-End-to-End-Test** (NÄCHSTER SCHRITT)
- [ ] PostgreSQL-Staging Stack auf Server starten
- [ ] Staging-Application Stack deployen
- [ ] Datenbank-Verbindung testen
- [ ] Application funktioniert korrekt
- [ ] Health-Checks erfolgreich
-**Production-Verifikation**
- [ ] Production-Stack nutzt `postgres-production`
- [ ] Migration von alter Datenbank (falls nötig)
- [ ] Rollback-Plan testen
## 📋 Test-Checkliste
### Vor dem Testen
- [ ] SSH-Zugriff auf Production-Server
- [ ] Ansible installiert und konfiguriert
- [ ] Docker und Docker Compose auf Server installiert
- [ ] Gitea Actions Runner läuft
- [ ] Vault-Passwort verfügbar (für Ansible)
### Während des Testens
- [ ] PostgreSQL-Production Stack startet erfolgreich
- [ ] PostgreSQL-Staging Stack startet erfolgreich
- [ ] Networks werden korrekt erstellt
- [ ] Application-Container können Datenbank erreichen
- [ ] Health-Checks funktionieren
- [ ] CI/CD-Workflow deployed erfolgreich
### Nach dem Testen
- [ ] Alle Container laufen stabil
- [ ] Datenbank-Isolation funktioniert (Staging kann nicht auf Production-DB zugreifen)
- [ ] Backups funktionieren für beide Datenbanken
- [ ] Monitoring zeigt beide Datenbanken an
## 🚀 Nächste Schritte
1. **Testen auf Server** (siehe `deployment/docs/guides/staging-test-plan.md`)
- Phase 1: PostgreSQL-Stacks manuell starten
- Phase 2: Networks verifizieren
- Phase 3: Ansible-Setup ausführen
- Phase 4: CI/CD-Workflow testen
2. **Production-Migration** (falls nötig)
- Backup erstellen
- Datenbank migrieren
- Application-Stack aktualisieren
3. **Monitoring einrichten**
- Beide Datenbanken überwachen
- Alerts konfigurieren
## 📊 Implementierungs-Statistik
- **Erstellte Dateien**: 21
- **Geänderte Dateien**: 10+
- **Dokumentations-Seiten**: 5
- **Ansible-Roles**: 2 neue
- **Docker Compose Stacks**: 2 neue
## ✅ Erfolgskriterien
- ✅ Separate Datenbank-Stacks erstellt
- ✅ Network-Isolation konfiguriert
- ✅ Ansible-Integration vollständig
- ✅ Dokumentation komplett
- ⏳ Tests erfolgreich (ausstehend)
**Status**: Bereit für Deployment und Tests! 🚀

View File

@@ -0,0 +1,26 @@
# Test-Dokumentation
Dieses Verzeichnis enthält historische Test-Dokumentationen für verschiedene Deployment-Szenarien.
## Status
Die meisten Dokumentationen in diesem Verzeichnis sind **veraltet** und beziehen sich auf alte Deployment-Pfade (`stacks/application` statt `stacks/production`).
## Aktuelle Test-Prozesse
Für aktuelle Test-Prozesse siehe:
- **[deployment/docs/guides/deployment-commands.md](../guides/deployment-commands.md)** - Aktuelle Deployment-Befehle
- **[deployment/README.md](../../README.md)** - Haupt-Dokumentation mit Quick Start
## Historische Dokumentationen
Die folgenden Dateien sind historisch und können als Referenz dienen:
- `quick-test.md` - Schnelle Test-Anleitung (veraltet)
- `git-deployment-test.md` - Git-Deployment Tests (veraltet)
- `test-git-deployment.md` - Weitere Git-Deployment Tests (veraltet)
- `git-deployment-issue.md` - Problem-Dokumentation (veraltet)
- `recommended-test-flow.md` - Empfohlener Test-Workflow (veraltet)
- `test-results.md` - Test-Ergebnisse (veraltet)
**Hinweis:** Diese Dokumentationen verweisen auf alte Pfade und sollten nicht mehr direkt verwendet werden.