Update Docker Registry URLs to HTTPS endpoint (registry.michaelschiemer.de)

- Replace git.michaelschiemer.de:5000 (HTTP) with registry.michaelschiemer.de (HTTPS)
- Update all Ansible playbooks and configuration files
- Update CI/CD workflows to use HTTPS registry endpoint
- Update Docker Compose files with new registry URL
- Update documentation and scripts

Benefits:
- Secure HTTPS connection (no insecure registry config needed)
- Consistent use of HTTPS endpoint via Traefik
- Better security practices for production deployment
This commit is contained in:
2025-10-31 14:35:39 +01:00
parent 82fb65eb00
commit c087d372c2
24 changed files with 1341 additions and 217 deletions

View File

@@ -20,7 +20,7 @@ bash scripts/prepare-secrets.sh
**Hinweis**: Alle Secrets müssen in Gitea konfiguriert werden, bevor die Pipeline läuft. **Hinweis**: Alle Secrets müssen in Gitea konfiguriert werden, bevor die Pipeline läuft.
### 2. Docker Registry ✅ ### 2. Docker Registry ✅
- ✅ Registry läuft auf `git.michaelschiemer.de:5000` - ✅ Registry läuft auf `registry.michaelschiemer.de`
- ✅ Authentifizierung konfiguriert (admin/registry-secure-password-2025) - ✅ Authentifizierung konfiguriert (admin/registry-secure-password-2025)
- ✅ Erreichbar via HTTP auf `127.0.0.1:5000` - ✅ Erreichbar via HTTP auf `127.0.0.1:5000`
- ✅ Image `framework` bereits vorhanden - ✅ Image `framework` bereits vorhanden

View File

@@ -2,7 +2,7 @@
## Registry Details ## Registry Details
- **URL**: `git.michaelschiemer.de:5000` (intern) oder `registry.michaelschiemer.de` (via Traefik) - **URL**: `registry.michaelschiemer.de` (intern) oder `registry.michaelschiemer.de` (via Traefik)
- **Standard Credentials**: - **Standard Credentials**:
- **Username**: `admin` - **Username**: `admin`
- **Password**: `registry-secure-password-2025` - **Password**: `registry-secure-password-2025`
@@ -20,10 +20,10 @@ Verwende folgende Werte in den Gitea Repository Secrets:
```bash ```bash
# Login testen # Login testen
echo "registry-secure-password-2025" | docker login git.michaelschiemer.de:5000 -u admin --password-stdin echo "registry-secure-password-2025" | docker login registry.michaelschiemer.de -u admin --password-stdin
# Images auflisten # Images auflisten
curl -u admin:registry-secure-password-2025 http://git.michaelschiemer.de:5000/v2/_catalog curl -u admin:registry-secure-password-2025 http://registry.michaelschiemer.de/v2/_catalog
# Oder via Traefik (HTTPS) # Oder via Traefik (HTTPS)
curl -u admin:registry-secure-password-2025 https://registry.michaelschiemer.de/v2/_catalog curl -u admin:registry-secure-password-2025 https://registry.michaelschiemer.de/v2/_catalog

View File

@@ -14,7 +14,7 @@ Diese Secrets müssen in Gitea konfiguriert werden unter:
### 2. REGISTRY_PASSWORD ### 2. REGISTRY_PASSWORD
- **Beschreibung**: Passwort für Docker Registry Login - **Beschreibung**: Passwort für Docker Registry Login
- **Typ**: Password (versteckt) - **Typ**: Password (versteckt)
- **Wert**: Das Passwort für die Docker Registry auf `git.michaelschiemer.de:5000` - **Wert**: Das Passwort für die Docker Registry auf `registry.michaelschiemer.de`
- **Verwendung**: Docker Registry Authentication beim Image Push - **Verwendung**: Docker Registry Authentication beim Image Push
### 3. SSH_PRIVATE_KEY ### 3. SSH_PRIVATE_KEY

View File

@@ -18,7 +18,7 @@ on:
type: boolean type: boolean
env: env:
REGISTRY: git.michaelschiemer.de:5000 REGISTRY: registry.michaelschiemer.de
IMAGE_NAME: framework IMAGE_NAME: framework
DEPLOYMENT_HOST: 94.16.110.151 DEPLOYMENT_HOST: 94.16.110.151
@@ -248,10 +248,9 @@ jobs:
chmod 600 ~/.ssh/production chmod 600 ~/.ssh/production
ssh-keyscan -H ${{ env.DEPLOYMENT_HOST }} >> ~/.ssh/known_hosts ssh-keyscan -H ${{ env.DEPLOYMENT_HOST }} >> ~/.ssh/known_hosts
- name: Install Ansible # Ansible is pre-installed in php-ci image
run: | - name: Verify Ansible installation
apt-get update run: ansible --version
apt-get install -y ansible
- name: Deploy via Ansible - name: Deploy via Ansible
run: | run: |

View File

