monitor/README_UPDATE.md
fds2610-bot 6bad9b470c Auto-Update per Push-Webhook fuer Produktionsserver einrichten
deploy-webhook.py laeuft auf dem Host, prueft eingehende Codeberg-Webhooks per
HMAC-Signatur (analog zu POST /api/v1/webhooks/codeberg) und stoesst bei einem
Push auf main - also nach jedem manuell gemergten PR - das bereits vorhandene
update.sh an. README_UPDATE.md dokumentiert die dafuer noetigen manuellen
Vorarbeiten auf dem Server (Checkout, Docker, systemd-Unit, Webhook-Einrichtung).

Schliesst #36
2026-08-04 12:20:41 +02:00

5.6 KiB

Auto-Update auf einem Produktionsserver

Dieses Dokument beschreibt, wie ein bereits laufendes monitor auf einem Produktionsserver sich selbst aktualisiert, sobald der Repo-Besitzer einen Pull Request nach main mergt. Anders als im parallelen Agent-Projekt gibt es hier keine Trennung zwischen einem unveraenderlichen "Bootstrap"-Updater und dem eigentlichen Projekt-Code - update.sh gehoert direkt zum Projekt und wird bei jedem Update mit aktualisiert.

Bausteine

  • update.sh (Projekt-Wurzel) - holt die neueste Version des konfigurierten Branches per git pull --ff-only, baut die Docker-Images neu, startet api, web und sync neu und fuehrt (per Default) die Testsuiten aus. Kann jederzeit auch manuell aufgerufen werden, siehe Kommentar am Kopf der Datei fuer die Umgebungsvariablen UPDATE_REMOTE, UPDATE_BRANCH, UPDATE_RUN_TESTS.
  • deploy-webhook.py (Projekt-Wurzel) - kleiner HTTP-Server (nur Python-Standardbibliothek, keine Abhaengigkeiten) auf Basis von http.server. Prueft eingehende Codeberg-Webhooks per HMAC-Signatur (X-Forgejo-Signature/X-Gitea-Signature, analog zum bestehenden POST /api/v1/webhooks/codeberg aus API.md) und ruft bei einem Push auf den konfigurierten Branch update.sh auf. Laeuft auf dem Host, nicht im Docker-Compose-Stack
    • update.sh selbst ruft docker compose auf dem Host auf, das waere aus einem Container heraus nur mit riskantem Zugriff auf den Docker-Socket moeglich.
  • deploy/monitor-deploy-webhook.service - systemd-Unit-Vorlage, um deploy-webhook.py dauerhaft im Hintergrund laufen zu lassen.

Manuelle Vorarbeiten auf dem Server

Diese Schritte sind einmalig und nicht Teil dieses Repos (unterschiedlich je nach Server), daher hier nur als Checkliste:

  1. Repo auskecken. git clone https://codeberg.org/fds2610/monitor.git (oder per SSH, falls Push-Zugangsdaten fuer git pull als Deploy-Key/SSH-Key eingerichtet werden) nach z.B. /opt/monitor, Branch main ausgecheckt. Der Arbeitsbaum muss beim Update sauber sein - update.sh bricht kontrolliert ab, wenn lokale Aenderungen vorhanden sind, statt sie zu ueberschreiben.
  2. Docker + Docker Compose installieren (docker compose version muss funktionieren). Der Benutzer, unter dem deploy-webhook.py laeuft, braucht Mitgliedschaft in der docker-Gruppe (oder aequivalente Rechte), um docker compose ohne sudo aufzurufen.
  3. Python 3 installieren (Standardbibliothek genuegt, keine weiteren Pakete noetig) - mail_fds.py im selben Repo setzt das ohnehin schon voraus.
  4. .env anlegen aus .env.example, insbesondere MONITOR_ADMIN_API_KEY, MONITOR_API_BASE und die neuen Variablen MONITOR_DEPLOY_WEBHOOK_SECRET, MONITOR_DEPLOY_WEBHOOK_PORT, MONITOR_DEPLOY_WEBHOOK_BRANCH (Details siehe dort). Das Secret z.B. mit openssl rand -hex 32 erzeugen.
  5. systemd-Unit einrichten:
    sudo cp deploy/monitor-deploy-webhook.service /etc/systemd/system/
    sudo $EDITOR /etc/systemd/system/monitor-deploy-webhook.service   # Pfade/User/Group anpassen
    sudo systemctl daemon-reload
    sudo systemctl enable --now monitor-deploy-webhook
    sudo systemctl status monitor-deploy-webhook
    
  6. Port/Proxy freischalten. deploy-webhook.py lauscht auf MONITOR_DEPLOY_WEBHOOK_PORT (Default 9099) auf allen Interfaces. Analog zum bestehenden Codeberg-Sync-Webhook muss Proxy/Firewall eingehende Anfragen von Codeberg an diesen Port (bzw. an einen dahinter liegenden Reverse-Proxy-Pfad) durchlassen - alle anderen Dienste (api, web, sync) brauchen dafuer keine Aenderung.
  7. Webhook in Codeberg einrichten (macht der Repo-Besitzer manuell, siehe Issue #36): Repo-Einstellungen -> Webhooks -> Forgejo, Ziel-URL auf deploy-webhook.py (Port aus Schritt 6, ggf. per Proxy auf https://... gemappt), Content-Type application/json, Secret wie in .env (MONITOR_DEPLOY_WEBHOOK_SECRET), Ereignis nur "Push". Ein Merge erzeugt immer einen Push auf den Ziel-Branch, ein eigenes "Pull Request merged"-Event ist daher nicht noetig.

Testen

Zustellung testen (Codeberg schickt beim Anlegen automatisch ein ping-Event, sichtbar unter "Letzte Zustellungen" im Webhook selbst). Manuell mit korrekter Signatur:

SECRET=<MONITOR_DEPLOY_WEBHOOK_SECRET aus .env>
BODY='{"ref":"refs/heads/main"}'
SIG=$(python3 -c "import hmac,hashlib,sys; print(hmac.new(sys.argv[1].encode(), sys.argv[2].encode(), hashlib.sha256).hexdigest())" "$SECRET" "$BODY")
curl -i -X POST "http://<server>:9099/" \
  -H "X-Forgejo-Event: push" \
  -H "X-Forgejo-Signature: $SIG" \
  -d "$BODY"

Antwort 202 {"status": "update gestartet"} bedeutet, dass update.sh im Hintergrund laeuft. Der Verlauf landet in MONITOR_DEPLOY_LOG_FILE (Default: deploy-webhook.log neben deploy-webhook.py) sowie im systemd-Journal (journalctl -u monitor-deploy-webhook -f).

Sicherheit

Der Endpunkt ist wie POST /api/v1/webhooks/codeberg ohne Secret grundsaetzlich geschlossen (401) und akzeptiert nur Anfragen mit gueltiger HMAC-Signatur. Er loest im Erfolgsfall lediglich denselben git pull --ff-only + Rebuild aus, den ein Server-Betreiber auch manuell per ./update.sh anstossen wuerde - er bringt also keinen Code auf den Server, der nicht bereits reviewt und manuell nach main gemergt wurde. Diese manuelle Merge-Hürde ist laut Repo-Besitzer (Issue #36) als alleinige Sicherheitsmassnahme ausreichend; zusaetzliche Branch-Protection-Einstellungen im Codeberg-Repo (z.B. kein direkter Push nach main) bleiben trotzdem empfehlenswert, sind aber eine manuelle Repo-Einstellung und nicht Teil dieses Skripts.