Webhook-Infrastruktur: Cloudflare Tunnel für HTTPS-Webhook-Empfang #65

Open
opened 2026-07-15 20:04:23 +02:00 by frank · 1 comment
Owner

Kontext

Streamertool benötigt eine Möglichkeit, Webhooks von externen Diensten zu empfangen:

  • Ko-fi: Donations, Subscriptions, Shop-Verkäufe, Commissions
  • Patreon: Members:create/update/delete, Pledge-Events, Goal-Events
  • PayPal IPN: Zahlungsbenachrichtigungen
  • Stripe: Payment Intents, Subscriptions (zukünftig)

All diese Dienste senden Webhooks an eine öffentliche HTTPS-URL. Da streamertool lokal auf dem Rechner des Streamers läuft (Tauri 2 Desktop-App), gibt es keinen öffentlich erreichbaren Server.

Entscheidung

Cloudflare Tunnel (cloudflared) wird als Tunnel-Lösung eingesetzt, um den lokalen Webserver über HTTPS im Internet verfügbar zu machen.

Begründung

  • Kostenlos — keine Traffic-Limits wie bei ngrok (nur 1 GB/Monat im Free-Tier)
  • Feste URL — eigener Hostname via Cloudflare DNS (z.B. webhooks.streamertool.app)
  • HTTPS out-of-the-box — Cloudflare stellt automatisch TLS-Zertifikate aus
  • Zuverlässig — Cloudflare Edge-Netz, läuft wochenlang stabil ohne Neustart
  • Launchd-Integration — kann als macOS-Daemon laufen und überlebt Neustarts
  • Keine öffentliche IP nötig — funktioniert hinter NAT/Firewall

Verworfen

  • ngrok (Free Tier) — URL ändert sich bei jedem Neustart, Datenlimit 1 GB/Monat
  • localtunnel — kein statischer Hostname, öffentliche Instanz unzuverlässig
  • Tailscale Funnel — beta, benötigt Tailscale-Netz, weniger erprobt für Webhooks
  • Eigener Server — widerspricht dem Desktop-App-Ansatz

Aufgaben

1. Cloudflare Tunnel Setup

  • cloudflared als dev-Dependency oder Bundle-Option für macOS
  • Automatische Installation via brew install cloudflared oder Bundle
  • First-Run: cloudflared tunnel login (öffnet Browser für Cloudflare-Login)
  • Tunnel-Konfiguration mit eigenem Hostnamen (z.B. webhooks.streamertool.app)
  • Tunnel verbindet auf localhost:3443 (dedizierter Webhook-Port)

2. macOS Integration (Launchd Service)

  • Automatische Installation als LaunchAgent (~/Library/LaunchAgents/)
  • Tunnel startet automatisch beim Systemstart
  • Tunnel überwacht den Webhook-Port (localhost:3443)
  • Status-Anzeige: läuft / gestoppt / fehler
  • Dashboard: Enable/Disable Tunnel, Tunnel-Status, Letzte Verbindung

3. Dashboard Konfiguration

  • Tunnel-Status (Running/Stopped/Error)
  • URL des öffentlichen Webhook-Endpunkts anzeigen
  • Cloudflare-Login-Status (Token vorhanden/gültig/abgelaufen)
  • cloudflared Version anzeigen
  • Manueller Start/Stopp des Tunnels
  • Log-Ausgabe (letzte 50 Zeilen) für Debugging

4. Sicherheit

  • Tunnel läuft nur wenn der lokale Webhook-Server aktiv ist
  • Secrets/Tokens in macOS Keychain, nicht in Klartext-Konfig
  • Webhook-Empfänger validiert Signaturen (unabhängig vom Tunnel)
  • Tunnel-Konfiguration enthält keine sensiblen Daten

Technische Leitplanken

  • Tunnel-Port: 3443 (dediziert, nicht der Overlay-Server-Port)
  • Webhook-Server: Eigenständiger HTTP-Server in Rust (Actix Web / Axum), kein Teil des Overlay-Servers
  • Startreihenfolge: App startet → Webhook-Server (:3443) → Cloudflare Tunnel → Webhook-Registrierung bei Diensten
  • Konfiguration: Unter settings.jsonwebhooks.tunnel
  • Plattform: Zunächst macOS, später Windows/Linux via systemd/user-Service
  • Dokumentation: ADR im Wiki (siehe /wiki/ADR-001-Cloudflare-Tunnel)

