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