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

12 KiB

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

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:

# 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

vi /opt/kbcrm/test-prod/.env

Folgende Einstellungen muessen angepasst werden:

# 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

vi /opt/kbcrm/prod/.env
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

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:

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:

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:

# Auf dem Git-Server, im bare Repository:
vi /srv/git/kbcrm.git/hooks/post-receive
#!/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
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):

# /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:

# /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
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:

/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:

/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:

# 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:

#!/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

# 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

docker compose --env-file /opt/kbcrm/prod/.env \
    -f /opt/kbcrm/prod/repo/docker-compose.prod.yaml ps

Manuell in den Container wechseln

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:

# 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:

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:

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