Hub: der Dienst laeuft zentral statt auf dem Stream-PC

Zwei Dinge, die Reichweite bringen sollen, hingen bisher daran, dass jemand
vor seinem Rechner sitzt: der Discord-Rollen-Knopf und die Go-Live-
Ankuendigung. Beide brauchen nur Internet.

Der Schnitt verlaeuft entlang einer Frage: braucht die Aufgabe eine Datei
oder ein Programm, das nur auf dem Stream-PC existiert?

  Hub (LXC)                    Ingest (Abdus PC)
  ---------                    -----------------
  Chat, Zuschauerzahlen        OBS-Wiedergabepuffer
  Discord: Knopf und Go-Live   !clip, Rendern, Untertitel
  Overlay-Seiten fuer OBS

Beide schreiben in ihre eigene Datenbank. Eine gemeinsame waere eine
Netzwerkfreigabe fuer SQLite - der zuverlaessigste bekannte Weg zu einer
beschaedigten Datei.

Das kostet ADR-0005 seine Hauptbegruendung: "bindet nur auf 127.0.0.1" gilt
fuer den Hub nicht mehr. An die Stelle treten ein Passwort mit signiertem
Sitzungs-Cookie fuer alles, was ein Mensch bedient, und ein zufaelliger
Schluessel in der Adresse fuer die Browser-Sources. Der Schluessel ist kein
schoenes Verfahren - er steht in jedem OBS-Profil -, aber eine Browser-Source
kann kein Formular ausfuellen und keinen Login durchhalten.

`publicUrl` haengt der OAuth-Rueckruf daran. Twitch vergleicht die
Redirect-URI zeichengenau, und ein fehlender Schraegstrich sieht im Fehlertext
aus wie ein falsches Client-Secret.

Die Routen der Einrichtungsseite sind aus ingest/server.ts herausgeloest,
weil sie jetzt an zwei Servern haengen.

Begruendung und Konsequenzen in ADR-0008.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZeasyAlexandClaude Opus 5 committed 2026-09-18 00:12:58 +02:00
1 parent e18336c57f
commit 3b606e36fb
8 files changed
+985 -10

No files matched your search

