Zum Inhalt springen

Betrieb

Für den Plattformbetrieb. Diese Aufgaben betreffen die ganze Installation. Du brauchst je nach Aufgabe Serverzugriff oder Plattformrechte. Beginne mit dem Administrationshandbuch.

Diese Seite zeigt dir, wie du OpenBot im Produktivbetrieb laufen lässt. Du baust ein Docker-Image, bereitest die Datenbank vor, richtest die Plattform ein und startest den Server hinter einem Reverse Proxy. Alle Einstellungen findest du unter Konfiguration.


  • Einen Linux-Server mit Docker und Docker Compose.
  • Einen Domainnamen für OpenBot, zum Beispiel api.example.com, und ein TLS-Zertifikat dafür.
  • Einen OpenID-Connect-Anbieter für die Plattform, zum Beispiel https://id.example.com. Registriere dort einen Client mit der Redirect-URI https://api.example.com/auth/callback/oidc. Du kannst diesen Punkt weglassen, wenn sich alle nur über die SSO-Verbindungen von Organisationen anmelden.
  • Einen Modell-Dienst, wenn der Bot (KI-Assistent) Arbeit erledigen soll. Du fügst ihn nach der Einrichtung über die API hinzu. Siehe Models.

Alle Docker-Dateien liegen in deploy/docker/. Ein einziges Dockerfile erzeugt beide Images. Jedes Image ist ein Build-Ziel (eine benannte letzte Stufe in der Datei):

Ziel Image Was darin läuft
openbot openbot OpenBot und sein Migrationsprogramm.
protocol-test openbot-protocol-test Der Testdienst für das App Protocol. Siehe Protokolltest.

Die Datei docker-bake.hcl sagt Docker Bake, wie es die Images baut. Führe diesen Befehl im Hauptordner des Repositorys aus:

Terminal window
export OPENBOT_RELEASE=$(git rev-parse HEAD)
TAG=$OPENBOT_RELEASE docker buildx bake -f deploy/docker/docker-bake.hcl --load

Das baut openbot:$OPENBOT_RELEASE und openbot-protocol-test:$OPENBOT_RELEASE für linux/amd64. --load legt sie in dein lokales Docker. Ohne TAG heißt der Tag local. Wenn du nur ein Image bauen willst, gib seinen Zielnamen an, zum Beispiel openbot.

Auf einem Computer, der kein x86_64 ist, braucht Docker QEMU (ein Programm, das Code für einen anderen Prozessor ausführt), um die Images zu bauen. Installiere es einmal mit docker run --privileged --rm tonistiigi/binfmt --install amd64.

Beide Images beruhen auf distroless, mit derselben Node.js-Version wie in der Entwicklung. Distroless-Images haben keine Shell und keinen Paketmanager. Darum kannst du mit docker exec keine Shell darin öffnen. Sie laufen als Benutzer nonroot (65532).

Das OpenBot-Image enthält Node.js, den gebündelten Server, die gebündelten Programme für Migration und Einrichtung und die Datenbank-Migrationen. Es enthält keine Build-Werkzeuge und keine Geheimnisse.

Pfad im Image Was es ist
/app/dist/app/Main.mjs Der Server. Das Image startet ihn standardmäßig.
/app/dist/app/Migrate.mjs Das Migrationsprogramm. Es bereitet die Datenbank vor.
/app/dist/app/Setup.mjs Das Einrichtungsprogramm. Es schreibt die ersten Plattform-Einstellungen.
/app/migrations Die Datenbank-Migrationen.

Der Server im Image hört auf 0.0.0.0:3000. Das Image hat einen Health Check (Gesundheitsprüfung), der alle fünf Sekunden /health aufruft.

OpenBot liest jede Einstellung zuerst aus einer Umgebungsvariable. Wenn die Variable nicht gesetzt ist, liest OpenBot stattdessen die Datei /run/secrets/<NAME>, zum Beispiel /run/secrets/OPENBOT_SECRET_KEYS. Dort legen Docker und Compose Geheimnisse ab. Eine leere Datei zählt als nicht gesetzt. Siehe Konfiguration.

Umgebungsvariablen sind in docker inspect sichtbar. Dateien in /run/secrets sind dort nicht sichtbar. Compose nutzt für alle Geheimnisse Dateien.

Schreibe deine Einstellungen in eine Datei, zum Beispiel openbot.env. Sie braucht nur OPENBOT_DATABASE_URL, OPENBOT_SECRET_KEYS und OPENBOT_CLUSTER_SECRET. Beginne mit deploy/docker/production.env.example. docker run setzt ${POSTGRES_PASSWORD} nicht ein. Schreibe die ganze OPENBOT_DATABASE_URL also selbst.

