2 ADR-001-Cloudflare-Tunnel-Webhook-Infrastructure
Frank Hildebrandt edited this page 2026-07-15 20:16:58 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

ADR-001: Cloudflare Tunnel für Webhook-Infrastruktur

Status: Vorgeschlagen → Genehmigt (2026-07-15) — revidiert Datum: 2026-07-15 (revidiert) Autor: Hermes Agent + frank Kontext: #65, #66

Kontext

Streamertool ist eine lokale Tauri 2 Desktop-App für Streamer. Für die Integration von Drittanbieter-Diensten (Ko-fi, Patreon, PayPal, Stripe) müssen Webhooks empfangen werden — HTTP-POST-Requests von externen Servern an die App.

Da die App lokal auf dem Rechner des Streamers läuft (ohne öffentliche IP, hinter NAT/Firewall), muss ein Tunnel eine öffentlich erreichbare HTTPS-URL auf den lokalen Server bereitstellen.

Anforderungsänderung (Revision)

Die ursprüngliche Spezifikation ging von einem manuellen cloudflared-Setup mit LaunchAgent aus. Nach erneuter Analyse wurde klar:

Kriterium Alt (LaunchAgent) Neu (In-App-Integration)
Setup Manuell (brew install, Terminal) Setup-Assistent im Dashboard
Autostart System-Daemon (LaunchAgent) App-Lifecycle (mit der App)
Dependencies Externes cloudflared Gebundeltes Binary im Installer
Plattform-Fokus macOS Windows (AMD64) — primär
Dashboard Externes Log-Monitoring Integrierter Status + Log-Viewer
Sicherheit Klartext-Files OS-Keychain (SecretStore)

Ziel: Der Tunnel ist ein vollständig integriertes Feature — kein Terminal, kein manuelles cloudflared, keine externen Abhängigkeiten.

Entscheidung

Cloudflare Tunnel (cloudflared) wird als Tunnel-Lösung eingesetzt, vollständig integriert in die Streamertool-App.

Architektur

┌─────────────────────────────────────────────────────┐
│ Streamertool (Tauri 2 Desktop-App)                   │
│                                                      │
│  ┌──────────────────┐   ┌─────────────────────────┐  │
│  │ TunnelManager    │   │ Webhook-Server (:3443)  │  │
│  │ (Lifecycle-Task) │──▶│ (Rust Axum Server)      │  │
│  │                  │   │                         │  │
│  │ cloudflared      │   │ POST /webhooks/kofi     │  │
│  │ Subprocess       │   │ POST /webhooks/patreon  │  │
│  └────────┬─────────┘   │ POST /webhooks/paypal   │  │
│           │             └───────────┬─────────────┘  │
│           │                         │                 │
│  ┌────────▼─────────────────────────▼──────────┐     │
│  │ AppState                                    │     │
│  │  • db (SQLite Settings)                     │     │
│  │  • secrets (OS-Keychain)                    │     │
│  │  • event_bus (EventBus)                     │     │
│  └────────────────────────────────────────────┘     │
└──────────────────────┬──────────────────────────────┘
                       │
            ┌──────────▼──────────┐
            │ Cloudflare Tunnel   │
            │ (cloudflared)       │
            │ HTTPS → localhost   │
            └─────────────────────┘
                       ▲
           Ko-fi ──────┘
           Patreon ────┐
           PayPal ─────┤
           Stripe ─────┘

Komponenten

Komponente Beschreibung Datei
TunnelManager State Machine (Unconfigured → Configured → Running → Stopped) src-tauri/src/tunnel/mod.rs
BinaryManager Findet/gibt/verifiziert cloudflared Binary src-tauri/src/tunnel/binary.rs
ConfigManager Generiert config.yml, verwaltet Credential-Files src-tauri/src/tunnel/config.rs
Wizard OAuth-Login-Flow, Tunnel-Erstellung src-tauri/src/tunnel/wizard.rs
Platform Plattform-Pfade, Prozess-Start src-tauri/src/tunnel/platform.rs
API Status-Endpunkte src-tauri/src/server/api/tunnel.rs
Frontend Dashboard + Setup-Wizard src/pages/Tunnel.tsx

Lifecycle