@@ -0,0 +1,100 @@
# ADR-0008: Geteilter Betrieb - Hub im LXC, Ingest am Stream-PC
Datum: 2026-09-17
Status: akzeptiert
Berührt: [ADR-0005](ADR-0005-zugangsdaten.md), [ADR-0006](ADR-0006-ein-dach.md),
[ADR-0007](ADR-0007-native-windows.md)
## Kontext
Bis hierher lief alles in einem Prozess auf Abdus Rechner (ADR-0007), und
alles band an `127.0.0.1` (ADR-0005). Das war richtig, solange jede Aufgabe
etwas mit OBS zu tun hatte.
Zwei neue Aufgaben haben damit aber nichts zu tun:
- **Der Rollen-Knopf auf Discord.** Er hängt an einer Gateway-Verbindung im
Ingest-Daemon. Ist Abdus Rechner aus, klickt jemand auf den Knopf und
bekommt "Interaktion fehlgeschlagen". Ein Knopf, der nur läuft, während
der Besitzer am Rechner sitzt, ist kein Knopf.
- **Die Go-Live-Ankündigung.** Sie braucht Twitch und Discord, sonst nichts.
Dazu kam das Overlay. Eine Browser-Source in OBS holt ihre Seite über HTTP;
ob die von `127.0.0.1` kommt oder aus dem Netz, ist ihr gleich.
## Entscheidung
Das Toolkit läuft ab jetzt an zwei Stellen, mit einem klaren Schnitt:
| | Hub (LXC 141, `abdu.dimension47.de`) | Ingest (Abdus PC) |
|---|---|---|
| Befehl | `abdulive hub` | `abdulive ingest` |
| Twitch-Chat lesen und senden | ja | ja |
| Zuschauerzahlen, Stream-Sitzungen | ja | ja |
| Discord: Rollen-Knopf, Go-Live | **ja** | nein |
| Overlay-Seiten ausliefern | **ja** | nein |
| OBS, Wiedergabepuffer, `!clip` | nein | **ja** |
| Rendern, Untertitel | nein | **ja** |
Der Schnitt verläuft entlang einer einzigen Frage: **braucht die Aufgabe eine
Datei oder ein Programm, das nur auf dem Stream-PC existiert?** Alles, was mit
Nein zu beantworten ist, gehört in den Hub.
Der Hub ist damit der einzige Teil, der von außen erreichbar ist. Er bindet
auf `0.0.0.0`, hinter dem vorhandenen Nginx Proxy Manager, und bringt Overlay,
Einrichtungsseite und OAuth-Rückruf unter einer Adresse zusammen.
## Begründung
**Warum nicht alles zentral.** Der Wiedergabepuffer von OBS liegt als Datei
auf Abdus Platte, ffmpeg und whisper arbeiten darauf, und ein Clip ist
mehrere hundert Megabyte. Das über das Netz zu schieben wäre teurer als es
bringt, und obs-websocket gehört ohnehin nicht ins Internet.
**Warum nicht alles lokal bleiben.** Genau die zwei Dinge, die Reichweite
bringen sollen - der Ping und der Knopf - sind die, die durchlaufen müssen.
Sie an den Stream-PC zu hängen heißt, sie an die Verfügbarkeit einer Person zu
hängen.
**Warum zwei Datenbanken und nicht eine.** Beide Seiten schreiben in ihre
eigene SQLite-Datei. Eine gemeinsame wäre eine Netzwerkfreigabe für SQLite,
und das ist der zuverlässigste bekannte Weg zu einer beschädigten Datei. Was
zusammengeführt werden muss, wird später über Ereignisse zusammengeführt, nicht
über geteilten Dateizugriff.
**Warum der Bruch mit ADR-0005 vertretbar ist.** Dort war die Begründung: was
nur auf `127.0.0.1` hört, ist gegen alles geschützt, was nicht vor dem Rechner
sitzt. Diese Eigenschaft geht verloren, und der Schutz wandert auf zwei Dinge:
- Passwort mit Sitzungs-Cookie für Übersicht, Einrichtung und Status.
- Ein zufälliger Schlüssel in der Adresse jeder Browser-Source. Er darf nur
lesen, nie schreiben, und lässt sich auf der Übersichtsseite neu würfeln.
Der Schlüssel in der URL ist kein schönes Verfahren. Er steht in jedem
OBS-Profil und in jedem Screenshot der Einstellungen. Er ist trotzdem der
richtige: eine Browser-Source kann kein Formular ausfüllen, keinen Login
durchhalten und keinen zweiten Faktor bedienen. Jedes Verfahren, das mehr
verlangt, wird spätestens beim ersten Ausfall mitten im Stream abgeschaltet.
**Warum die Zugangsdaten trotzdem verschlüsselt neben der Datenbank liegen.**
Daran ändert sich nichts. Der Hub hat seinen eigenen Speicher, mit eigenem
Schlüssel, und die Twitch-Apps brauchen jetzt eine zweite Redirect-URI
(`https://abdu.dimension47.de/callback`) neben der bisherigen.
## Konsequenzen
- Die Twitch-App braucht eine zweite Redirect-URI. Twitch vergleicht
zeichengenau; ein fehlender Schrägstrich sieht im Fehlertext aus wie ein
falsches Client-Secret.
- Der Discord-Bot darf nur an **einer** Stelle laufen. Laufen Hub und Ingest
beide mit hinterlegtem Bot-Token, antworten zwei Prozesse auf denselben
Klick. Auf dem Stream-PC bleibt das Discord-Token deshalb leer.
- `abdulive ingest` verliert nichts, macht aber weniger. Der Go-Live-Post ist
dort weiterhin eingebaut - wer nur lokal fährt, hat damit alles an einer
Stelle, und dort gibt es zusätzlich das OBS-Vorschaubild.
- Der Hub kennt OBS nicht und kann deshalb keinen Screenshot für die
Ankündigung machen. Er nimmt Twitchs Vorschaubild. Das ist kurz nach dem
Start manchmal noch schwarz - der Preis dafür, dass der Post auch dann
rausgeht, wenn der Daemon am Stream-PC nicht läuft.
- ADR-0006 ("ein Dach") gilt weiter, aber jetzt je Seite: der Hub hat ein
Dach, der Stream-PC hat eins.