Abhängigkeiten

  • cloudflared (brew / manuelle Installation)
  • Cloudflare Account (kostenlos)
  • Eigene Domain (optional — Cloudflare stellt .trycloudflare.com-Subdomain)

Akzeptanzkriterien

  • Cloudflare Tunnel verbindet localhost:3443 mit öffentlicher HTTPS-URL
  • Tunnel läuft als LaunchAgent und startet automatisch beim Boot
  • Dashboard zeigt Status, URL und Logs an
  • Webhook-Empfänger ist unter der öffentlichen URL erreichbar
  • Tunnel kann im Dashboard gestartet/gestoppt werden
  • Token/Secret wird sicher in der Keychain gespeichert

Verwandte Issues

  • #66 Webhook-Receiver-API (baut auf diesem Tunnel auf)
  • #61 Ko-fi Webhook-System
  • #63 Patreon OAuth & Alert-Overlay
## Kontext Streamertool benötigt eine Möglichkeit, **Webhooks von externen Diensten** zu empfangen: - **Ko-fi**: Donations, Subscriptions, Shop-Verkäufe, Commissions - **Patreon**: Members:create/update/delete, Pledge-Events, Goal-Events - **PayPal IPN**: Zahlungsbenachrichtigungen - **Stripe**: Payment Intents, Subscriptions (zukünftig) All diese Dienste senden Webhooks an eine **öffentliche HTTPS-URL**. Da streamertool lokal auf dem Rechner des Streamers läuft (Tauri 2 Desktop-App), gibt es keinen öffentlich erreichbaren Server. ## Entscheidung **Cloudflare Tunnel (`cloudflared`)** wird als Tunnel-Lösung eingesetzt, um den lokalen Webserver über HTTPS im Internet verfügbar zu machen. ### Begründung - ✅ **Kostenlos** — keine Traffic-Limits wie bei ngrok (nur 1 GB/Monat im Free-Tier) - ✅ **Feste URL** — eigener Hostname via Cloudflare DNS (z.B. `webhooks.streamertool.app`) - ✅ **HTTPS out-of-the-box** — Cloudflare stellt automatisch TLS-Zertifikate aus - ✅ **Zuverlässig** — Cloudflare Edge-Netz, läuft wochenlang stabil ohne Neustart - ✅ **Launchd-Integration** — kann als macOS-Daemon laufen und überlebt Neustarts - ✅ **Keine öffentliche IP nötig** — funktioniert hinter NAT/Firewall ### Verworfen - ❌ **ngrok (Free Tier)** — URL ändert sich bei jedem Neustart, Datenlimit 1 GB/Monat - ❌ **localtunnel** — kein statischer Hostname, öffentliche Instanz unzuverlässig - ❌ **Tailscale Funnel** — beta, benötigt Tailscale-Netz, weniger erprobt für Webhooks - ❌ **Eigener Server** — widerspricht dem Desktop-App-Ansatz ## Aufgaben ### 1. Cloudflare Tunnel Setup - [ ] `cloudflared` als dev-Dependency oder Bundle-Option für macOS - [ ] Automatische Installation via `brew install cloudflared` oder Bundle - [ ] First-Run: `cloudflared tunnel login` (öffnet Browser für Cloudflare-Login) - [ ] Tunnel-Konfiguration mit eigenem Hostnamen (z.B. `webhooks.streamertool.app`) - [ ] Tunnel verbindet auf `localhost:3443` (dedizierter Webhook-Port) ### 2. macOS Integration (Launchd Service) - [ ] Automatische Installation als LaunchAgent (`~/Library/LaunchAgents/`) - [ ] Tunnel startet automatisch beim Systemstart - [ ] Tunnel überwacht den Webhook-Port (`localhost:3443`) - [ ] Status-Anzeige: läuft / gestoppt / fehler - [ ] Dashboard: Enable/Disable Tunnel, Tunnel-Status, Letzte Verbindung ### 3. Dashboard Konfiguration - [ ] Tunnel-Status (Running/Stopped/Error) - [ ] URL des öffentlichen Webhook-Endpunkts anzeigen - [ ] Cloudflare-Login-Status (Token vorhanden/gültig/abgelaufen) - [ ] `cloudflared` Version anzeigen - [ ] Manueller Start/Stopp des Tunnels - [ ] Log-Ausgabe (letzte 50 Zeilen) für Debugging ### 4. Sicherheit - [ ] Tunnel läuft nur wenn der lokale Webhook-Server aktiv ist - [ ] Secrets/Tokens in macOS Keychain, nicht in Klartext-Konfig - [ ] Webhook-Empfänger validiert Signaturen (unabhängig vom Tunnel) - [ ] Tunnel-Konfiguration enthält keine sensiblen Daten ## Technische Leitplanken - **Tunnel-Port**: `3443` (dediziert, nicht der Overlay-Server-Port) - **Webhook-Server**: Eigenständiger HTTP-Server in Rust (Actix Web / Axum), kein Teil des Overlay-Servers - **Startreihenfolge**: App startet → Webhook-Server (`:3443`) → Cloudflare Tunnel → Webhook-Registrierung bei Diensten - **Konfiguration**: Unter `settings.json` → `webhooks.tunnel` - **Plattform**: Zunächst macOS, später Windows/Linux via systemd/user-Service - **Dokumentation**: ADR im Wiki (siehe `/wiki/ADR-001-Cloudflare-Tunnel`) ## Abhängigkeiten - `cloudflared` (brew / manuelle Installation) - Cloudflare Account (kostenlos) - Eigene Domain (optional — Cloudflare stellt `.trycloudflare.com`-Subdomain) ## Akzeptanzkriterien - [ ] Cloudflare Tunnel verbindet `localhost:3443` mit öffentlicher HTTPS-URL - [ ] Tunnel läuft als LaunchAgent und startet automatisch beim Boot - [ ] Dashboard zeigt Status, URL und Logs an - [ ] Webhook-Empfänger ist unter der öffentlichen URL erreichbar - [ ] Tunnel kann im Dashboard gestartet/gestoppt werden - [ ] Token/Secret wird sicher in der Keychain gespeichert ## Verwandte Issues - #66 Webhook-Receiver-API (baut auf diesem Tunnel auf) - #61 Ko-fi Webhook-System - #63 Patreon OAuth & Alert-Overlay
Author
Owner

