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>
4.8 KiB
ADR-0008: Geteilter Betrieb - Hub im LXC, Ingest am Stream-PC
Datum: 2026-09-17 Status: akzeptiert Berührt: ADR-0005, ADR-0006, ADR-0007
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 ingestverliert 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.