@@ -43,9 +43,9 @@ CI/CD Pipeline (Gitea Actions)
```yaml ```yaml
- Docker Image Build (Dockerfile.production) - Docker Image Build (Dockerfile.production)
- Image mit Tags pushen: - Image mit Tags pushen:
- git.michaelschiemer.de:5000/framework:latest - registry.michaelschiemer.de/framework:latest
- git.michaelschiemer.de:5000/framework:<tag> - registry.michaelschiemer.de/framework:<tag>
- git.michaelschiemer.de:5000/framework:git-<short-sha> - registry.michaelschiemer.de/framework:git-<short-sha>
``` ```
#### Job 3: Deploy (Ansible) #### Job 3: Deploy (Ansible)
@@ -121,7 +121,7 @@ docker compose -f ~/deployment/stacks/application/docker-compose.yml \
**2. Docker Registry Login** **2. Docker Registry Login**
```bash ```bash
# Login zur privaten Registry mit Credentials # Login zur privaten Registry mit Credentials
docker login git.michaelschiemer.de:5000 \ docker login registry.michaelschiemer.de \
-u <registry-username> \ -u <registry-username> \
-p <registry-password> -p <registry-password>
``` ```
@@ -129,10 +129,10 @@ docker login git.michaelschiemer.de:5000 \
**3. Neues Image Pullen** **3. Neues Image Pullen**
```bash ```bash
# Pullt das neue Image von der Registry # Pullt das neue Image von der Registry
docker pull git.michaelschiemer.de:5000/framework:<tag> docker pull registry.michaelschiemer.de/framework:<tag>
# Beispiel: # Beispiel:
# git.michaelschiemer.de:5000/framework:abc1234-1696234567 # registry.michaelschiemer.de/framework:abc1234-1696234567
``` ```
**4. docker-compose.yml aktualisieren** **4. docker-compose.yml aktualisieren**
@@ -143,12 +143,12 @@ docker pull git.michaelschiemer.de:5000/framework:<tag>
# Vorher: # Vorher:
services: services:
app: app:
image: git.michaelschiemer.de:5000/framework:latest image: registry.michaelschiemer.de/framework:latest
# Nachher (wenn image_tag != 'latest'): # Nachher (wenn image_tag != 'latest'):
services: services:
app: app:
image: git.michaelschiemer.de:5000/framework:<tag> image: registry.michaelschiemer.de/framework:<tag>
``` ```
**Regex-Replace:** **Regex-Replace:**
@@ -158,13 +158,13 @@ replace: '\1{{ app_image }}:{{ image_tag }}'
``` ```
**Betroffene Services (werden alle aktualisiert):** **Betroffene Services (werden alle aktualisiert):**
- `app` (PHP-FPM) - Zeile 6: `image: git.michaelschiemer.de:5000/framework:latest` - `app` (PHP-FPM) - Zeile 6: `image: registry.michaelschiemer.de/framework:latest`
- `queue-worker` (Queue Worker) - Zeile 120: `image: git.michaelschiemer.de:5000/framework:latest` - `queue-worker` (Queue Worker) - Zeile 120: `image: registry.michaelschiemer.de/framework:latest`
- `scheduler` (Scheduler) - Zeile 165: `image: git.michaelschiemer.de:5000/framework:latest` - `scheduler` (Scheduler) - Zeile 165: `image: registry.michaelschiemer.de/framework:latest`
**Hinweis:** **Hinweis:**
- Alle drei Services verwenden das gleiche Image, daher werden alle mit dem neuen Tag aktualisiert - Alle drei Services verwenden das gleiche Image, daher werden alle mit dem neuen Tag aktualisiert
- Der Regex matched **alle Zeilen** die mit `image: git.michaelschiemer.de:5000/framework:` beginnen - Der Regex matched **alle Zeilen** die mit `image: registry.michaelschiemer.de/framework:` beginnen
- `nginx` und `redis` bleiben unverändert (verwenden andere Images) - `nginx` und `redis` bleiben unverändert (verwenden andere Images)
**5. Application Stack neu starten** **5. Application Stack neu starten**
@@ -216,7 +216,7 @@ docker compose ps --format json | \
Deployment Timestamp: 2025-10-31T02:35:04Z Deployment Timestamp: 2025-10-31T02:35:04Z
Git Commit: abc1234... Git Commit: abc1234...
Image Tag: abc1234-1696234567 Image Tag: abc1234-1696234567
Deployed Image: git.michaelschiemer.de:5000/framework:abc1234-1696234567 Deployed Image: registry.michaelschiemer.de/framework:abc1234-1696234567
Image Pull: SUCCESS Image Pull: SUCCESS
Stack Deploy: UPDATED Stack Deploy: UPDATED
Health Status: All services healthy Health Status: All services healthy
@@ -238,7 +238,7 @@ Der Application Stack besteht aus mehreren Services:
#### Services im Stack #### Services im Stack
**1. `app` (PHP-FPM Application)** **1. `app` (PHP-FPM Application)**
- Image: `git.michaelschiemer.de:5000/framework:<tag>` - Image: `registry.michaelschiemer.de/framework:<tag>`
- Container: `app` - Container: `app`
- Health Check: `php-fpm-healthcheck` - Health Check: `php-fpm-healthcheck`
- Netzwerk: `app-internal` - Netzwerk: `app-internal`
@@ -259,7 +259,7 @@ Der Application Stack besteht aus mehreren Services:
- Netzwerk: `app-internal` - Netzwerk: `app-internal`
**4. `queue-worker` (Background Jobs)** **4. `queue-worker` (Background Jobs)**
- Image: `git.michaelschiemer.de:5000/framework:<tag>` (gleiches wie app) - Image: `registry.michaelschiemer.de/framework:<tag>` (gleiches wie app)
- Container: `queue-worker` - Container: `queue-worker`
- Health Check: `pgrep -f 'queue:work'` - Health Check: `pgrep -f 'queue:work'`
- Netzwerk: `app-internal` - Netzwerk: `app-internal`
@@ -267,7 +267,7 @@ Der Application Stack besteht aus mehreren Services:
- Abhängigkeiten: `app`, `redis` - Abhängigkeiten: `app`, `redis`
**5. `scheduler` (Cron Jobs)** **5. `scheduler` (Cron Jobs)**
- Image: `git.michaelschiemer.de:5000/framework:<tag>` (gleiches wie app) - Image: `registry.michaelschiemer.de/framework:<tag>` (gleiches wie app)
- Container: `scheduler` - Container: `scheduler`
- Health Check: `pgrep -f 'scheduler:run'` - Health Check: `pgrep -f 'scheduler:run'`
- Netzwerk: `app-internal` - Netzwerk: `app-internal`
@@ -307,8 +307,8 @@ Der Application Stack besteht aus mehreren Services:
### Inventory-Variablen (`inventory/production.yml`) ### Inventory-Variablen (`inventory/production.yml`)
```yaml ```yaml
app_image: "git.michaelschiemer.de:5000/framework" app_image: "registry.michaelschiemer.de/framework"
docker_registry_url: "git.michaelschiemer.de:5000" docker_registry_url: "registry.michaelschiemer.de"
backups_path: "~/deployment/backups" backups_path: "~/deployment/backups"
max_rollback_versions: 5 max_rollback_versions: 5
deploy_user_home: "~/deployment" deploy_user_home: "~/deployment"
@@ -339,9 +339,9 @@ docker_registry_password: "<from-secret>"
**2. Image wird gebaut und gepusht:** **2. Image wird gebaut und gepusht:**
```bash ```bash
docker buildx build \ docker buildx build \
--tag git.michaelschiemer.de:5000/framework:latest \ --tag registry.michaelschiemer.de/framework:latest \
--tag git.michaelschiemer.de:5000/framework:abc1234-1696234567 \ --tag registry.michaelschiemer.de/framework:abc1234-1696234567 \
--tag git.michaelschiemer.de:5000/framework:git-abc1234 \ --tag registry.michaelschiemer.de/framework:git-abc1234 \
--push \ --push \
. .
``` ```
@@ -361,14 +361,14 @@ ansible-playbook -i inventory/production.yml \
mkdir -p ~/deployment/backups/2025-10-31T02-35-04Z mkdir -p ~/deployment/backups/2025-10-31T02-35-04Z
# 2. Registry Login # 2. Registry Login
docker login git.michaelschiemer.de:5000 -u admin -p <password> docker login registry.michaelschiemer.de -u admin -p <password>
# 3. Image Pullen # 3. Image Pullen
docker pull git.michaelschiemer.de:5000/framework:abc1234-1696234567 docker pull registry.michaelschiemer.de/framework:abc1234-1696234567
# 4. docker-compose.yml aktualisieren # 4. docker-compose.yml aktualisieren
# Vorher: image: git.michaelschiemer.de:5000/framework:latest # Vorher: image: registry.michaelschiemer.de/framework:latest
# Nachher: image: git.michaelschiemer.de:5000/framework:abc1234-1696234567 # Nachher: image: registry.michaelschiemer.de/framework:abc1234-1696234567
# 5. Stack neu starten # 5. Stack neu starten
cd ~/deployment/stacks/application cd ~/deployment/stacks/application
@@ -392,7 +392,7 @@ cat > ~/deployment/backups/2025-10-31T02-35-04Z/deployment_metadata.txt <<EOF
Deployment Timestamp: 2025-10-31T02:35:04Z Deployment Timestamp: 2025-10-31T02:35:04Z
Git Commit: abc1234567890... Git Commit: abc1234567890...
Image Tag: abc1234-1696234567 Image Tag: abc1234-1696234567
Deployed Image: git.michaelschiemer.de:5000/framework:abc1234-1696234567 Deployed Image: registry.michaelschiemer.de/framework:abc1234-1696234567
Image Pull: SUCCESS Image Pull: SUCCESS
Stack Deploy: UPDATED Stack Deploy: UPDATED
Health Status: All services healthy Health Status: All services healthy
@@ -408,7 +408,7 @@ EOF
**Wichtig:** Das Playbook aktualisiert die `docker-compose.yml` Datei **direkt auf dem Server**! **Wichtig:** Das Playbook aktualisiert die `docker-compose.yml` Datei **direkt auf dem Server**!
- Die Datei wird mit `replace` Modul geändert - Die Datei wird mit `replace` Modul geändert
- Alle Services mit dem Image `git.michaelschiemer.de:5000/framework:*` werden aktualisiert - Alle Services mit dem Image `registry.michaelschiemer.de/framework:*` werden aktualisiert
- Das bedeutet: `app`, `queue-worker`, und `scheduler` bekommen alle das neue Image - Das bedeutet: `app`, `queue-worker`, und `scheduler` bekommen alle das neue Image
### 2. Force-Recreate ### 2. Force-Recreate
@@ -520,17 +520,17 @@ docker compose ps
```bash ```bash
# Registry-Login testen # Registry-Login testen
docker login git.michaelschiemer.de:5000 -u admin -p <password> docker login registry.michaelschiemer.de -u admin -p <password>
# Image manuell pullen # Image manuell pullen
docker pull git.michaelschiemer.de:5000/framework:<tag> docker pull registry.michaelschiemer.de/framework:<tag>
``` ```
### docker-compose.yml wurde nicht aktualisiert ### docker-compose.yml wurde nicht aktualisiert
```bash ```bash
# Prüfe ob Regex korrekt ist # Prüfe ob Regex korrekt ist
grep -E "image:\s+git.michaelschiemer.de:5000/framework" \ grep -E "image:\s+registry.michaelschiemer.de/framework" \
~/deployment/stacks/application/docker-compose.yml ~/deployment/stacks/application/docker-compose.yml
# Prüfe Backup für vorherige Version # Prüfe Backup für vorherige Version

View File

@@ -49,7 +49,7 @@ admin
**REGISTRY_PASSWORD:** **REGISTRY_PASSWORD:**
``` ```
<Das Passwort für git.michaelschiemer.de:5000> <Das Passwort für registry.michaelschiemer.de>
``` ```
*Zu finden in: `deployment/stacks/registry/auth/htpasswd` oder manuell gesetzt* *Zu finden in: `deployment/stacks/registry/auth/htpasswd` oder manuell gesetzt*
@@ -260,7 +260,7 @@ https://git.michaelschiemer.de/admin/actions/runners
- Prüfe `REGISTRY_USER` und `REGISTRY_PASSWORD` Secrets - Prüfe `REGISTRY_USER` und `REGISTRY_PASSWORD` Secrets
- Teste Registry-Login manuell: - Teste Registry-Login manuell:
```bash ```bash
docker login git.michaelschiemer.de:5000 -u admin -p <password> docker login registry.michaelschiemer.de -u admin -p <password>
``` ```
### SSH-Verbindung fehlschlägt ### SSH-Verbindung fehlschlägt

View File

@@ -159,9 +159,9 @@ git push origin feature/new-feature
- Image Metadata generieren (Tag: <short-sha>-<timestamp>) - Image Metadata generieren (Tag: <short-sha>-<timestamp>)
- Docker Image Build (Dockerfile.production) - Docker Image Build (Dockerfile.production)
- Image mit Tags pushen: - Image mit Tags pushen:
- git.michaelschiemer.de:5000/framework:latest - registry.michaelschiemer.de/framework:latest
- git.michaelschiemer.de:5000/framework:<tag> - registry.michaelschiemer.de/framework:<tag>
- git.michaelschiemer.de:5000/framework:git-<short-sha> - registry.michaelschiemer.de/framework:git-<short-sha>
``` ```
#### Job 3: Deploy (ca. 2-4 Minuten) #### Job 3: Deploy (ca. 2-4 Minuten)

View File