Cloudflare Tunnel Integration im Tool

🚨 Korrektur & Neuspezifikation

Dieses Issue wurde ursprünglich als "Webhook-Infrastruktur: Cloudflare Tunnel für HTTPS-Webhook-Empfang" angelegt. Nach Analyse der Projektarchitektur und der Nutzeranforderungen wird die Spezifikation grundlegend überarbeitet:

Der Cloudflare Tunnel muss vollständig in das Tool integriert sein — mit einem Einrichtungsassistenten, automatischem Start/Stopp und ohne dass der Nutzer zusätzliche Abhängigkeiten installieren muss. Die meisten Streamer nutzen Windows (AMD64), daher ist Windows der primäre Fokus.


🎯 Ziel

Streamertool integriert Cloudflare Tunnel (cloudflared) als eingebautes Feature:

  • Setup-Assistent im Dashboard (kein Terminal, keine manuelle Konfiguration)
  • Autostart/Stopp mit der App (Lifecycle-gesteuert, kein eigener Service)
  • Keine externen Dependenciescloudflared Binary wird im Bundle mitgeliefert oder automatisch heruntergeladen
  • Dashboard-Integration (Status, URL, Logs, Start/Stopp)
  • Sicher (Token in Keychain, keine Klartext-Konfiguration)

📐 Architektur

Neues Rust-Modul: src-tauri/src/tunnel/

tunnel/
├── mod.rs           # TunnelManager — State Machine, Lifecycle
├── binary.rs        # cloudflared Binary Management (Bundle/Download/Verify)
├── config.rs        # Tunnel-Konfiguration (YAML), Credential-File
├── wizard.rs        # OAuth-Login-Flow (Browser-Öffnen, Token abholen)
└── platform.rs      # Plattform-spezifische Pfade (Windows/macOS)

Integration in bestehende Struktur

Komponente Anbindung
AppState Neues Feld tunnel: Arc<RwLock<TunnelManager>>
Lifecycle Tunnel-Start/Stopp über lifecycle.spawn("tunnel", ...)
Secrets Cloudflare-Tunnel-Token via secrets.set("cloudflare.tunnelToken", ...)
Settings tunnel.enabled, tunnel.port (default 3443), tunnel.hostname in SQLite settings
Tauri-Commands get_tunnel_status, start_tunnel, stop_tunnel, open_tunnel_login, get_tunnel_logs
API-Routes GET /api/tunnel (Status), POST /api/tunnel/start, POST /api/tunnel/stop