Erzeuge die geheimen Schlüssel einmal:

Terminal window
echo "OPENBOT_SECRET_KEYS=k1:$(openssl rand -hex 32)" >> openbot.env
echo "OPENBOT_CLUSTER_SECRET=$(openssl rand -hex 32)" >> openbot.env

Siehe Geheime Schlüssel.

Private Aufrufe zwischen Knoten nutzen /internal/executions/rpc und /internal/resources/rpc. Halte beide Pfade im privaten Netzwerk. Alle Knoten nutzen dasselbe zufällige Geheimnis. Gib bei mehreren Knoten jedem Knoten einen eigenen erreichbaren Host. Der private RPC-Client ist vom Schutz des App-Netzwerks getrennt.

Das Migrationsprogramm braucht OPENBOT_DATABASE_URL und OPENBOT_SECRET_KEYS. Stoppe zuerst alle OpenBot-Instanzen. Sichere die Datenbank und die Liste der Schlüssel im Objektspeicher. Behalte die alten Geheimschlüssel: Das Programm braucht sie zum Öffnen alter Einträge. Führe es vor dem ersten Serverstart und vor jeder neuen Version aus:

Terminal window
docker run --rm --env-file openbot.env \
openbot:$OPENBOT_RELEASE /app/dist/app/Migrate.mjs

Dieselbe Migration ändert geeignete UUID-Spalten von Text in den PostgreSQL-Typ uuid. Jede ID belegt dort 16 Bytes. Alte v4-Werte bleiben gleich. Neue gespeicherte IDs nutzen v7, wenn die Zeitfolge hilft. Spalten mit gemischten oder externen IDs behalten Text. Stoppe dafür wie oben alle Server.

Führe nach einem Abbruch denselben Befehl erneut aus. Jeder Datenblock und sein Fortschritt werden zusammen gespeichert. Ein beschädigter Eintrag stoppt den Lauf. Die Fehlerursache bleibt in einem verschlüsselten Bericht. Das Programm prüft Anzahl, Verweise, Geheimnisse und Zustände. Erst dann ist die Datenversion bereit und der Server darf starten. Laufende Server halten eine gemeinsame Datenbanksperre. Die Umstellung braucht eine alleinige Sperre.

Die Sicherung behält Ressourcen-IDs, Verlauf und offene Entscheidungen. Alte externe Aktionen ohne bekanntes Ergebnis bleiben outcome_unknown. Arbeit ohne sicheren Prüfpunkt wird mit Grund als interrupted markiert. Ein fehlendes ursprüngliches Token wird nie zu einem uneingeschränkten Mitgliedsaufruf.

Vor dem neuen Verkehr kannst du die Sicherung wiederherstellen. Sobald externe Aktionen erneut laufen, repariere die Daten nur vorwärts. Stelle keine alten Daten wieder her, die diese Aktionen wiederholen würden.

Führe das Einrichtungsprogramm einmal aus, auf einer neuen Datenbank:

Terminal window
docker run --rm --env-file openbot.env openbot:$OPENBOT_RELEASE \
/app/dist/app/Setup.mjs \
--public-origin=https://api.example.com \
--oidc-issuer=https://id.example.com \
--oidc-client-id=openbot \
--admin-email=alice@example.com

Es schreibt den öffentlichen Origin, den Anbieter der Plattform und die ersten Plattform-Admins in die Datenbank. Gib ein Client-Geheimnis mit -e OPENBOT_SETUP_OIDC_CLIENT_SECRET=... an, nicht auf der Befehlszeile. Alle Optionen findest du unter Platform.

Du kannst die Einrichtung auch nach dem Start des Servers ausführen. Bis dahin antwortet jede Route außer /health mit 503 und SetupRequired.

Terminal window
docker run -d --name openbot --env-file openbot.env \
-p 127.0.0.1:8080:3000 openbot:$OPENBOT_RELEASE

Beim Start prüft der Server die Tabellen und die abgeschlossene Datenversion. Wenn eine Prüfung fehlschlägt, stoppt er und schreibt einen Fehler ins Log.

Terminal window
curl http://127.0.0.1:8080/health
{ "status": "ok" }

/health zeigt nur, dass der HTTP-Server antworten kann. Es prüft nicht die Datenbank, die Einrichtung oder das Modell.