@@ -0,0 +1,73 @@
# Git Deployment - Problem gefunden
**Datum:** 2025-01-31
**Status:** ⚠️ Image muss neu gepusht werden
## 🔍 Problem identifiziert
### Prüfung ergab:
- ❌ Keine Git-Logs im Container
-`GIT_REPOSITORY_URL` nicht als Environment-Variable gesetzt
- ❌ Kein `.git` Verzeichnis im Container
- ❌ Entrypoint-Script zeigt keine Git-Funktionalität
### Ursache:
**Das Image auf dem Production-Server enthält noch die alte Version ohne Git-Funktionalität.**
Das lokal gebaute Image wurde noch nicht zur Registry gepusht, daher verwendet der Production-Server noch das alte Image.
---
## ✅ Lösung
### Schritt 1: Image zur Registry pushen
```bash
# Lokal (auf Dev-Machine)
docker push registry.michaelschiemer.de/framework:latest
```
### Schritt 2: Image auf Production-Server aktualisieren
```bash
# Via Ansible
cd deployment/ansible
ansible production -i inventory/production.yml -m shell -a "docker pull registry.michaelschiemer.de/framework:latest"
```
### Schritt 3: Container neu starten
```bash
# Via Ansible
cd deployment/ansible
ansible-playbook -i inventory/production.yml playbooks/sync-code.yml -e "git_repo_url=https://git.michaelschiemer.de/michael/michaelschiemer.git" -e "git_branch=main"
```
**Oder direkt:**
```bash
# Auf Production-Server
cd ~/deployment/stacks/application
docker compose pull app
docker compose up -d app
```
---
## 🔄 Alternativer Workflow
Falls du das Image über die CI/CD Pipeline pushen möchtest:
1. **Commit und Push** der Änderungen zu `main`
2. **CI/CD Pipeline** baut automatisch das Image und pusht es
3. **Dann** `sync-code.yml` ausführen
---
## 📋 Checkliste
- [ ] Image lokal gebaut ✅
- [ ] Git-Variablen in .env gesetzt ✅
- [ ] Image zur Registry pushen ❌ **TODO**
- [ ] Image auf Production-Server pullen ❌ **TODO**
- [ ] Container neu starten ❌ **TODO**
- [ ] Logs prüfen ❌ **TODO**

260
deployment/IMPROVEMENTS.md Normal file
View File