State Machine (TunnelManager)

               ┌──────────────┐
               │  Unconfigured │  ← Erstinstallation, kein Account
               └──────┬───────┘
                      │ setup wizard
               ┌──────▼───────┐
               │  Configured   │  ← Token vorhanden, Konfiguration steht
               └──────┬───────┘
                      │ start
               ┌──────▼───────┐
          ┌───▶│   Running     │◀───┐
          │    └──────┬───────┘    │
          │           │ stop      │ start
          │    ┌──────▼───────┐    │
          └────│   Stopped    │────┘
               └──────────────┘
               
               ┌──────────────┐
               │    Error     │ ← Fehlerzustand (recoverable)
               └──────────────┘

🔧 Setup-Assistent (Wizard)

Schritt 1: Cloudflare-Login

  • Button "Bei Cloudflare anmelden" → öffnet Browser mit cloudflared tunnel login
  • Wartet auf die cert.pem (Cloudflare API Token)
  • Zeigt Status: "Angemeldet als [Email]" oder "Nicht angemeldet"

Schritt 2: Tunnel erstellen

  • Name: streamertool-webhooks (voreingestellt)
  • Optional: Eigene Domain (z.B. webhooks.streamertool.app)
  • Fallback: Cloudflare .trycloudflare.com Subdomain