App-Start
  │
  ├── bootstrap()
  │     ├── DB-Migrationen
  │     ├── SecretStore laden
  │     ├── TunnelManager::load() — Config aus DB + Secrets
  │     └── Wenn tunnel.enabled → lifecycle.spawn("tunnel", ...)
  │
  ├── Tunnel-Prozess (Background)
  │     ├── cloudflared tunnel run --config ...
  │     ├── Log-Pufferung (letzte 100 Zeilen)
  │     └── Event-Bus-Publikation bei Status-Wechseln
  │
  └── shutdown()
        ├── TunnelManager::stop()
        │     ├── SIGTERM → cloudflared
        │     ├── 5s Timeout → SIGKILL
        │     └── Log-Eintrag
        └── cleanup()

Bundling-Strategie

Primär: Windows AMD64 (NSIS-Installer) Sekundär: macOS ARM64/AMD64 (DMG)

Plattform Quelle Pfad
Windows cloudflared-windows-amd64.exe vom GitHub Release <AppData>\bin\cloudflared.exe
macOS cloudflared-darwin-amd64 / cloudflared-darwin-arm64 <AppSupport>/bin/cloudflared

Fallback bei fehlender Binary: Auto-Download von Cloudflare GitHub Releases mit SHA-256-Verifikation.

Warum kein systemnaher Daemon?

  • LaunchAgent/systemd/user-Service wäre getrennt von der App → kein Dashboard, kein Lifecycle
  • App-Lifecycle ist einfacher — Tunnel läuft nur wenn die App läuft
  • Bei App-Neustart: Webhook-Registrierung muss ohnehin erneuert werden
  • Windows Nutzer sind systemd/LaunchAgent nicht gewohnt → App-Integration ist nutzerfreundlicher

Konsequenzen

Positiv

  • Keine manuelle Installation — Binary ist gebundelt oder wird automatisch geladen
  • Setup-Assistent — auch technisch nicht versierte Streamer können einrichten
  • Dashboard-Integration — Status, URL, Logs, Start/Stopp aus einer Hand
  • Lifecycle-gesteuert — Tunnel startet/stoppt mit der App, kein zusätzlicher Service
  • Sicher — Tokens in OS-Keychain (via SecretStore), nicht in Klartext-Konfig
  • Windows-first — optimiert für die Hauptzielgruppe

Negativ

⚠️ Binary-Größecloudflared.exe ~15 MB zusätzlich im Bundle ⚠️ Cloudflare-Account nötig — aber kostenlos, einmalige Anmeldung ⚠️ Browser-OAuth — Ersteinrichtung erfordert Browser-Öffnen ⚠️ Nicht ohne GUI — Tunnel-Start nur über Dashboard möglich (kein Headless-Betrieb)

Risiken & Mitigation

Risiko Wahrscheinlichkeit Mitigation
Cloudflare-Ausfall Sehr selten Webhook-Anbieter retryen automatisch
cloudflared-Update bricht API Selten Pinning auf getestete Version, SHA-256-Check
Token läuft ab Selten (Jahre) Wizard erneuert Token bei Bedarf
Binary fehlt nach Update Mittel SHA-256-Check + Auto-Download-Fallback
Windows Defender blockiert Niedrig Signierte Binary, MSI/NSIS-Installer

Implementierung

Phase 1 — Grundstruktur (Rust Backend)

  • src-tauri/src/tunnel/mod.rs — TunnelManager + State Machine
  • src-tauri/src/tunnel/binary.rs — Binary-Management
  • src-tauri/src/tunnel/config.rs — Config-Generierung
  • src-tauri/src/tunnel/platform.rs — Plattform-Pfade

Phase 2 — Lifecycle & API

  • Integration in AppState, lib.rs
  • Tauri-Commands: get_tunnel_status, start_tunnel, stop_tunnel
  • API: GET /api/tunnel, POST /api/tunnel/start, POST /api/tunnel/stop

Phase 3 — Setup-Wizard

  • src-tauri/src/tunnel/wizard.rs — OAuth-Flow
  • Frontend: 4-Schritt-Wizard-Dialog

Phase 4 — Dashboard

  • Frontend: Tunnel-Seite in Settings
  • Dashboard-Status-Karte
  • Log-Viewer

Phase 5 — Bundling & Build

  • Download-Script für CI
  • Tauri-Resource-Integration
  • Windows NSIS + macOS DMG

Verwandte ADRs

(noch keine — dies ist der erste ADR)

Quellen


Dieser ADR wurde revidiert am 2026-07-15. Die ursprüngliche Version spezifizierte ein manuelles LaunchAgent-Setup. Die Revision definiert eine vollständige In-App-Integration mit Windows-Fokus und gebundeltem Binary.