Alice kann sich jetzt anmelden. Sie ist Plattform-Admin. Füge als Nächstes ein Model und einen Model Provider hinzu, der darauf verweist. Siehe Models.

Du kannst die Programme auch mit Node.js auf dem Server ausführen:

Terminal window
pnpm install --frozen-lockfile
pnpm --filter-prod @openbot-build/openbot... build
pnpm --filter @openbot-build/openbot migrate
pnpm --filter @openbot-build/openbot setup --public-origin=https://api.example.com --admin-email=alice@example.com
pnpm --filter @openbot-build/openbot start

Das Paket @openbot-build/openbot hat auch die Befehle openbot-server, openbot-migrate und openbot-setup. Mit dem Paket @openbot-build/cli kannst du sie auch als openbot server, openbot migrate und openbot setup ausführen.


Die Datei deploy/docker/compose.production.yaml startet diese Dienste:

Dienst Image Port auf dem Host
postgres postgres:18.6-alpine3.24, fest per Digest, Daten im Volume postgres keiner
migrate openbot:$OPENBOT_RELEASE keiner
openbot openbot:$OPENBOT_RELEASE 127.0.0.1:8080 oder OPENBOT_PUBLISHED_PORT
protocol-test openbot-protocol-test:$OPENBOT_RELEASE 127.0.0.1:3001

migrate führt das Migrationsprogramm einmal aus, sobald PostgreSQL gesund ist. openbot startet erst, wenn migrate erfolgreich war. So migriert up die Datenbank immer zuerst.

Der Dienst protocol-test ist der öffentliche Testdienst für das App Protocol. Siehe Protokolltest. Die Datei braucht PROTOCOL_TEST_PUBLIC_ORIGIN, auch wenn du nur OpenBot nutzt.

Compose gibt POSTGRES_PASSWORD, OPENBOT_DATABASE_URL, OPENBOT_SECRET_KEYS und OPENBOT_CLUSTER_SECRET als Dateien in /run/secrets weiter. Die Werte kommen aus .env.production. Der Dienst openbot bekommt auch OPENBOT_OUTBOUND_ALLOW und OPENBOT_CLUSTER_HOST. Die Produkteinstellungen liegen in der Datenbank. Der Dienst migrate braucht OPENBOT_DATABASE_URL und OPENBOT_SECRET_KEYS.

In der Vorlage nutzt OPENBOT_DATABASE_URL den Wert ${POSTGRES_PASSWORD}. So setzt du das Passwort nur einmal.

Terminal window
cp deploy/docker/production.env.example .env.production
openssl rand -hex 32 # use the output for POSTGRES_PASSWORD
echo "k1:$(openssl rand -hex 32)" # use the output for OPENBOT_SECRET_KEYS
openssl rand -hex 32 # use the output for OPENBOT_CLUSTER_SECRET

Trage die Werte in .env.production ein.

Terminal window
export OPENBOT_RELEASE=$(git rev-parse HEAD)
TAG=$OPENBOT_RELEASE docker buildx bake -f deploy/docker/docker-bake.hcl --load
Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml config --quiet

Das zeigt einen Fehler, wenn eine nötige Einstellung fehlt. Ohne --quiet gibt es die ganze Konfiguration mit allen eingesetzten Werten aus.

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml up -d --wait

--wait kehrt zurück, wenn alle Dienste gesund sind. Die Images prüfen ihre Gesundheit alle fünf Sekunden. Wenn ein Dienstprozess anhält, startet Compose ihn neu.

Führe das Einrichtungsprogramm einmal aus, nach dem ersten up:

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml \
run --rm openbot /app/dist/app/Setup.mjs \
--public-origin=https://api.example.com \
--oidc-issuer=https://id.example.com \
--oidc-client-id=openbot \
--admin-email=alice@example.com

Bis du das tust, antwortet jede Route außer /health mit 503 und SetupRequired. Siehe Platform.

Für eine neue Version baust du neue Images und setzt das neue OPENBOT_RELEASE. Stoppe alle OpenBot-Instanzen. Sichere die Datenbank und die Objektschlüsselliste. Führe dann up -d --wait erneut aus. migrate läuft vor dem neuen OpenBot. Lösche nie das Volume postgres. Es enthält alle deine Daten.

Du kannst viele OpenBot-Instanzen hinter einem Load Balancer betreiben. Gib jeder Instanz:

  • dieselbe OPENBOT_DATABASE_URL,
  • dieselben OPENBOT_SECRET_KEYS und OPENBOT_CLUSTER_SECRET,
  • einen eigenen OPENBOT_CLUSTER_HOST, den alle anderen Knoten erreichen,
  • dieselbe OPENBOT_OUTBOUND_ALLOW, wenn du sie setzt. Siehe Ausgehende Verbindungen.