Schritt 3: Port konfigurieren

  • Standard: 3443 (dedizierter Webhook-Port)
  • Verknüpfung mit dem Webhook-Server (Issue #66)

Schritt 4: Autostart

  • "Tunnel automatisch mit der App starten" (Toggle)
  • "Tunnel beim Beenden der App stoppen" (Toggle)

📦 Bundling-Strategie

Windows (AMD64) — Primär

Methode Beschreibung
Bundle im NSIS-Installer cloudflared.exe (~15 MB) als Tauri-Resource in bundle.resources
Fallback: Auto-Download Bei Fehlen: Download von https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe nach %APPDATA%/streamertool/bin/
Signatur-Prüfung SHA-256 Verifikation gegen bekannten Hash
Installationsort %APPDATA%\io.hildebrandt.streamertool\bin\cloudflared.exe

macOS (ARM64/AMD64) — Sekundär

Methode Beschreibung
Bundle als Tauri-Resource cloudflared als Bundle-Resource in bundle.resources
Fallback: Auto-Download curl -L von Cloudflare GitHub Releases
Installationsort ~/Library/Application Support/io.hildebrandt.streamertool/bin/cloudflared

Verifikation

  • SHA-256 Check gegen Hardcoded (oder online abgerufene) Hashes
  • Bei Hash-Mismatch: Warnung, Fallback auf Auto-Download
  • cloudflared version zur Laufzeit prüfen

🖥️ Dashboard-Integration

Neue Seite: "Tunnel" (in der Settings-Navigation)

  • Status-Anzeige: Running / Stopped / Error / Unconfigured
  • Public URL: Anzeige der öffentlichen Webhook-URL (Copy-Button)
  • Cloudflare-Status: Angemeldet als [Email] / Nicht angemeldet
  • Start/Stopp Button: Je nach aktuellem Zustand
  • Log-Viewer: Letzte 50 Zeilen cloudflared Output
  • Konfiguration: Port, Hostname, Autostart-Toggle
  • Einrichtungs-Assistent: "Neu einrichten" Button führt durch Wizard

Dashboard-Übersicht

  • Kleine Status-Karte: Tunnel-Status + URL
  • Fehleranzeige bei Verbindungsproblemen

🔄 Lifecycle-Integration

App-Start

  1. AppState::bootstrap()TunnelManager::load() (Config aus DB + Secrets)
  2. Wenn tunnel.enabled == true und Token vorhanden:
    • lifecycle.spawn("cloudflare-tunnel", tunnel_manager.run())
    • Tunnel-Prozess startet im Hintergrund
  3. Dashboard zeigt "Tunnel läuft" mit URL

App-Shutdown

  1. AppState::shutdown()TunnelManager::stop()
  2. cloudflared Prozess bekommt SIGTERM (oder taskkill auf Windows)
  3. Wartet auf sauberes Beenden (max 5s), dann SIGKILL
  4. Log: "Tunnel gestoppt"

Bei Fehlern

  • Log-Ausgabe in den tunnel-eigenen Log-Puffer (letzte 100 Zeilen)
  • Event: tunnel.error → Event-Bus (für Alarme)
  • Dashboard zeigt Error-Status + Logs

📝 cloudflared Konfiguration

Tunnel-Konfiguration (~/.cloudflared/config.yml — automatisch generiert)

tunnel: <TUNNEL-ID>
credentials-file: <DATA_DIR>/cloudflare/<TUNNEL-ID>.json
ingress:
  - hostname: webhooks.streamertool.app
    service: http://localhost:3443
  - service: http_status:404

Alternativ: Quick-Tunnel (ohne eigene Domain)

cloudflared tunnel --url http://localhost:3443

→ Gibt https://<random>.trycloudflare.com zurück


⚙️ Implementierungsschritte

Phase 1: Grundstruktur (Rust Backend)

  • tunnel/mod.rs — TunnelManager Struct + State Machine
  • tunnel/binary.rs — Binary-Suche (Bundle/DataDir/System-PATH), Auto-Download, SHA-256 Verify
  • tunnel/config.rs — Config-Generierung, Credential-File-Management
  • tunnel/platform.rs — Windows: %APPDATA%, macOS: ~/Library/Application Support
  • Integration in AppState (neues Feld, Shutdown-Reihenfolge)
  • Tauri-Commands: get_tunnel_status, start_tunnel, stop_tunnel

Phase 2: Setup-Wizard

  • tunnel/wizard.rs — OAuth-Flow via cloudflared tunnel login
  • Tunnel-Erstellung via cloudflared tunnel create
  • DNS-Route via cloudflared tunnel route dns
  • Frontend: Wizard-Dialog mit 4 Schritten

Phase 3: Dashboard & API

  • API-Routes: GET /api/tunnel, POST /api/tunnel/start, POST /api/tunnel/stop
  • Frontend: Tunnel-Seite in Settings
  • Frontend: Status-Karte im Dashboard
  • Frontend: Log-Viewer für Tunnel

Phase 4: Bundling & Build

  • cloudflared Download-Script für CI/CD (scripts/download-cloudflared.sh)
  • Tauri-Resource-Integration in tauri.conf.json + Makefile
  • Windows: NSIS-Installer inkludiert cloudflared.exe
  • macOS: DMG enthält cloudflared Binary
  • SHA-256 Hash-Verifikation in tunnel/binary.rs

Phase 5: Autostart & Lifecycle

  • Lifecycle-Integration: Start/Stopp mit der App
  • graceful shutdown (SIGTERM → 5s → SIGKILL/kill)
  • Reconnect bei Absturz (max 3 Versuche)
  • Event-Bus-Publikation bei Status-Änderungen

🔐 Sicherheit

Aspekt Lösung
Cloudflare-Token In SecretStore via OS-Keychain (bereits vorhanden)
Tunnel Credential File Verschlüsselt im App-Datenverzeichnis, nicht in ~/.cloudflared/
Webhook-Port 3443 — nur localhost, nicht im LAN erreichbar
Binary-Integrität SHA-256 Verifikation vor erstem Start
Tunnel-Start Nur wenn Webhook-Server aktiv und Port belegt ist

🌐 Plattform-Strategie

Plattform Priorität Binary-Quelle Autostart
Windows (AMD64) 🔴 P0 Bundle + Fallback-Download App-Lifecycle
macOS (ARM64) 🟡 P1 Bundle + Fallback-Download App-Lifecycle
macOS (AMD64) 🟡 P1 Bundle + Fallback-Download App-Lifecycle
Linux (AMD64) 🟢 P2 App-Binary + Fallback-Download App-Lifecycle

📊 Legacy-API

Die bestehenden API-Endpunkte aus server/mod.rs bleiben unverändert. Neue Tunnel-Endpunkte werden separat unter /api/tunnel/* hinzugefügt, geschützt durch den existierenden admin_auth_middleware.


🔗 Abhängigkeiten & Verwandte Issues

Issue Beziehung
#66 Webhook-Receiver-API — empfängt auf :3443, Tunnel leitet dorthin
#61 Ko-fi Webhook-Integration — nutzt die öffentliche URL
#63 Patreon OAuth & Alert-Overlay — nutzt die öffentliche URL
ADR-001 Wiki: Architektur-Entscheidungen für den Tunnel
#20 Browser-Integration (für OAuth-Login)

Verworfen

  • System-Daemon/Service (LaunchAgent, systemd) — zu komplex, App-Lifecycle reicht
  • ngrok/Localtunnel — unzuverlässig, keine feste URL, Traffic-Limits
  • Eigener Rust-Tunnelcloudflared ist erprobt und von Cloudflare maintained
  • Docker-Container — zu viel Overhead für eine Desktop-App
  • Tailscale Funnel — beta, benötigt separates Tailscale-Konto
# Cloudflare Tunnel Integration im Tool ## 🚨 Korrektur & Neuspezifikation Dieses Issue wurde ursprünglich als "Webhook-Infrastruktur: Cloudflare Tunnel für HTTPS-Webhook-Empfang" angelegt. Nach Analyse der Projektarchitektur und der Nutzeranforderungen wird die Spezifikation **grundlegend überarbeitet**: **Der Cloudflare Tunnel muss vollständig in das Tool integriert sein** — mit einem Einrichtungsassistenten, automatischem Start/Stopp und ohne dass der Nutzer zusätzliche Abhängigkeiten installieren muss. Die meisten Streamer nutzen **Windows (AMD64)**, daher ist Windows der primäre Fokus. --- ## 🎯 Ziel Streamertool integriert Cloudflare Tunnel (`cloudflared`) als **eingebautes Feature**: - **Setup-Assistent** im Dashboard (kein Terminal, keine manuelle Konfiguration) - **Autostart/Stopp** mit der App (Lifecycle-gesteuert, kein eigener Service) - **Keine externen Dependencies** — `cloudflared` Binary wird im Bundle mitgeliefert oder automatisch heruntergeladen - **Dashboard-Integration** (Status, URL, Logs, Start/Stopp) - **Sicher** (Token in Keychain, keine Klartext-Konfiguration) --- ## 📐 Architektur ### Neues Rust-Modul: `src-tauri/src/tunnel/` ``` tunnel/ ├── mod.rs # TunnelManager — State Machine, Lifecycle ├── binary.rs # cloudflared Binary Management (Bundle/Download/Verify) ├── config.rs # Tunnel-Konfiguration (YAML), Credential-File ├── wizard.rs # OAuth-Login-Flow (Browser-Öffnen, Token abholen) └── platform.rs # Plattform-spezifische Pfade (Windows/macOS) ``` ### Integration in bestehende Struktur | Komponente | Anbindung | |---|---| | **`AppState`** | Neues Feld `tunnel: Arc<RwLock<TunnelManager>>` | | **`Lifecycle`** | Tunnel-Start/Stopp über `lifecycle.spawn("tunnel", ...)` | | **`Secrets`** | Cloudflare-Tunnel-Token via `secrets.set("cloudflare.tunnelToken", ...)` | | **Settings** | `tunnel.enabled`, `tunnel.port` (default 3443), `tunnel.hostname` in SQLite settings | | **Tauri-Commands** | `get_tunnel_status`, `start_tunnel`, `stop_tunnel`, `open_tunnel_login`, `get_tunnel_logs` | | **API-Routes** | `GET /api/tunnel` (Status), `POST /api/tunnel/start`, `POST /api/tunnel/stop` | ### State Machine (TunnelManager) ``` ┌──────────────┐ │ Unconfigured │ ← Erstinstallation, kein Account └──────┬───────┘ │ setup wizard ┌──────▼───────┐ │ Configured │ ← Token vorhanden, Konfiguration steht └──────┬───────┘ │ start ┌──────▼───────┐ ┌───▶│ Running │◀───┐ │ └──────┬───────┘ │ │ │ stop │ start │ ┌──────▼───────┐ │ └────│ Stopped │────┘ └──────────────┘ ┌──────────────┐ │ Error │ ← Fehlerzustand (recoverable) └──────────────┘ ``` --- ## 🔧 Setup-Assistent (Wizard) ### Schritt 1: Cloudflare-Login - Button "Bei Cloudflare anmelden" → öffnet Browser mit `cloudflared tunnel login` - Wartet auf die `cert.pem` (Cloudflare API Token) - Zeigt Status: "Angemeldet als [Email]" oder "Nicht angemeldet" ### Schritt 2: Tunnel erstellen - Name: `streamertool-webhooks` (voreingestellt) - Optional: Eigene Domain (z.B. `webhooks.streamertool.app`) - Fallback: Cloudflare `.trycloudflare.com` Subdomain ### Schritt 3: Port konfigurieren - Standard: `3443` (dedizierter Webhook-Port) - Verknüpfung mit dem Webhook-Server (Issue #66) ### Schritt 4: Autostart - "Tunnel automatisch mit der App starten" (Toggle) - "Tunnel beim Beenden der App stoppen" (Toggle) --- ## 📦 Bundling-Strategie ### Windows (AMD64) — Primär | Methode | Beschreibung | |---|---| | **Bundle im NSIS-Installer** | `cloudflared.exe` (~15 MB) als Tauri-Resource in `bundle.resources` | | **Fallback: Auto-Download** | Bei Fehlen: Download von `https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe` nach `%APPDATA%/streamertool/bin/` | | **Signatur-Prüfung** | SHA-256 Verifikation gegen bekannten Hash | | **Installationsort** | `%APPDATA%\io.hildebrandt.streamertool\bin\cloudflared.exe` | ### macOS (ARM64/AMD64) — Sekundär | Methode | Beschreibung | |---|---| | **Bundle als Tauri-Resource** | `cloudflared` als Bundle-Resource in `bundle.resources` | | **Fallback: Auto-Download** | `curl -L` von Cloudflare GitHub Releases | | **Installationsort** | `~/Library/Application Support/io.hildebrandt.streamertool/bin/cloudflared` | ### Verifikation - SHA-256 Check gegen Hardcoded (oder online abgerufene) Hashes - Bei Hash-Mismatch: Warnung, Fallback auf Auto-Download - `cloudflared version` zur Laufzeit prüfen --- ## 🖥️ Dashboard-Integration ### Neue Seite: "Tunnel" (in der Settings-Navigation) - **Status-Anzeige**: Running / Stopped / Error / Unconfigured - **Public URL**: Anzeige der öffentlichen Webhook-URL (Copy-Button) - **Cloudflare-Status**: Angemeldet als [Email] / Nicht angemeldet - **Start/Stopp Button**: Je nach aktuellem Zustand - **Log-Viewer**: Letzte 50 Zeilen `cloudflared` Output - **Konfiguration**: Port, Hostname, Autostart-Toggle - **Einrichtungs-Assistent**: "Neu einrichten" Button führt durch Wizard ### Dashboard-Übersicht - Kleine Status-Karte: Tunnel-Status + URL - Fehleranzeige bei Verbindungsproblemen --- ## 🔄 Lifecycle-Integration ### App-Start 1. `AppState::bootstrap()` → `TunnelManager::load()` (Config aus DB + Secrets) 2. Wenn `tunnel.enabled == true` und Token vorhanden: - `lifecycle.spawn("cloudflare-tunnel", tunnel_manager.run())` - Tunnel-Prozess startet im Hintergrund 3. Dashboard zeigt "Tunnel läuft" mit URL ### App-Shutdown 1. `AppState::shutdown()` → `TunnelManager::stop()` 2. `cloudflared` Prozess bekommt SIGTERM (oder `taskkill` auf Windows) 3. Wartet auf sauberes Beenden (max 5s), dann SIGKILL 4. Log: "Tunnel gestoppt" ### Bei Fehlern - Log-Ausgabe in den tunnel-eigenen Log-Puffer (letzte 100 Zeilen) - Event: `tunnel.error` → Event-Bus (für Alarme) - Dashboard zeigt Error-Status + Logs --- ## 📝 cloudflared Konfiguration ### Tunnel-Konfiguration (`~/.cloudflared/config.yml` — automatisch generiert) ```yaml tunnel: <TUNNEL-ID> credentials-file: <DATA_DIR>/cloudflare/<TUNNEL-ID>.json ingress: - hostname: webhooks.streamertool.app service: http://localhost:3443 - service: http_status:404 ``` ### Alternativ: Quick-Tunnel (ohne eigene Domain) ```bash cloudflared tunnel --url http://localhost:3443 ``` → Gibt `https://<random>.trycloudflare.com` zurück --- ## ⚙️ Implementierungsschritte ### Phase 1: Grundstruktur (Rust Backend) - [ ] `tunnel/mod.rs` — TunnelManager Struct + State Machine - [ ] `tunnel/binary.rs` — Binary-Suche (Bundle/DataDir/System-PATH), Auto-Download, SHA-256 Verify - [ ] `tunnel/config.rs` — Config-Generierung, Credential-File-Management - [ ] `tunnel/platform.rs` — Windows: `%APPDATA%`, macOS: `~/Library/Application Support` - [ ] Integration in `AppState` (neues Feld, Shutdown-Reihenfolge) - [ ] Tauri-Commands: `get_tunnel_status`, `start_tunnel`, `stop_tunnel` ### Phase 2: Setup-Wizard - [ ] `tunnel/wizard.rs` — OAuth-Flow via `cloudflared tunnel login` - [ ] Tunnel-Erstellung via `cloudflared tunnel create` - [ ] DNS-Route via `cloudflared tunnel route dns` - [ ] Frontend: Wizard-Dialog mit 4 Schritten ### Phase 3: Dashboard & API - [ ] API-Routes: `GET /api/tunnel`, `POST /api/tunnel/start`, `POST /api/tunnel/stop` - [ ] Frontend: Tunnel-Seite in Settings - [ ] Frontend: Status-Karte im Dashboard - [ ] Frontend: Log-Viewer für Tunnel ### Phase 4: Bundling & Build - [ ] `cloudflared` Download-Script für CI/CD (`scripts/download-cloudflared.sh`) - [ ] Tauri-Resource-Integration in `tauri.conf.json` + `Makefile` - [ ] Windows: NSIS-Installer inkludiert `cloudflared.exe` - [ ] macOS: DMG enthält `cloudflared` Binary - [ ] SHA-256 Hash-Verifikation in `tunnel/binary.rs` ### Phase 5: Autostart & Lifecycle - [ ] Lifecycle-Integration: Start/Stopp mit der App - [ ] graceful shutdown (SIGTERM → 5s → SIGKILL/kill) - [ ] Reconnect bei Absturz (max 3 Versuche) - [ ] Event-Bus-Publikation bei Status-Änderungen --- ## 🔐 Sicherheit | Aspekt | Lösung | |---|---| | **Cloudflare-Token** | In `SecretStore` via OS-Keychain (bereits vorhanden) | | **Tunnel Credential File** | Verschlüsselt im App-Datenverzeichnis, nicht in `~/.cloudflared/` | | **Webhook-Port** | `3443` — nur localhost, nicht im LAN erreichbar | | **Binary-Integrität** | SHA-256 Verifikation vor erstem Start | | **Tunnel-Start** | Nur wenn Webhook-Server aktiv und Port belegt ist | --- ## 🌐 Plattform-Strategie | Plattform | Priorität | Binary-Quelle | Autostart | |---|---|---|---| | **Windows (AMD64)** | 🔴 P0 | Bundle + Fallback-Download | App-Lifecycle | | **macOS (ARM64)** | 🟡 P1 | Bundle + Fallback-Download | App-Lifecycle | | **macOS (AMD64)** | 🟡 P1 | Bundle + Fallback-Download | App-Lifecycle | | **Linux (AMD64)** | 🟢 P2 | App-Binary + Fallback-Download | App-Lifecycle | --- ## 📊 Legacy-API Die bestehenden API-Endpunkte aus `server/mod.rs` bleiben unverändert. Neue Tunnel-Endpunkte werden separat unter `/api/tunnel/*` hinzugefügt, geschützt durch den existierenden `admin_auth_middleware`. --- ## 🔗 Abhängigkeiten & Verwandte Issues | Issue | Beziehung | |---|---| | **#66** | Webhook-Receiver-API — empfängt auf `:3443`, Tunnel leitet dorthin | | **#61** | Ko-fi Webhook-Integration — nutzt die öffentliche URL | | **#63** | Patreon OAuth & Alert-Overlay — nutzt die öffentliche URL | | **ADR-001** | Wiki: Architektur-Entscheidungen für den Tunnel | | **#20** | Browser-Integration (für OAuth-Login) | --- ## ❌ Verworfen - **System-Daemon/Service** (LaunchAgent, systemd) — zu komplex, App-Lifecycle reicht - **ngrok/Localtunnel** — unzuverlässig, keine feste URL, Traffic-Limits - **Eigener Rust-Tunnel** — `cloudflared` ist erprobt und von Cloudflare maintained - **Docker-Container** — zu viel Overhead für eine Desktop-App - **Tailscale Funnel** — beta, benötigt separates Tailscale-Konto
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
frank/streamertool#65
No description provided.