fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
161
deployment/docs/guides/ansible-vs-bash-scripts.md
Normal file
161
deployment/docs/guides/ansible-vs-bash-scripts.md
Normal 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.
|
||||
|
||||
362
deployment/docs/guides/backup-and-rollback-guide.md
Normal file
362
deployment/docs/guides/backup-and-rollback-guide.md
Normal 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
|
||||
|
||||
347
deployment/docs/guides/cicd-workflow-guide.md
Normal file
347
deployment/docs/guides/cicd-workflow-guide.md
Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
339
deployment/docs/guides/code-deployment-workflow.md
Normal file
339
deployment/docs/guides/code-deployment-workflow.md
Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
94
deployment/docs/guides/health-checks.md
Normal file
94
deployment/docs/guides/health-checks.md
Normal 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
|
||||
```
|
||||
|
||||
238
deployment/docs/guides/initial-deployment-guide.md
Normal file
238
deployment/docs/guides/initial-deployment-guide.md
Normal 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
|
||||
|
||||
247
deployment/docs/guides/manual-server-test.md
Normal file
247
deployment/docs/guides/manual-server-test.md
Normal 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
|
||||
|
||||
286
deployment/docs/guides/migrate-to-separate-databases.md
Normal file
286
deployment/docs/guides/migrate-to-separate-databases.md
Normal 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`
|
||||
|
||||
144
deployment/docs/guides/os-selection.md
Normal file
144
deployment/docs/guides/os-selection.md
Normal 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`
|
||||
356
deployment/docs/guides/pipeline-test-checklist.md
Normal file
356
deployment/docs/guides/pipeline-test-checklist.md
Normal 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`
|
||||
|
||||
214
deployment/docs/guides/pipeline-test-steps.md
Normal file
214
deployment/docs/guides/pipeline-test-steps.md
Normal 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
|
||||
|
||||
298
deployment/docs/guides/pipeline-testing-guide.md
Normal file
298
deployment/docs/guides/pipeline-testing-guide.md
Normal 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
|
||||
|
||||
162
deployment/docs/guides/production-database-connection.md
Normal file
162
deployment/docs/guides/production-database-connection.md
Normal 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`
|
||||
|
||||
@@ -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
|
||||
|
||||
143
deployment/docs/guides/security-hardening.md
Normal file
143
deployment/docs/guides/security-hardening.md
Normal 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`
|
||||
|
||||
428
deployment/docs/guides/server-rebuild-plan.md
Normal file
428
deployment/docs/guides/server-rebuild-plan.md
Normal 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
|
||||
218
deployment/docs/guides/ssh-access.md
Normal file
218
deployment/docs/guides/ssh-access.md
Normal 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
|
||||
315
deployment/docs/guides/staging-test-plan.md
Normal file
315
deployment/docs/guides/staging-test-plan.md
Normal 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
|
||||
|
||||
299
deployment/docs/guides/test-execution-plan.md
Normal file
299
deployment/docs/guides/test-execution-plan.md
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user