Nutze die private Adresse jedes Knotens, nicht die Adresse des Load Balancers. Vergrößere den Compose-Dienst openbot nur, wenn jeder neue Knoten seinen eigenen Host bekommt. Die zwei Knoten in compose.check.yaml zeigen diese Einrichtung.

Alle gemeinsamen Einstellungen liegen in der Datenbank. Wenn ein Admin sie ändert, nutzt jede Instanz die Änderung sofort. Siehe Konfiguration. Führe das Migrationsprogramm und das Einrichtungsprogramm nur einmal aus, nicht auf jeder Instanz.


Im Produktivbetrieb kümmert sich ein Reverse Proxy um HTTPS. Er schickt den Verkehr an OpenBot auf 127.0.0.1:8080. OpenBot liefert nur einfaches HTTP. Darum liefert nur der Proxy HTTPS.

Der Proxy muss:

  • alle öffentlichen Anfragen unter /internal/ ablehnen,

  • die Header Origin, Cookie und Authorization unverändert an OpenBot schicken,

  • Antworten nicht puffern, denn Turns können ihre Ausgabe als Server-Sent Events (SSE) streamen,

  • lange Antworten erlauben. Ein Ereignis-Stream kann bis zum Ende seiner Ausführung offen bleiben.

server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/ssl/api.example.com.pem;
ssl_certificate_key /etc/ssl/api.example.com.key;
location /internal/ {
return 404;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 1h;
}
}

Ein Browser-Client auf demselben Origin wie OpenBot kann das Anmelde-Cookie nutzen. Er braucht kein User Token. Dafür schickt dein Proxy einige Pfade an OpenBot und alle anderen Pfade an deinen Client.

Pfad Senden an Was es ist
/auth/* OpenBot Anmelden, Abmelden und der Rückruf für die App-Autorisierung.
/v1/* OpenBot Die API.
/health OpenBot Der Health Check.
/openapi.json OpenBot Das OpenAPI-Dokument.
/docs OpenBot Die interaktive API-Referenz. Optional.
alles andere Dein Client Deine Seiten, auch /.

Wenn du deinen Client unter / einhängst, ist das Dienstdokument von GET / nicht mehr öffentlich. Das ist in Ordnung. Clients können die Pfade oben direkt nutzen.

Nach der Anmeldung schickt OpenBot den Browser zurück zu einem Pfad in deinem Client. Standard ist /. Dein Client muss auch diese Rücksprungadressen verarbeiten:

  • /?authorization=<flowId> nach einer App-Autorisierung. Rufe danach completeAppAuthorization auf. Siehe Apps.
  • /?developerTest=<testId> nach einer Autorisierung für einen Entwicklertest. Siehe Entwicklerwerkzeuge.

Ein Rücksprungpfad kann jeder Pfad auf demselben Origin sein, außer Pfaden unter /auth/, /v1/ und /development/.


Sichere diese Dinge und bewahre sie zusammen auf:

  1. Die Datenbank. Sie enthält die Einstellungen von Plattform und Organisationen, Konten, Organisationen und ihre Mitglieder, User Tokens, Models und Model Providers, SSO-Verbindungen, das Audit-Log, Bots, Chats und ihren Verlauf und App-Verbindungen.
  2. OPENBOT_SECRET_KEYS. Die Schlüssel entschlüsseln die Geheimnisse in der Datenbank: App-Geheimnisse, Schlüssel der Model Provider, SSO-Client-Geheimnisse und das Anmelde-Geheimnis. Eine Datenbank-Sicherung ohne die Schlüssel kann diese Geheimnisse nicht wiederherstellen.
  3. Der Bucket der Dateien. Er hält die Bytes der Dateien, die Leute hochgeladen haben. Die Datenbank nennt sie nur.

Mit Compose machst du so eine Datenbank-Sicherung:

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml \
exec -T postgres pg_dump -U openbot -Fc openbot > openbot-$(date +%F).dump

Zum Wiederherstellen hältst du zuerst OpenBot an, mit docker compose --env-file .env.production -f deploy/docker/compose.production.yaml stop openbot. Dann führst du pg_restore aus:

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml \
exec -T postgres pg_restore -U openbot -d openbot --clean < openbot-2026-10-20.dump

Für diese Entwicklungsaufgabe siehe Das Projekt veröffentlichen und prüfen.