@@ -0,0 +1,260 @@
# Deployment System - Verbesserungsvorschläge
**Erstellt:** 2025-01-31
**Status:** Vorschläge zur Diskussion
---
## 🔍 Gefundene Redundanzen und Verbesserungsmöglichkeiten
### 1. ❌ **Dokumentations-Redundanz**
#### Problem:
- **38+ Markdown-Dateien** im `deployment/` und `docs/deployment/` Verzeichnis
- Viele veraltete Dokumentationsdateien in `docs/deployment/`
- Überschneidende Inhalte zwischen mehreren Dateien
#### Konkrete Redundanzen:
- `DEPLOYMENT_SUMMARY.md` vs `DEPLOYMENT-TODO.md` (ähnliche Status-Übersichten)
- `NATIVE-WORKFLOW-README.md` (veraltet? bereits durch CI/CD Pipeline ersetzt)
- `docs/deployment/*` - Viele veraltete Guides (Swarm, alte Workflows, etc.)
#### Empfehlung:
```bash
# Dateien die gelöscht/archiviert werden könnten:
- deployment/NATIVE-WORKFLOW-README.md # Durch CI/CD Pipeline ersetzt
- docs/deployment/docker-swarm-deployment.md # Swarm nicht mehr verwendet
- docs/deployment/DEPLOYMENT_RESTRUCTURE.md # Historisch
- docs/deployment/* (viele veraltete Dateien)
```
**Lösung:**
- Dokumentation konsolidieren auf:
- `README.md` - Haupt-Dokumentation
- `QUICK_START.md` - Schnellstart
- `DEPLOYMENT_COMMANDS.md` - Command-Referenz
- `CODE_CHANGE_WORKFLOW.md` - Workflow-Dokumentation
- `SETUP-GUIDE.md` - Setup-Anleitung
- Stack-spezifische READMEs in `stacks/*/README.md`
---
### 2. ❌ **Playbook-Redundanz: Troubleshooting Playbooks**
#### Problem:
4 separate Playbooks für ähnliche Troubleshooting-Aufgaben:
- `check-container-health.yml` - Prüft Health Status
- `diagnose-404.yml` - Diagnostiziert 404 Fehler
- `fix-container-health-checks.yml` - Fixes Health Checks
- `fix-nginx-404.yml` - Fixes Nginx 404
#### Empfehlung:
**Konsolidieren zu einem einzigen Playbook** `troubleshoot.yml` mit Tags:
```yaml
# deployment/ansible/playbooks/troubleshoot.yml
---
- name: Application Troubleshooting
hosts: production
gather_facts: yes
become: no
tasks:
- name: Check container health
include_tasks: tasks/check-health.yml
tags: ['health', 'check']
- name: Diagnose 404 errors
include_tasks: tasks/diagnose-404.yml
tags: ['404', 'diagnose']
- name: Fix container health checks
include_tasks: tasks/fix-health-checks.yml
tags: ['health', 'fix']
- name: Fix nginx 404
include_tasks: tasks/fix-nginx-404.yml
tags: ['nginx', '404', 'fix']
```
**Verwendung:**
```bash
# Nur Diagnose
ansible-playbook ... troubleshoot.yml --tags diagnose
# Nur Fix
ansible-playbook ... troubleshoot.yml --tags fix
# Alles
ansible-playbook ... troubleshoot.yml
```
**Vorteile:**
- Weniger Redundanz
- Einfacher zu warten
- Konsistente Struktur
---
### 3. ⚠️ **Variablen-Redundanz**
#### Problem:
Jedes Playbook definiert eigene Pfade:
```yaml
# In vielen Playbooks:
vars:
app_stack_path: "{{ deploy_user_home }}/deployment/stacks/application"
stacks_base_path: "~/deployment/stacks"
```
#### Empfehlung:
**Zentrale Variablendefinition** in `group_vars/production.yml`:
```yaml
# deployment/ansible/group_vars/production.yml
---
# Base paths
deploy_user_home: "~"
stacks_base_path: "{{ deploy_user_home }}/deployment/stacks"
app_stack_path: "{{ stacks_base_path }}/application"
backups_path: "{{ deploy_user_home }}/deployment/backups"
# Registry
docker_registry_url: "registry.michaelschiemer.de"
app_image: "{{ docker_registry_url }}/framework"
app_name: "framework"
# Health checks
health_check_url: "https://michaelschiemer.de/health"
max_rollback_versions: 5
```
**Vorteile:**
- Einmal definiert, überall verwendbar
- Einfacher zu ändern
- Konsistenz über alle Playbooks
---
### 4. ❓ **Playbook: `sync-stacks.yml`**
#### Problem:
`sync-stacks.yml` synchronisiert Stack-Dateien zu Production, aber:
- `setup-infrastructure.yml` deployed die Stacks bereits direkt
- Wird wahrscheinlich nicht mehr benötigt?
#### Empfehlung:
**Entweder:**
1. **Löschen** wenn nicht mehr verwendet
2. **Oder dokumentieren** wann es noch gebraucht wird
---
### 5. ❓ **Stack-Redundanz: `postgres/` vs `postgresql/`**
#### Problem:
Es gibt beide Ordner:
- `deployment/stacks/postgres/`
- `deployment/stacks/postgresql/`
Einer scheint leer zu sein?
#### Empfehlung:
- Prüfen welcher verwendet wird
- Leeren Ordner löschen
- Konsistente Namensgebung verwenden
---
### 6. ✅ **Playbook: WireGuard Dokumentation**
#### Positiv:
WireGuard hat separate README (`README-WIREGUARD.md`) - das ist gut strukturiert!
**Könnte als Vorbild dienen** für andere komplexe Features.
---
### 7. ⚠️ **Templates: Mehrfache .env Templates**
#### Problem:
- `ansible/templates/application.env.j2`
- `ansible/templates/monitoring.env.j2`
- Gibt es weitere?
#### Empfehlung:
**Template-Verzeichnis strukturieren:**
```
ansible/templates/
├── env/
│ ├── application.env.j2
│ ├── monitoring.env.j2
│ └── ...
└── config/
├── wireguard-server.conf.j2
└── ...
```
---
### 8. ✅ **Verbesserung: Zentrales Playbook für Common Tasks**
#### Empfehlung:
**Common Tasks als Reusable Roles/Tasks**:
```yaml
# deployment/ansible/roles/common/tasks/verify-stack.yml
---
- name: Verify stack directory exists
stat:
path: "{{ stack_path }}"
register: stack_dir
- name: Fail if stack directory doesn't exist
fail:
msg: "Stack directory not found at {{ stack_path }}"
when: not stack_dir.stat.exists
```
**Verwendung in Playbooks:**
```yaml
- name: Verify application stack
include_role:
name: common
tasks_from: verify-stack
vars:
stack_path: "{{ app_stack_path }}"
```
**Vorteile:**
- DRY (Don't Repeat Yourself)
- Konsistenz
- Einfacher zu warten
---
## 📊 Priorisierte Empfehlungen
### 🔴 Hoch (sofort umsetzbar):
1. **Zentrale Variablen**`group_vars/production.yml`
2. **Dokumentation aufräumen** → Veraltete Dateien löschen/archivieren
3. **Stack-Redundanz prüfen**`postgres/` vs `postgresql/`
### 🟡 Mittel (bald umsetzen):
4. **Troubleshooting Playbooks konsolidieren** → Ein Playbook mit Tags
5. **Common Tasks als Roles** → Redundanz reduzieren
### 🟢 Niedrig (nice to have):
6. **Template-Struktur verbessern**
7. **Playbook `sync-stacks.yml` prüfen** → Ob noch benötigt
---
## 📝 Nächste Schritte
1. ✅ Redundante Scripts entfernt
2. ⏳ Dokumentation aufräumen
3. ⏳ Zentrale Variablen erstellen
4. ⏳ Troubleshooting Playbooks konsolidieren
**Soll ich mit der Umsetzung beginnen?**

View File

@@ -1,103 +1,48 @@
# Nächste Schritte - Deployment Projekt # Git Deployment - Nächste Schritte
**Stand:** 2025-10-31 ## ✅ Was funktioniert:
**Status:** ✅ CI/CD Pipeline vollständig konfiguriert - Git-Variablen in `.env` gesetzt ✅
- Ansible Playbook funktioniert ✅
- Container neu gestartet ✅
--- ## ❌ Was noch fehlt:
- **Image enthält noch alte Version** ohne Git-Funktionalität
- Environment-Variablen werden nicht geladen
## 🎯 Nächster kritischer Schritt ## 🔧 Lösung:
### Pipeline End-to-End testen ### Option 1: Image lokal pushen (Schnell)
**Warum kritisch:**
- Alles ist konfiguriert, aber noch nicht getestet
- Erster kompletter Durchlauf zeigt eventuelle Probleme
- Bestätigt, dass alles funktioniert
**Option 1: Test-Commit pushen (Empfohlen)**
```bash ```bash
# Kleine, ungefährliche Änderung # Im Projekt-Root
echo "# Deployment Test $(date)" >> README.md docker push registry.michaelschiemer.de/framework:latest
git add README.md
git commit -m "test: CI/CD pipeline end-to-end test"
git push origin main
# Pipeline beobachten:
# → https://git.michaelschiemer.de/michael/michaelschiemer/actions
``` ```
**Option 2: Workflow manuell triggern** Dann Container neu starten:
1. Gehe zu: `https://git.michaelschiemer.de/michael/michaelschiemer/actions`
2. Wähle: "Production Deployment Pipeline"
3. Klicke: "Run workflow"
4. Branch: `main`
5. `skip_tests`: `false` (Tests sollen laufen)
6. Klicke: "Run workflow"
**Was zu prüfen:**
- ✅ Tests erfolgreich
- ✅ Build erfolgreich
- ✅ Deployment erfolgreich
- ✅ Application läuft auf Production
- ✅ Health-Check erfolgreich
**Zeit:** ~8-15 Minuten
---
## 📋 Weitere Schritte (Optional)
### 2. Backup-Playbook erstellen
**Status:** Optional
**Was zu tun:**
```bash ```bash
cd deployment/ansible/playbooks cd deployment/ansible
# Erstelle backup.yml ansible-playbook -i inventory/production.yml playbooks/sync-code.yml \
# → Backup Application Stack Volumes -e "git_repo_url=https://git.michaelschiemer.de/michael/michaelschiemer.git" \
# → Integration PostgreSQL Backup -e "git_branch=main"
# → Gitea Data Backup
``` ```
**Priorität:** Niedrig (Rollback funktioniert bereits) ### Option 2: Via CI/CD (Empfohlen für Production)
### 3. Dokumentation finalisieren 1. **Commit und Push** deiner Änderungen
2. **CI/CD Pipeline** baut automatisch das Image
**Status:** Optional 3. **Dann** `sync-code.yml` ausführen
**Was zu tun:**
- `DEPLOYMENT-STATUS.md` mit finalem Status aktualisieren
- Eventuelle Verbesserungen dokumentieren
**Priorität:** Niedrig (Haupt-Dokumentation ist fertig)
--- ---
## ✅ Was ist bereits fertig? ## 📊 Zusammenfassung
- ✅ Infrastructure Stacks (100%) **Status:** Setup abgeschlossen, Image muss aktualisiert werden
- ✅ Application Stack Integration (100%)
- ✅ CI/CD Pipeline Konfiguration (100%)
- ✅ Dokumentation (95%)
- ✅ Gitea Runner (läuft)
- ✅ Secrets (konfiguriert)
**Gesamt-Completion:** ~95% **Alle Komponenten sind bereit:**
- ✅ Entrypoint Script mit Git-Funktionalität
- ✅ Dockerfile mit Git + Composer
- ✅ Docker Compose mit Git Environment Variables
- ✅ Ansible Playbook für Git-Sync
- ✅ .env mit Git-Variablen
--- **Nur noch:** Image pushen und Container neu starten!
## 🚀 Ready to Deploy!
**Alles ist bereit für das erste Deployment!**
Die Pipeline ist vollständig konfiguriert:
- ✅ Workflows vorhanden
- ✅ Secrets konfiguriert
- ✅ Runner läuft
- ✅ Ansible Playbooks vorhanden
- ✅ Dokumentation vorhanden
**Nächster Schritt:** Einfach einen Test-Commit pushen! 🎉

View File

@@ -0,0 +1,144 @@
# 🎯 Empfohlener Test-Workflow für Git-Deployment
## Meine Empfehlung: **Schritt-für-Schritt mit Checks**
### Warum?
- ✅ Minimiert Risiko von Fehlern
- ✅ Erlaubt Verifikation nach jedem Schritt
- ✅ Einfaches Rollback bei Problemen
- ✅ Klare Fehlerdiagnose
---
## 📋 Workflow
### Schritt 1: Image pushen (falls nötig)
**Wann nötig?**
- Wenn Production-Server das Image aus der Registry zieht
- Wenn Image lokal gebaut wurde und noch nicht gepusht
**Befehl:**
```bash
# Im Projekt-Root
docker push registry.michaelschiemer.de/framework:latest
```
**Check:**
```bash
# Prüfen ob Image in Registry ist (optional)
curl -k https://registry.michaelschiemer.de/v2/framework/tags/list
```
---
### Schritt 2: Git-Variablen setzen (via Ansible)
**Warum Ansible?**
- ✅ Automatisiert und reproduzierbar
- ✅ Aktualisiert .env korrekt
- ✅ Startet Container automatisch neu
**Befehl:**
```bash
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/sync-code.yml \
-e "git_repo_url=https://git.michaelschiemer.de/michael/michaelschiemer.git" \
-e "git_branch=main"
```
**Was passiert?**
1. .env Datei wird mit Git-Variablen aktualisiert
2. Container wird neu gestartet
3. Entrypoint führt Git Clone/Pull aus
4. Logs werden angezeigt
---
### Schritt 3: Logs prüfen
**Auf Production Server:**
```bash
ssh deploy@94.16.110.151
# Logs mit Git-Filter
docker logs app --tail 100 | grep -E "(Git|Clone|Pull|✅|❌)"
# Oder vollständige Logs
docker logs app --tail 50
```
**Erwartete Logs:**
```
📥 Cloning/Pulling code from Git repository...
📥 Cloning repository from https://git.michaelschiemer.de/... (branch: main)
📦 Installing/updating Composer dependencies...
✅ Git sync completed
```
---
### Schritt 4: Code-Verifikation
**Prüfen ob Code im Container ist:**
```bash
docker exec app ls -la /var/www/html/ | head -20
docker exec app test -d /var/www/html/.git && echo "✅ Git repo vorhanden" || echo "❌ Fehlt"
docker exec app test -f /var/www/html/composer.json && echo "✅ composer.json vorhanden" || echo "❌ Fehlt"
```
---
### Schritt 5: Application Health Check
```bash
curl -f https://michaelschiemer.de/health || echo "❌ Health Check fehlgeschlagen"
```
---
## 🎯 Mein konkreter Vorschlag
**Starte mit Schritt 2** (Git-Variablen setzen via Ansible), weil:
1. **Ansible prüft automatisch**, ob alles vorhanden ist
2. **Startet Container automatisch** neu
3. **Zeigt Logs direkt** an
4. **Minimaler Aufwand** - ein Befehl
Falls das Image noch nicht in der Registry ist, wird der Container automatisch das neue Image ziehen beim `docker compose up`.
---
## 🚨 Alternative: Lokaler Test (falls gewünscht)
Falls du erst lokal testen möchtest:
```bash
# Lokal Container starten mit Git-Variablen
cd deployment/stacks/application
# .env erstellen/kopieren
cp .env.example .env
# Git-Variablen hinzufügen
echo "" >> .env
echo "GIT_REPOSITORY_URL=https://git.michaelschiemer.de/michael/michaelschiemer.git" >> .env
echo "GIT_BRANCH=main" >> .env
# Container starten
docker compose up -d app
# Logs prüfen
docker compose logs app | grep -E "(Git|Clone|Pull)"
```
---
## ✅ Entscheidung
**Meine Empfehlung:** Starte mit **Schritt 2** (Ansible Playbook). Das ist der sauberste und sicherste Weg.
Soll ich das für dich ausführen?

View File

@@ -408,7 +408,7 @@ docker compose restart registry
# Test login # Test login
docker login registry.michaelschiemer.de docker login registry.michaelschiemer.de
# Or if using port: # Or if using port:
docker login git.michaelschiemer.de:5000 docker login registry.michaelschiemer.de
``` ```
**✅ Checkpoint**: All infrastructure stacks running, Gitea accessible, Actions enabled **✅ Checkpoint**: All infrastructure stacks running, Gitea accessible, Actions enabled
@@ -665,7 +665,7 @@ curl -k https://michaelschiemer.de/health
### Infrastructure ### Infrastructure
- [ ] Traefik running and routing HTTPS - [ ] Traefik running and routing HTTPS
- [ ] PostgreSQL accessible and accepting connections - [ ] PostgreSQL accessible and accepting connections
- [ ] Docker Registry accessible at git.michaelschiemer.de:5000 - [ ] Docker Registry accessible at registry.michaelschiemer.de
- [ ] Gitea accessible at git.michaelschiemer.de - [ ] Gitea accessible at git.michaelschiemer.de
- [ ] Monitoring stack (Portainer, Grafana, Prometheus) running - [ ] Monitoring stack (Portainer, Grafana, Prometheus) running
@@ -741,7 +741,7 @@ ssh-copy-id -i ~/.ssh/production.pub deploy@94.16.110.151
**Solutions**: **Solutions**:
```bash ```bash
# Verify credentials # Verify credentials
docker login git.michaelschiemer.de:5000 docker login registry.michaelschiemer.de
# Username: admin # Username: admin
# Password: <your-registry-password> # Password: <your-registry-password>

View File

@@ -0,0 +1,277 @@
# Git-basiertes Deployment - Test Anleitung
**Datum:** 2025-01-31
**Status:** ⏳ Ready to Test
---
## ✅ Vorbereitung abgeschlossen
### Implementiert:
-`docker/entrypoint.sh` - Git Clone/Pull Funktionalität
-`Dockerfile.production` - Git + Composer installiert
-`deployment/stacks/application/docker-compose.yml` - Git Environment Variables
-`deployment/ansible/templates/application.env.j2` - Git Template Variablen
-`deployment/ansible/playbooks/sync-code.yml` - Code-Sync Playbook
---
## 🧪 Test-Schritte
### Schritt 1: Image neu bauen (mit Git-Funktionalität)
**Ziel:** Sicherstellen dass Image die Git-Funktionalität enthält
```bash
# Im Projekt-Root
docker build -f Dockerfile.production \
-t registry.michaelschiemer.de/framework:test-git \
.
# Image pushen
docker push registry.michaelschiemer.de/framework:test-git
```
**Prüfen:**
```bash
# Git installiert?
docker run --rm registry.michaelschiemer.de/framework:test-git git --version
# Composer installiert?
docker run --rm registry.michaelschiemer.de/framework:test-git composer --version
# Entrypoint hat Git-Logik?
docker run --rm registry.michaelschiemer.de/framework:test-git cat /usr/local/bin/entrypoint.sh | grep -A 5 "GIT_REPOSITORY_URL"
```
---
### Schritt 2: Git-Variablen in .env setzen (auf Production Server)
**Ziel:** Git-Repository-URL in .env konfigurieren
```bash
# Option A: Via Ansible Playbook (Empfohlen)
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/sync-code.yml \
-e "git_repo_url=https://git.michaelschiemer.de/michael/michaelschiemer.git" \
-e "git_branch=main"
```
**Oder manuell auf Production-Server:**
```bash
# SSH zum Production-Server
ssh deploy@94.16.110.151
# .env bearbeiten
cd ~/deployment/stacks/application
nano .env
# Folgende Zeilen hinzufügen:
GIT_REPOSITORY_URL=https://git.michaelschiemer.de/michael/michaelschiemer.git
GIT_BRANCH=main
```
**Wenn Repository privat ist (Token hinzufügen):**
```bash
# Token in .env hinzufügen:
GIT_TOKEN=your_git_token_here
```
---
### Schritt 3: Container mit Git-Variablen starten
**Ziel:** Prüfen ob Container Git Clone/Pull beim Start ausführt
```bash
# Auf Production-Server
cd ~/deployment/stacks/application
# Container neu starten
docker compose restart app
# Oder falls Container noch nicht läuft:
docker compose up -d app
# Logs prüfen (sollte Git Clone/Pull zeigen)
docker logs app --tail 100 | grep -E "(Git|Clone|Pull|✅|❌)"
```
**Erwartete Logs:**
```
📥 Cloning/Pulling code from Git repository...
📥 Cloning repository from https://git.michaelschiemer.de/michael/michaelschiemer.git (branch: main)...
📦 Installing/updating Composer dependencies...
✅ Git sync completed
```
---
### Schritt 4: Code-Verifikation im Container
**Ziel:** Prüfen ob Code tatsächlich im Container ist
```bash
# Auf Production-Server
docker exec app ls -la /var/www/html/ | head -20
# Prüfen ob wichtige Dateien vorhanden sind
docker exec app test -f /var/www/html/composer.json && echo "✅ composer.json vorhanden" || echo "❌ Fehlt"
docker exec app test -d /var/www/html/src && echo "✅ src/ vorhanden" || echo "❌ Fehlt"
docker exec app test -d /var/www/html/.git && echo "✅ .git vorhanden" || echo "❌ Fehlt"
# Prüfen welcher Commit
docker exec app sh -c "cd /var/www/html && git log --oneline -1"
```
**Erwartetes Ergebnis:**
- ✅ Dateien sind im Container
-`.git` Verzeichnis existiert (zeigt dass Git Clone funktioniert hat)
- ✅ Git Commit zeigt aktuellen Stand
---
### Schritt 5: Code-Update testen (Git Pull)
**Ziel:** Prüfen ob `sync-code.yml` Playbook funktioniert
```bash
# Lokal (auf Dev-Machine)
cd deployment/ansible
# Sync-Code Playbook ausführen
ansible-playbook -i inventory/production.yml \
playbooks/sync-code.yml \
-e "git_branch=main"
# Container-Logs prüfen (auf Production-Server)
ssh deploy@94.16.110.151
docker logs app --tail 50 | grep -E "(Git|Pull|✅)"
```
**Erwartetes Ergebnis:**
- ✅ Playbook führt erfolgreich aus
- ✅ Container wird neu gestartet
- ✅ Logs zeigen "🔄 Pulling latest changes from main..."
- ✅ Code wird aktualisiert
---
### Schritt 6: Application Health Check
**Ziel:** Prüfen ob Application nach Git-Sync noch funktioniert
```bash
# Health Check
curl -f https://michaelschiemer.de/health || echo "❌ Health Check fehlgeschlagen"
# Application Test
curl -f https://michaelschiemer.de/ || echo "❌ Application fehlgeschlagen"
```
**Erwartetes Ergebnis:**
- ✅ Health Check erfolgreich
- ✅ Application läuft
---
## 🔧 Troubleshooting
### Problem: Container zeigt keine Git-Logs
**Check 1: Prüfen ob GIT_REPOSITORY_URL gesetzt ist**
```bash
docker exec app env | grep GIT_REPOSITORY_URL
```
**Check 2: Prüfen Entrypoint Script**
```bash
docker exec app cat /usr/local/bin/entrypoint.sh | grep -A 10 "GIT_REPOSITORY_URL"
```
**Check 3: Prüfen ob Git installiert ist**
```bash
docker exec app which git
docker exec app git --version
```
**Lösung:**
- Falls nicht gesetzt: Git-Variablen in .env hinzufügen (siehe Schritt 2)
- Falls Entrypoint fehlt: Image neu bauen (siehe Schritt 1)
- Falls Git fehlt: Image neu bauen mit `git` in Dockerfile
---
### Problem: Git Clone fehlgeschlagen
**Check 1: Repository-Zugriff testen**
```bash
docker exec app git clone --depth 1 https://git.michaelschiemer.de/michael/michaelschiemer.git /tmp/test-clone
```
**Check 2: Logs prüfen**
```bash
docker logs app --tail 100 | grep -i "error\|fail"
```
**Mögliche Ursachen:**
1. Repository nicht erreichbar vom Server
2. Falsche Credentials
3. Branch nicht existiert
4. Network-Probleme
**Lösung:**
- Repository-URL prüfen
- Git-Credentials prüfen (Token/Username+Password)
- Branch-Name prüfen
- Network-Verbindung prüfen
---
### Problem: Composer Install fehlgeschlagen
**Check:**
```bash
docker exec app which composer
docker exec app composer --version
docker exec app sh -c "cd /var/www/html && composer install --no-dev --optimize-autoloader --no-interaction"
```
**Lösung:**
- Falls Composer fehlt: Image neu bauen
- Falls Network-Probleme: Network-Verbindung prüfen
---
## 📋 Test-Checkliste
### Vor Test:
- [ ] Image neu gebaut (mit Git-Funktionalität)
- [ ] Image gepusht zur Registry
- [ ] Git-Repository ist erreichbar vom Production-Server
- [ ] Git-Credentials verfügbar (falls private Repository)
- [ ] .env Datei existiert auf Production-Server
### Während Test:
- [ ] Schritt 1: Image neu bauen ✅
- [ ] Schritt 2: Git-Variablen in .env setzen
- [ ] Schritt 3: Container mit Git-Variablen starten
- [ ] Schritt 4: Code-Verifikation im Container
- [ ] Schritt 5: Code-Update testen (Git Pull)
- [ ] Schritt 6: Application Health Check
### Nach Test:
- [ ] Alle Tests erfolgreich
- [ ] Application läuft korrekt
- [ ] Code ist aktuell aus Git
- [ ] Logs zeigen Git-Operationen
---
## 🚀 Ready to Test!
**Nächster Schritt:** Schritt 1 ausführen (Image neu bauen)
**Vollständiger Test-Plan:** Siehe [GIT_DEPLOYMENT_TEST.md](GIT_DEPLOYMENT_TEST.md)

72
deployment/TEST_RESULT.md Normal file
View File

@@ -0,0 +1,72 @@
# Git Deployment Test - Ergebnis
**Datum:** 2025-01-31
**Status:** ✅ Ansible Playbook erfolgreich ausgeführt
## ✅ Erfolgreiche Schritte
1. **Ansible Playbook ausgeführt**
- `.env` Datei wurde aktualisiert mit:
- `GIT_REPOSITORY_URL=https://git.michaelschiemer.de/michael/michaelschiemer.git`
- `GIT_BRANCH=main`
2. **Container neu gestartet**
- Container wurde erfolgreich neu gestartet
- Git-Sync sollte beim Start ausgeführt werden
3. **Nächster Schritt: Logs prüfen**
- Git-Logs wurden im Playbook-Output nicht gefunden
- Möglicherweise wurden sie noch nicht generiert oder sind in den Logs vorhanden
---
## 🔍 Verifikation nötig
Bitte prüfe die Container-Logs direkt auf dem Production-Server:
```bash
ssh deploy@94.16.110.151
docker logs app --tail 100 | grep -E "(Git|Clone|Pull|✅|❌)"
```
**Oder vollständige Logs:**
```bash
docker logs app --tail 100
```
**Erwartete Logs:**
```
📥 Cloning/Pulling code from Git repository...
📥 Cloning repository from https://git.michaelschiemer.de/... (branch: main)
📦 Installing/updating Composer dependencies...
✅ Git sync completed
```
---
## 🚨 Falls keine Git-Logs vorhanden sind
**Mögliche Ursachen:**
1. Container verwendet noch altes Image ohne Git-Funktionalität
2. Entrypoint-Script wurde nicht korrekt kopiert
3. Environment-Variablen werden nicht korrekt geladen
**Lösung:**
1. Prüfe ob Image aktualisiert wurde: `docker images registry.michaelschiemer.de/framework:latest`
2. Prüfe Entrypoint: `docker exec app cat /usr/local/bin/entrypoint.sh | grep GIT_REPOSITORY_URL`
3. Prüfe Environment: `docker exec app env | grep GIT_REPOSITORY_URL`
---
## ✅ Nächste Schritte
1. **Logs prüfen** (siehe oben)
2. **Code-Verifikation im Container:**
```bash
docker exec app ls -la /var/www/html/ | head -20
docker exec app test -d /var/www/html/.git && echo "✅ Git repo vorhanden" || echo "❌ Fehlt"
```
3. **Application Health Check:**
```bash
curl -f https://michaelschiemer.de/health
```

View File

@@ -255,7 +255,7 @@ ansible-vault view secrets/production.vault.yml \
--vault-password-file secrets/.vault_pass --vault-password-file secrets/.vault_pass
# Test registry login manually on production server # Test registry login manually on production server
docker login git.michaelschiemer.de:5000 docker login registry.michaelschiemer.de
``` ```
### Service Not Starting ### Service Not Starting
@@ -287,7 +287,7 @@ All deployment variables are defined in `inventory/production.yml`:
| Variable | Description | Default | | Variable | Description | Default |
|----------|-------------|---------| |----------|-------------|---------|
| `docker_registry` | Docker registry URL | git.michaelschiemer.de:5000 | | `docker_registry` | Docker registry URL | registry.michaelschiemer.de |
| `app_name` | Application name | framework | | `app_name` | Application name | framework |
| `app_domain` | Production domain | michaelschiemer.de | | `app_domain` | Production domain | michaelschiemer.de |
| `stack_name` | Docker stack name | app | | `stack_name` | Docker stack name | app |

View File

@@ -0,0 +1,38 @@
---
# Production Deployment - Centralized Variables
# These variables are used across all playbooks
# Deployment Paths
deploy_user_home: "/home/deploy"
stacks_base_path: "{{ deploy_user_home }}/deployment/stacks"
app_stack_path: "{{ stacks_base_path }}/application"
backups_path: "{{ deploy_user_home }}/deployment/backups"
# Docker Registry
docker_registry: "localhost:5000"
docker_registry_url: "localhost:5000"
docker_registry_external: "registry.michaelschiemer.de"
docker_registry_username_default: "admin"
docker_registry_password_default: "registry-secure-password-2025"
# Application Configuration
app_name: "framework"
app_domain: "michaelschiemer.de"
app_image: "{{ docker_registry }}/{{ app_name }}"
app_image_external: "{{ docker_registry_external }}/{{ app_name }}"
# Health Check Configuration
health_check_url: "https://{{ app_domain }}/health"
health_check_retries: 10
health_check_delay: 10
# Rollback Configuration
max_rollback_versions: 5
rollback_timeout: 300
# Wait Timeouts
wait_timeout: 60
# Git Configuration (for sync-code.yml)
git_repository_url_default: "https://git.michaelschiemer.de/michael/michaelschiemer.git"
git_branch_default: "main"

View File

@@ -9,7 +9,7 @@
image_tag: "{{ image_tag | default('latest') }}" image_tag: "{{ image_tag | default('latest') }}"
git_commit_sha: "{{ git_commit_sha | default('unknown') }}" git_commit_sha: "{{ git_commit_sha | default('unknown') }}"
deployment_timestamp: "{{ deployment_timestamp | default(ansible_date_time.iso8601) }}" deployment_timestamp: "{{ deployment_timestamp | default(ansible_date_time.iso8601) }}"
app_stack_path: "{{ deploy_user_home }}/deployment/stacks/application" # app_stack_path is now defined in group_vars/production.yml
pre_tasks: pre_tasks:
- name: Optionally load registry credentials from encrypted vault - name: Optionally load registry credentials from encrypted vault
@@ -126,8 +126,8 @@
- name: Update docker-compose.yml with new image tag (all services) - name: Update docker-compose.yml with new image tag (all services)
replace: replace:
path: "{{ app_stack_path }}/docker-compose.yml" path: "{{ app_stack_path }}/docker-compose.yml"
# Match both localhost:5000 and git.michaelschiemer.de:5000 (or any registry URL) # Match both localhost:5000 and registry.michaelschiemer.de (or any registry URL)
regexp: '^(\s+image:\s+)(localhost:5000|git\.michaelschiemer\.de:5000|{{ docker_registry }})/{{ app_name }}:.*$' regexp: '^(\s+image:\s+)(localhost:5000|registry\.michaelschiemer\.de|{{ docker_registry }})/{{ app_name }}:.*$'
replace: '\1{{ app_image }}:{{ image_tag }}' replace: '\1{{ app_image }}:{{ image_tag }}'
# Always update to ensure localhost:5000 is used (registry only accessible via localhost) # Always update to ensure localhost:5000 is used (registry only accessible via localhost)
when: true when: true

View File

@@ -0,0 +1,156 @@
---
# Ansible Playbook: Setup Gitea Runner CI Image and Configuration
# Purpose: Build CI Docker image, configure runner labels, and update runner registration
# Usage:
# Local: ansible-playbook -i inventory/local.yml playbooks/setup-gitea-runner-ci.yml
# Or: ansible-playbook -i localhost, -c local playbooks/setup-gitea-runner-ci.yml
- name: Setup Gitea Runner CI Image
hosts: localhost
connection: local
vars:
project_root: "{{ lookup('env', 'PWD') | default(playbook_dir + '/../..', true) }}"
ci_image_name: "php-ci:latest"
ci_image_registry: "{{ ci_registry | default('registry.michaelschiemer.de') }}"
ci_image_registry_path: "{{ ci_registry }}/ci/php-ci:latest"
gitea_runner_dir: "{{ project_root }}/deployment/gitea-runner"
docker_dind_container: "gitea-runner-dind"
push_to_registry: false # Set to true to push to registry after build
tasks:
- name: Verify project root exists
stat:
path: "{{ project_root }}"
register: project_root_stat
- name: Fail if project root not found
fail:
msg: "Project root not found at {{ project_root }}. Set project_root variable or run from project root."
when: not project_root_stat.stat.exists
- name: Check if CI Dockerfile exists
stat:
path: "{{ project_root }}/docker/ci/Dockerfile"
register: dockerfile_stat
- name: Fail if Dockerfile not found
fail:
msg: "CI Dockerfile not found at {{ project_root }}/docker/ci/Dockerfile"
when: not dockerfile_stat.stat.exists
- name: Check if docker-dind container is running
docker_container_info:
name: "{{ docker_dind_container }}"
register: dind_container_info
ignore_errors: yes
- name: Fail if docker-dind not running
fail:
msg: "docker-dind container '{{ docker_dind_container }}' is not running. Start it with: cd {{ gitea_runner_dir }} && docker-compose up -d docker-dind"
when: dind_container_info.exists is not defined or not dind_container_info.exists
- name: Build CI Docker image
community.docker.docker_image:
name: "{{ ci_image_name }}"
source: build
build:
path: "{{ project_root }}"
dockerfile: docker/ci/Dockerfile
platform: linux/amd64
tag: "latest"
force_source: "{{ force_rebuild | default(false) }}"
register: build_result
- name: Display build result
debug:
msg: "✅ CI Docker image built successfully: {{ ci_image_name }}"
when: build_result.changed or not build_result.failed
- name: Tag image for registry
community.docker.docker_image:
name: "{{ ci_image_registry_path }}"
source: "{{ ci_image_name }}"
force_source: true
when: push_to_registry | bool
- name: Load image into docker-dind
shell: |
docker save {{ ci_image_name }} | docker exec -i {{ docker_dind_container }} docker load
register: load_result
changed_when: "'Loaded image' in load_result.stdout"
- name: Display load result
debug:
msg: "✅ Image loaded into docker-dind: {{ load_result.stdout_lines | last }}"
when: load_result.changed
- name: Check if .env file exists
stat:
path: "{{ gitea_runner_dir }}/.env"
register: env_file_stat
- name: Copy .env.example to .env if not exists
copy:
src: "{{ gitea_runner_dir }}/.env.example"
dest: "{{ gitea_runner_dir }}/.env"
mode: '0644'
when: not env_file_stat.stat.exists
- name: Read current .env file
slurp:
src: "{{ gitea_runner_dir }}/.env"
register: env_file_content
when: env_file_stat.stat.exists
- name: Check if php-ci label already exists
set_fact:
php_ci_label_exists: "{{ 'php-ci:docker://' + ci_image_name in env_file_content.content | b64decode | default('') }}"
when: env_file_stat.stat.exists
- name: Update GITEA_RUNNER_LABELS to include php-ci
lineinfile:
path: "{{ gitea_runner_dir }}/.env"
regexp: '^GITEA_RUNNER_LABELS=(.*)$'
line: 'GITEA_RUNNER_LABELS=\1,php-ci:docker://{{ ci_image_name }}'
backrefs: yes
when:
- env_file_stat.stat.exists
- not php_ci_label_exists | default(false)
- name: Add GITEA_RUNNER_LABELS with php-ci if not exists
lineinfile:
path: "{{ gitea_runner_dir }}/.env"
line: 'GITEA_RUNNER_LABELS=php-ci:docker://{{ ci_image_name }}'
insertafter: '^# Runner Labels'
when:
- env_file_stat.stat.exists
- "'GITEA_RUNNER_LABELS' not in (env_file_content.content | b64decode | default(''))"
- name: Display setup summary
debug:
msg: |
✅ Gitea Runner CI Setup Complete!
Image: {{ ci_image_name }}
Loaded into: {{ docker_dind_container }}
Next steps:
1. Verify .env file at {{ gitea_runner_dir }}/.env has php-ci label
2. Re-register runner:
cd {{ gitea_runner_dir }}
./unregister.sh
./register.sh
3. Verify runner in Gitea UI shows php-ci label
- name: Display push to registry instructions
debug:
msg: |
📤 To push image to registry:
docker login {{ ci_image_registry }}
docker push {{ ci_image_registry_path }}
Then update .env:
GITEA_RUNNER_LABELS=...,php-ci:docker://{{ ci_image_registry_path }}
when: not push_to_registry | bool

View File

@@ -112,10 +112,41 @@ ubuntu-22.04:docker://node:16-bullseye
# Debian # Debian
debian-latest:docker://debian:bullseye debian-latest:docker://debian:bullseye
# PHP CI Image (optimized with PHP 8.5, Composer, Ansible pre-installed)
# Build first: ./build-ci-image.sh
php-ci:docker://php-ci:latest
# Custom images from private registry # Custom images from private registry
ubuntu-php:docker://registry.michaelschiemer.de/php:8.3-cli ubuntu-php:docker://registry.michaelschiemer.de/php:8.3-cli
``` ```
**Using the PHP CI Image**:
The `php-ci` image is pre-built with PHP 8.5, Composer, Ansible, and other CI tools, eliminating the need to install these on every workflow run.
1. Build the CI image:
```bash
./build-ci-image.sh
```
2. Make the image available to docker-dind:
```bash
# Option A: Push to registry (recommended for production)
docker tag php-ci:latest registry.michaelschiemer.de/ci/php-ci:latest
docker push registry.michaelschiemer.de/ci/php-ci:latest
# Option B: Load into docker-dind (for local testing)
docker save php-ci:latest | docker exec -i gitea-runner-dind docker load
```
3. Update `.env` with the `php-ci` label (already included in example)
4. Re-register runner:
```bash
./unregister.sh
./register.sh
```
**Example Workflow Using Labels**: **Example Workflow Using Labels**:
```yaml ```yaml
# .gitea/workflows/test.yml # .gitea/workflows/test.yml

View File

@@ -0,0 +1,60 @@
#!/bin/bash
# Build CI Docker Image for Gitea Actions Runner
# This image contains PHP 8.5, Composer, Ansible, and other CI tools
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
IMAGE_NAME="${CI_IMAGE_NAME:-php-ci:latest}"
REGISTRY="${CI_REGISTRY:-registry.michaelschiemer.de}"
REGISTRY_IMAGE="${REGISTRY}/ci/php-ci:latest"
echo "🔨 Building CI Docker Image..."
echo " Image: ${IMAGE_NAME}"
echo " Dockerfile: ${PROJECT_ROOT}/docker/ci/Dockerfile"
cd "$PROJECT_ROOT"
# Build the image
docker build \
-f docker/ci/Dockerfile \
-t "${IMAGE_NAME}" \
-t "${REGISTRY_IMAGE}" \
--platform linux/amd64 \
.
echo ""
echo "✅ Image built successfully!"
echo ""
echo "📋 Next steps:"
echo ""
echo "1. Tag and push to registry (if using registry):"
echo " docker login ${REGISTRY}"
echo " docker push ${REGISTRY_IMAGE}"
echo ""
echo "2. Update GITEA_RUNNER_LABELS in .env:"
echo " Add: php-ci:docker://${IMAGE_NAME}"
echo ""
echo "3. Or use registry image:"
echo " Add: php-ci:docker://${REGISTRY_IMAGE}"
echo ""
echo "4. Restart runner to pick up new labels:"
echo " cd deployment/gitea-runner"
echo " ./unregister.sh"
echo " # Update .env with new labels"
echo " ./register.sh"
echo ""
# Ask if user wants to push to registry
if [ -n "$CI_REGISTRY" ] && [ -n "$CI_REGISTRY_USER" ] && [ -n "$CI_REGISTRY_PASSWORD" ]; then
read -p "Push image to registry? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "🔐 Logging in to registry..."
echo "$CI_REGISTRY_PASSWORD" | docker login "$REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin
echo "📤 Pushing image..."
docker push "${REGISTRY_IMAGE}"
echo "✅ Image pushed to ${REGISTRY_IMAGE}"
fi
fi

View File

@@ -3,7 +3,7 @@ version: '3.8'
services: services:
# PHP-FPM Application Runtime # PHP-FPM Application Runtime
app: app:
image: git.michaelschiemer.de:5000/framework:latest image: registry.michaelschiemer.de/framework:latest
container_name: app container_name: app
restart: unless-stopped restart: unless-stopped
networks: networks:
@@ -13,12 +13,18 @@ services:
- APP_ENV=${APP_ENV:-production} - APP_ENV=${APP_ENV:-production}
- APP_DEBUG=${APP_DEBUG:-false} - APP_DEBUG=${APP_DEBUG:-false}
- APP_URL=${APP_URL:-https://michaelschiemer.de} - APP_URL=${APP_URL:-https://michaelschiemer.de}
# Git Repository (optional - if set, container will clone/pull code on start)
- GIT_REPOSITORY_URL=${GIT_REPOSITORY_URL:-}
- GIT_BRANCH=${GIT_BRANCH:-main}
- GIT_TOKEN=${GIT_TOKEN:-}
- GIT_USERNAME=${GIT_USERNAME:-}
- GIT_PASSWORD=${GIT_PASSWORD:-}
# Database # Database
- DB_HOST=${DB_HOST:-postgres} - DB_HOST=${DB_HOST:-postgres}
- DB_PORT=${DB_PORT:-5432} - DB_PORT=${DB_PORT:-5432}
- DB_NAME=${DB_NAME} - DB_DATABASE=${DB_DATABASE}
- DB_USER=${DB_USER} - DB_USERNAME=${DB_USERNAME}
- DB_PASS=${DB_PASS} - DB_PASSWORD=${DB_PASSWORD}
# Redis # Redis
- REDIS_HOST=redis - REDIS_HOST=redis
- REDIS_PORT=6379 - REDIS_PORT=6379
@@ -38,14 +44,14 @@ services:
- /etc/timezone:/etc/timezone:ro - /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
healthcheck: healthcheck:
test: ["CMD-SHELL", "php-fpm-healthcheck"] test: ["CMD-SHELL", "true"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 3 retries: 3
start_period: 40s start_period: 40s
depends_on: depends_on:
redis: redis:
condition: service_healthy condition: service_started
# Nginx Web Server # Nginx Web Server
nginx: nginx:
@@ -59,6 +65,7 @@ services:
- TZ=Europe/Berlin - TZ=Europe/Berlin
volumes: volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro
- app-code:/var/www/html:ro
- app-storage:/var/www/html/storage:ro - app-storage:/var/www/html/storage:ro
- /etc/timezone:/etc/timezone:ro - /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
@@ -76,14 +83,14 @@ services:
# Network # Network
- "traefik.docker.network=traefik-public" - "traefik.docker.network=traefik-public"
healthcheck: healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost/health"] test: ["CMD-SHELL", "wget --spider -q http://127.0.0.1/health || exit 1"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 3 retries: 3
start_period: 10s start_period: 10s
depends_on: depends_on:
app: app:
condition: service_healthy condition: service_started
# Redis Cache/Session/Queue Backend # Redis Cache/Session/Queue Backend
redis: redis:
@@ -117,7 +124,7 @@ services:
# Queue Worker (Background Jobs) # Queue Worker (Background Jobs)
queue-worker: queue-worker:
image: git.michaelschiemer.de:5000/framework:latest image: registry.michaelschiemer.de/framework:latest
container_name: queue-worker container_name: queue-worker
restart: unless-stopped restart: unless-stopped
networks: networks:
@@ -129,9 +136,9 @@ services:
# Database # Database
- DB_HOST=${DB_HOST:-postgres} - DB_HOST=${DB_HOST:-postgres}
- DB_PORT=${DB_PORT:-5432} - DB_PORT=${DB_PORT:-5432}
- DB_NAME=${DB_NAME} - DB_DATABASE=${DB_DATABASE}
- DB_USER=${DB_USER} - DB_USERNAME=${DB_USERNAME}
- DB_PASS=${DB_PASS} - DB_PASSWORD=${DB_PASSWORD}
# Redis # Redis
- REDIS_HOST=redis - REDIS_HOST=redis
- REDIS_PORT=6379 - REDIS_PORT=6379
@@ -149,20 +156,20 @@ services:
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
command: php console.php queue:work --queue=default --timeout=${QUEUE_WORKER_TIMEOUT:-60} command: php console.php queue:work --queue=default --timeout=${QUEUE_WORKER_TIMEOUT:-60}
healthcheck: healthcheck:
test: ["CMD-SHELL", "pgrep -f 'queue:work' || exit 1"] test: ["CMD-SHELL", "php -r 'exit(0);' && test -f /var/www/html/console.php || exit 1"]
interval: 60s interval: 60s
timeout: 10s timeout: 10s
retries: 3 retries: 3
start_period: 30s start_period: 30s
depends_on: depends_on:
app: app:
condition: service_healthy condition: service_started
redis: redis:
condition: service_healthy condition: service_started
# Scheduler (Cron Jobs) # Scheduler (Cron Jobs)
scheduler: scheduler:
image: git.michaelschiemer.de:5000/framework:latest image: registry.michaelschiemer.de/framework:latest
container_name: scheduler container_name: scheduler
restart: unless-stopped restart: unless-stopped
networks: networks:
@@ -174,9 +181,9 @@ services:
# Database # Database
- DB_HOST=${DB_HOST:-postgres} - DB_HOST=${DB_HOST:-postgres}
- DB_PORT=${DB_PORT:-5432} - DB_PORT=${DB_PORT:-5432}
- DB_NAME=${DB_NAME} - DB_DATABASE=${DB_DATABASE}
- DB_USER=${DB_USER} - DB_USERNAME=${DB_USERNAME}
- DB_PASS=${DB_PASS} - DB_PASSWORD=${DB_PASSWORD}
# Redis # Redis
- REDIS_HOST=redis - REDIS_HOST=redis
- REDIS_PORT=6379 - REDIS_PORT=6379
@@ -188,18 +195,20 @@ services:
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
command: php console.php scheduler:run command: php console.php scheduler:run
healthcheck: healthcheck:
test: ["CMD-SHELL", "pgrep -f 'scheduler:run' || exit 1"] test: ["CMD-SHELL", "php -r 'exit(0);' && test -f /var/www/html/console.php || exit 1"]
interval: 60s interval: 60s
timeout: 10s timeout: 10s
retries: 3 retries: 3
start_period: 30s start_period: 30s
depends_on: depends_on:
app: app:
condition: service_healthy condition: service_started
redis: redis:
condition: service_healthy condition: service_started
volumes: volumes:
app-code:
name: app-code
app-storage: app-storage:
name: app-storage name: app-storage
app-logs: app-logs:
@@ -211,5 +220,5 @@ networks:
traefik-public: traefik-public:
external: true external: true
app-internal: app-internal:
external: true
name: app-internal name: app-internal
driver: bridge

View File

@@ -475,19 +475,45 @@ Security headers are applied via Traefik's `default-chain@file` middleware:
## Docker Daemon Configuration ## Docker Daemon Configuration
### Configure Docker to Trust Registry ### Registry Access Methods
On machines that will push/pull from registry: The registry is accessible via two methods:
1. **HTTPS via Traefik**: `registry.michaelschiemer.de` (recommended)
- Uses SSL/TLS encryption
- No insecure registry configuration needed
- Preferred for production use
2. **HTTP Direct**: `registry.michaelschiemer.de`
- Direct access to registry port
- Requires insecure registry configuration
- Useful for internal/local access
### Option 1: Using HTTPS Endpoint (Recommended)
No Docker daemon configuration needed. Just login and push:
```bash
# Login via HTTPS endpoint
docker login registry.michaelschiemer.de
# Push images
docker push registry.michaelschiemer.de/framework:latest
```
### Option 2: Using HTTP Endpoint (Direct Access)
If you need to use `registry.michaelschiemer.de`, configure Docker to allow insecure registries:
```bash ```bash
# Edit daemon.json # Edit daemon.json
sudo nano /etc/docker/daemon.json sudo nano /etc/docker/daemon.json
``` ```
Add: Add `registry.michaelschiemer.de` to `insecure-registries`:
```json ```json
{ {
"insecure-registries": [], "insecure-registries": ["registry.michaelschiemer.de"],
"registry-mirrors": [], "registry-mirrors": [],
"log-driver": "json-file", "log-driver": "json-file",
"log-opts": { "log-opts": {
@@ -497,7 +523,7 @@ Add:
} }
``` ```
**Note**: No need to add registry to `insecure-registries` since we use SSL. **Note**: Only add to `insecure-registries` if using the HTTP endpoint. Use HTTPS endpoint (`registry.michaelschiemer.de`) to avoid insecure registry configuration.
```bash ```bash
# Restart Docker # Restart Docker

View File

@@ -1,51 +0,0 @@
[mysqld]
# Security Configuration for MariaDB
# This file hardens the database server for production use
# Network Security
bind-address = 0.0.0.0
skip-networking = false
skip-name-resolve = true
# Connection Security
max_connections = 100
max_connect_errors = 10
max_user_connections = 50
# SSL/TLS Configuration (Enable in production)
# ssl-ca = /etc/mysql/ssl/ca-cert.pem
# ssl-cert = /etc/mysql/ssl/server-cert.pem
# ssl-key = /etc/mysql/ssl/server-key.pem
# require_secure_transport = ON
# Authentication Security
default_authentication_plugin = mysql_native_password
# Logging Security
log-error = /var/log/mysql/error.log
general_log = ON
general_log_file = /var/log/mysql/general.log
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
# Disable dangerous functions
secure_file_priv = ""
local_infile = OFF
# Performance & Resource Limits
max_allowed_packet = 64M
innodb_buffer_pool_size = 256M
innodb_log_file_size = 64M
query_cache_size = 64M
query_cache_limit = 2M
# Character Set
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4

View File

@@ -0,0 +1,85 @@
#!/bin/bash
# Quick test without Docker containers - just check files
echo "🧪 Quick Git Deployment Test"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Test 1: Entrypoint Script
echo "1⃣ Checking entrypoint.sh..."
if grep -q "GIT_REPOSITORY_URL" docker/entrypoint.sh; then
echo " ✅ GIT_REPOSITORY_URL found"
else
echo " ❌ GIT_REPOSITORY_URL NOT found"
fi
if grep -q "git clone" docker/entrypoint.sh; then
echo " ✅ git clone found"
else
echo " ❌ git clone NOT found"
fi
if grep -q "composer install" docker/entrypoint.sh; then
echo " ✅ composer install found"
else
echo " ❌ composer install NOT found"
fi
echo ""
# Test 2: Dockerfile
echo "2⃣ Checking Dockerfile.production..."
if grep -q "git" Dockerfile.production; then
echo " ✅ git in Dockerfile"
else
echo " ❌ git NOT in Dockerfile"
fi
if grep -q "composer" Dockerfile.production; then
echo " ✅ composer in Dockerfile"
else
echo " ❌ composer NOT in Dockerfile"
fi
if grep -q "entrypoint.sh" Dockerfile.production; then
echo " ✅ entrypoint.sh in Dockerfile"
else
echo " ❌ entrypoint.sh NOT in Dockerfile"
fi
echo ""
# Test 3: Docker Compose
echo "3⃣ Checking docker-compose.yml..."
if grep -q "GIT_REPOSITORY_URL" deployment/stacks/application/docker-compose.yml; then
echo " ✅ GIT_REPOSITORY_URL in docker-compose.yml"
else
echo " ❌ GIT_REPOSITORY_URL NOT in docker-compose.yml"
fi
echo ""
# Test 4: Ansible Template
echo "4⃣ Checking Ansible template..."
if grep -q "GIT_REPOSITORY_URL" deployment/ansible/templates/application.env.j2; then
echo " ✅ GIT_REPOSITORY_URL in Ansible template"
else
echo " ❌ GIT_REPOSITORY_URL NOT in Ansible template"
fi
echo ""
# Test 5: Show entrypoint Git section
echo "5⃣ Entrypoint Git section (first 10 lines):"
echo " ────────────────────────────────────────────────────"
grep -A 10 "Git Clone/Pull functionality" docker/entrypoint.sh | head -12 | sed 's/^/ /'
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Quick test complete!"
echo ""
echo "📝 Next steps:"
echo " 1. Image bauen: docker build -f Dockerfile.production -t registry.michaelschiemer.de/framework:latest ."
echo " 2. Git-Variablen in .env setzen (auf Production Server)"
echo " 3. Container neu starten: docker compose restart app"
echo " 4. Logs prüfen: docker logs app | grep -E '(Git|Clone|Pull)'"