Files
kbcrm/Dokumentationen/Deployment-Anleitung.md
T
gg 40ad0e1ba9 refactor(deploy): Image-Versionen fest in Dockerfiles verankern
ARG-Variablen durch feste Werte in FROM ersetzt — nicht per .env
ueberschreibbar. PYTHON_VERSION, NODE_VERSION, NPM_VERSION,
NGINX_VERSION aus .env, env-sample und Compose-Dateien entfernt.
Deployment-Anleitung erstellt und entsprechend angepasst.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-13 19:12:14 +02:00

423 lines
12 KiB
Markdown

# Anleitung: Automatisches Deployment einrichten
Diese Anleitung richtet sich an den Administrator des Deploy-Servers.
Sie beschreibt, wie der automatische Deploy-Mechanismus fuer KB-CRM
eingerichtet und betrieben wird.
---
## 1. Architektur ueberblick
```
Entwickler
│ git push origin main
▼
┌─────────────────┐
│ Git-Remote │ (z.B. Gitea auf git.everdc.eu)
└────────┬────────┘
│ Webhook oder post-receive Hook
▼
┌─────────────────┐
│ Deploy-Server │
│ (Deploy-Script) │
└────────┬────────┘
│
┌──────────┴──────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Stufe 1: TEST │ │ Stufe 2: PROD │
│ (automatisch) │ │ (manuell) │
└─────────────────┘ └─────────────────┘
```
**Prinzip:**
- Jeder `git push` auf `main` loest automatisch ein Deployment auf dem
Test-Server aus (Stufe 1).
- Nach erfolgreicher Verifikation wird manuell auf den Prod-Server
deployt (Stufe 2).
- In Prod wird der gesamte Code (Python + TypeScript) in das Docker-Image
gebaut. Es wird kein Node.js, npm oder Python-venv auf dem Server benoetigt.
- Der Deploy-Server benoetigt nur: `git`, `docker` und `docker compose`.
---
## 2. Voraussetzungen auf dem Deploy-Server
Folgende Software muss installiert sein:
| Software | Version | Zweck |
|---|---|---|
| `git` | aktuell | Code vom Remote-Repository holen |
| `docker` | aktuell | Container bauen und starten |
| `docker compose` | v2+ | Multi-Container-Orchestrierung |
| `curl` | aktuell | Health-Check nach Deploy |
Docker Compose muss als Plugin installiert sein (Befehl: `docker compose`,
nicht `docker-compose`).
---
## 3. Verzeichnisstruktur auf dem Deploy-Server
Es werden zwei Umgebungen (test-prod und prod) parallel betrieben:
```
/opt/kbcrm/
├── test-prod/
│ ├── repo/ ← git clone des Repos
│ └── .env ← test-prod Umgebung (eigene Ports, eigene DB)
├── prod/
│ ├── repo/
│ └── .env ← prod Umgebung
└── scripts/
├── deploy-kbcrm-test.sh ← aus dem Repo (scripts/)
└── deploy-kbcrm-prod.sh ← aus dem Repo (scripts/)
```
Die SQLite-Datenbanken liegen ausserhalb des Repos in einem bind-mount
(`PYTHON_DB_DIR`), der beim Deploy nicht beruehrt wird.
---
## 4. Einrichtung: Schritt fuer Schritt
### 4.1. Repositories klonen
```bash
sudo mkdir -p /opt/kbcrm/test-prod /opt/kbcrm/prod
# Test-Prod Repository
sudo git clone https://git.everdc.eu/chmln-app-dev/kbcrm /opt/kbcrm/test-prod/repo
# Prod Repository
sudo git clone https://git.everdc.eu/chmln-app-dev/kbcrm /opt/kbcrm/prod/repo
```
### 4.2. `.env`-Dateien anlegen
Kopieren Sie die Vorlage aus dem Repo und passen Sie die Werte an:
```bash
# Test-Prod
cp /opt/kbcrm/test-prod/repo/env-sample /opt/kbcrm/test-prod/.env
# Prod
cp /opt/kbcrm/prod/repo/env-sample /opt/kbcrm/prod/.env
```
### 4.3. `.env` fuer Test-Prod anpassen
```bash
vi /opt/kbcrm/test-prod/.env
```
Folgende Einstellungen muessen angepasst werden:
```bash
# WICHTIG: BUILD_ENVIRONMENT muss in den .env-Dateien auf dem Deploy-Server
# NICHT gesetzt werden. Die Deploy-Scripts rufen docker compose explizit
# mit -f docker-compose.prod.yaml auf und ignorieren COMPOSE_FILE.
# Daher kann BUILD_ENVIRONMENT und COMPOSE_FILE aus der .env geloescht
# oder ignoriert werden.
# NGINX-Server
NGINX_USE_SSL=true
NGINX_HOST_PORT=8443 # eigener Port fuer Test-Prod
NGINX_SERVER_NAME=test.kbp_crm.mylocal.de
# NGINX_STATIC_DIR und NGINX_CONFIG_TEMPLATE_DIR werden in Prod nicht
# benoetigt (statische Dateien und Templates sind im Image).
NGINX_CERTS=/opt/kbcrm/test-prod/certs # Pfad zu SSL-Zertifikaten
NGINX_CERT=test-wildcard.mylocal.crt
NGINX_CERT_KEY=test-wildcard.mylocal.key
# Python App-Server
PYTHON_DB_DIR=/opt/kbcrm/test-prod/data # eigene DB fuer Test-Prod
# OIDC-Settings anpassen (ggf. separater OIDC-Client fuer Test)
ZITADEL_ISSUER=https://id.vmlx.de
ZITADEL_CLIENT_ID=<test-client-id>
ZITADEL_CLIENT_SECRET=<test-client-secret>
ZITADEL_REDIRECT_URI=https://test.kbp_crm.mylocal.de/auth/callback
```
### 4.4. `.env` fuer Prod anpassen
```bash
vi /opt/kbcrm/prod/.env
```
```bash
NGINX_HOST_PORT=443 # Produktions-Port
NGINX_SERVER_NAME=kbp_crm.mylocal.de
NGINX_CERTS=/opt/kbcrm/prod/certs
NGINX_CERT=wildcard.mylocal.crt
NGINX_CERT_KEY=wildcard.mylocal.key
PYTHON_DB_DIR=/opt/kbcrm/prod/data # eigene DB fuer Prod
ZITADEL_REDIRECT_URI=https://kbp_crm.mylocal.de/auth/callback
```
### 4.5. Datenbank-Verzeichnisse erstellen
```bash
sudo mkdir -p /opt/kbcrm/test-prod/data
sudo mkdir -p /opt/kbcrm/prod/data
```
### 4.6. SSL-Zertifikate ablegen
Kopieren Sie die Zertifikate in die in `.env` angegebenen Verzeichnisse:
```bash
sudo mkdir -p /opt/kbcrm/test-prod/certs /opt/kbcrm/prod/certs
sudo cp wildcard.mylocal.crt wildcard.mylocal.key /opt/kbcrm/test-prod/certs/
sudo cp wildcard.mylocal.crt wildcard.mylocal.key /opt/kbcrm/prod/certs/
```
### 4.7. Deploy-Scripts kopieren
Die Scripts liegen im Repo unter `scripts/`. Kopieren Sie sie an einen
zentralen Ort:
```bash
sudo mkdir -p /opt/kbcrm/scripts
sudo cp /opt/kbcrm/test-prod/repo/scripts/deploy-kbcrm-test.sh /opt/kbcrm/scripts/
sudo cp /opt/kbcrm/prod/repo/scripts/deploy-kbcrm-prod.sh /opt/kbcrm/scripts/
sudo chmod +x /opt/kbcrm/scripts/*.sh
```
Passen Sie die Pfad-Variablen am Anfang der Scripts an, falls Ihre
Verzeichnisstruktur abweicht.
---
## 5. Git-Hook einrichten (automatisches Test-Deploy)
### Variante A: post-receive Hook (direkt auf dem Git-Server)
Wenn Shell-Zugang zum Git-Server besteht:
```bash
# Auf dem Git-Server, im bare Repository:
vi /srv/git/kbcrm.git/hooks/post-receive
```
```bash
#!/bin/bash
while read oldrev newrev ref; do
if [ "$ref" = "refs/heads/main" ]; then
ssh deploy-user@deploy-server "/opt/kbcrm/scripts/deploy-kbcrm-test.sh"
fi
done
```
```bash
chmod +x /srv/git/kbcrm.git/hooks/post-receive
```
### Variante B: Webhook (empfohlen fuer Gitea)
1. In Gitea: Repository-Einstellungen -> Webhooks -> Webhook hinzufuegen
2. URL: `http://deploy-server:9000/webhook` (Beispiel)
3. Content-Type: `application/json`
4. Trigger: "Push Events" (nur auf `main`)
5. Auf dem Deploy-Server: kleiner HTTP-Listener, der den Webhook entgegennimmt
und das Deploy-Script startet.
Beispiel fuer einen einfachen Webhook-Listener (systemd-Service mit Python):
```python
# /opt/kbcrm/scripts/webhook-listener.py
from http.server import HTTPServer, BaseHTTPRequestHandler
import subprocess
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
subprocess.run(["/opt/kbcrm/scripts/deploy-kbcrm-test.sh"])
self.send_response(200)
self.end_headers()
HTTPServer(("", 9000), Handler).serve_forever()
```
Systemd-Service:
```ini
# /etc/systemd/system/kbcrm-webhook.service
[Unit]
Description=KB-CRM Deploy Webhook Listener
After=network.target
[Service]
ExecStart=/usr/bin/python3 /opt/kbcrm/scripts/webhook-listener.py
Restart=always
User=deploy-user
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl enable --now kbcrm-webhook
```
---
## 6. Deployment durchfuehren
### 6.1. Automatisches Deploy nach Test-Prod
Wird durch `git push` ausgeloest (sofern Hook eingerichtet). Manuell:
```bash
/opt/kbcrm/scripts/deploy-kbcrm-test.sh
```
Das Script fuehrt folgende Schritte aus:
1. `git pull` (latest main)
2. `docker compose up -d --build` (baut beide Images: NGINX mit TypeScript-
Build und Python mit Anwendungscode)
3. Health-Check
### 6.2. Manuelle Promotion nach Prod
Nach Verifikation auf dem Test-Server:
```bash
/opt/kbcrm/scripts/deploy-kbcrm-prod.sh
```
Das Script fragt eine Bestaetigung ("yes/no") und fuehrt dann den gleichen
Ablauf aus wie das Test-Script, jedoch mit der Prod-`.env`.
### 6.3. Alternative: Git-Tag-basierte Promotion
Statt das Prod-Script manuell aufzurufen, kann ein Git-Tag das Prod-Deploy
ausloesen:
```bash
# Auf dem Entwickler-Rechner:
git tag -a v00.00.02 -m "Release: deploy to prod"
git push origin v00.00.02
```
Der `post-receive`-Hook prueft auf Tags:
```bash
#!/bin/bash
while read oldrev newrev ref; do
if [ "$ref" = "refs/heads/main" ]; then
ssh deploy-user@deploy-server "/opt/kbcrm/scripts/deploy-kbcrm-test.sh"
elif [[ "$ref" = refs/tags/v* ]]; then
ssh deploy-user@deploy-server "/opt/kbcrm/scripts/deploy-kbcrm-prod.sh"
fi
done
```
---
## 7. Wartung und Fehlersuche
### Logs anzeigen
```bash
# Test-Prod
docker compose --env-file /opt/kbcrm/test-prod/.env \
-f /opt/kbcrm/test-prod/repo/docker-compose.prod.yaml logs
# Prod
docker compose --env-file /opt/kbcrm/prod/.env \
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml logs
# Nur Python-Container
docker compose --env-file /opt/kbcrm/prod/.env \
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml logs pythonapp
# Nur NGINX-Container
docker compose --env-file /opt/kbcrm/prod/.env \
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml logs nginx-proxy
```
### Container-Status pruefen
```bash
docker compose --env-file /opt/kbcrm/prod/.env \
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml ps
```
### Manuell in den Container wechseln
```bash
docker compose --env-file /opt/kbcrm/prod/.env \
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml exec pythonapp bash
```
### Rollback
Bei Problemen kann auf einen frueheren Stand zurueckgekehrt werden:
```bash
# Auf dem Deploy-Server:
cd /opt/kbcrm/prod/repo
git log --oneline -10 # frueheren Commit finden
git checkout <commit-hash>
docker compose --env-file /opt/kbcrm/prod/.env \
-f docker-compose.prod.yaml up -d --build
```
### Datenbank sichern
Die SQLite-Datenbanken liegen im bind-mount (`PYTHON_DB_DIR`).
Sicherung:
```bash
cp /opt/kbcrm/prod/data/*.db /backup/kbcrm-prod-$(date +%Y%m%d).db
```
### Docker-Images aufraeumen
Nach mehreren Deploys koennen alte Images Speicher belegen:
```bash
docker image prune -f
```
---
## 8. Uebersicht: `.env`-Variablen fuer Prod
| Variable | Erforderlich | Beschreibung |
|---|---|---|
| `NGINX_USE_SSL` | ja | SSL aktivieren (true/false) |
| `NGINX_HOST_PORT` | ja | Externer Port (443 fuer SSL, 8080 fuer no-SSL) |
| `NGINX_SERVER_NAME` | ja | Server-Name fuer NGINX-Konfiguration |
| `NGINX_CERTS` | ja | Pfad zu SSL-Zertifikaten (bind-mount) |
| `NGINX_CERT` | ja | Zertifikatsdatei |
| `NGINX_CERT_KEY` | ja | Privater Schluessel |
| `NGINX_STATIC_DIR` | nein | Nur in Dev; in Prod im Image |
| `NGINX_CONFIG_TEMPLATE_DIR` | nein | Nur in Dev; in Prod im Image |
| `PYTHON_DB_DIR` | ja | Pfad zu SQLite-Datenbanken (bind-mount) |
| `PYTHON_DEV_DIR` | nein | Nur in Dev |
| `APP_DEBUG` | nein | Nur in Dev; in Prod nicht setzen |
| `BUILD_ENVIRONMENT` | nein | Nicht relevant — Deploy-Scripts geben Compose-Datei explizit an. In .env auf Deploy-Server nicht erforderlich |
| `ZITADEL_*` | ja | OIDC-Konfiguration |
| `COMPOSE_FILE` | nein | Wird von Deploy-Scripts ignoriert |
---
## 9. Checkliste fuer den Admin
- [ ] Docker und Docker Compose installiert
- [ ] Git installiert, Repository geklont (test-prod + prod)
- [ ] `.env`-Dateien erstellt und angepasst (Ports, DB, Zertifikate, OIDC)
- [ ] Datenbank-Verzeichnisse erstellt (`PYTHON_DB_DIR`)
- [ ] SSL-Zertifikate abgelegt (`NGINX_CERTS`)
- [ ] Deploy-Scripts kopiert und ausfuehrbar gemacht
- [ ] Git-Hook oder Webhook eingerichtet (fuer automatisches Test-Deploy)
- [ ] Erster manueller Deploy-Test: `deploy-kbcrm-test.sh`
- [ ] Health-Check erfolgreich: `curl -k https://localhost:8443/health-check`
- [ ] Erster Prod-Deploy: `deploy-kbcrm-prod.sh`
- [ ] Health-Check erfolgreich: `curl -k https://localhost:443/health-check`