Betrieb
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.
Was du brauchst
- 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-URIhttps://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 Agent (KI-Assistent) Arbeit erledigen soll. Du fügst ihn nach der Einrichtung über die API hinzu. Siehe Models.
Die Images bauen
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:
export OPENBOT_RELEASE=$(git rev-parse HEAD)TAG=$OPENBOT_RELEASE docker buildx bake -f deploy/docker/docker-bake.hcl --loadDas 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.
Geheimnisse als Dateien
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.
Mit Docker starten
Schreibe deine Einstellungen in eine Datei, zum Beispiel openbot.env. Sie braucht nur OPENBOT_DATABASE_URL und OPENBOT_SECRET_KEYS. 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:
echo "OPENBOT_SECRET_KEYS=k1:$(openssl rand -hex 32)" >> openbot.envSiehe Geheime Schlüssel.
Die Datenbank vorbereiten
Das Migrationsprogramm braucht nur OPENBOT_DATABASE_URL. Führe es aus, bevor du den Server startest. Führe es auch vor jeder neuen Version wieder aus:
docker run --rm --env-file openbot.env \ openbot:$OPENBOT_RELEASE /app/dist/app/Migrate.mjsDu kannst es ohne Gefahr mehrmals ausführen. Es führt nur die Migrationen aus, die der Datenbank noch fehlen. Migrationen gehen nur vorwärts. Du kannst keine rückgängig machen. Mache also zuerst eine Sicherung.
Die Plattform einrichten
Führe das Einrichtungsprogramm einmal aus, auf einer neuen Datenbank:
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.comEs 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.
Den Server starten
docker run -d --name openbot --env-file openbot.env \ -p 127.0.0.1:8080:3000 openbot:$OPENBOT_RELEASEBeim Start prüft der Server, ob die Datenbank alle Tabellen hat. Wenn nicht, hält er an, und du siehst einen Fehler im Log.
Prüfen
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.
Ohne Docker
Du kannst die Programme auch mit Node.js auf dem Server ausführen:
pnpm install --frozen-lockfilepnpm --filter-prod @openbot-build/openbot... buildpnpm --filter @openbot-build/openbot migratepnpm --filter @openbot-build/openbot setup --public-origin=https://api.example.com --admin-email=alice@example.compnpm --filter @openbot-build/openbot startDas Paket @openbot-build/openbot hat auch die Befehle openbot-migrate, openbot-setup und openbot.
Mit Compose starten
Die Datei deploy/docker/compose.production.yaml startet diese Dienste:
| Dienst | Image | Port auf dem Host |
|---|---|---|
postgres |
postgres:18-alpine, 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 die Geheimnisse den Containern als Dateien in /run/secrets, nicht als Umgebungsvariablen. Das sind POSTGRES_PASSWORD, OPENBOT_DATABASE_URL und OPENBOT_SECRET_KEYS. Compose nimmt ihre Werte aus .env.production.
Der Dienst openbot bekommt nur OPENBOT_DATABASE_URL und OPENBOT_SECRET_KEYS. Er hat keine anderen Umgebungsvariablen, denn alle anderen Einstellungen liegen in der Datenbank. Der Dienst migrate bekommt nur OPENBOT_DATABASE_URL.
In der Vorlage nutzt OPENBOT_DATABASE_URL den Wert ${POSTGRES_PASSWORD}. So setzt du das Passwort nur einmal.
Die Einstellungen vorbereiten
cp deploy/docker/production.env.example .env.productionopenssl rand -hex 32 # use the output for POSTGRES_PASSWORDecho "k1:$(openssl rand -hex 32)" # use the output for OPENBOT_SECRET_KEYSTrage die Werte in .env.production ein.
Beide Images bauen
export OPENBOT_RELEASE=$(git rev-parse HEAD)TAG=$OPENBOT_RELEASE docker buildx bake -f deploy/docker/docker-bake.hcl --loadDie Einstellungen prüfen
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml config --quietDas zeigt einen Fehler, wenn eine nötige Einstellung fehlt. Ohne --quiet gibt es die ganze Konfiguration mit allen eingesetzten Werten aus.
Alles starten
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.
Die Plattform einrichten
Führe das Einrichtungsprogramm einmal aus, nach dem ersten up:
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.comBis du das tust, antwortet jede Route außer /health mit 503 und SetupRequired. Siehe Platform.
Für eine neue Version baust du neue Images, setzt das neue OPENBOT_RELEASE, sicherst die Datenbank und führst up -d --wait noch einmal aus. migrate läuft dann wieder, bevor das neue OpenBot startet.
Lösche nie das Volume postgres. Es enthält alle deine Daten.
Viele Instanzen
Du kannst viele OpenBot-Instanzen hinter einem Load Balancer betreiben. Gib jeder Instanz:
- dieselbe
OPENBOT_DATABASE_URL, - dieselben
OPENBOT_SECRET_KEYS.
Mehr ist nicht nötig. 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.
TLS und der Reverse Proxy
Im Produktivbetrieb kümmert sich ein Reverse Proxy um HTTPS. Er schickt den Verkehr an OpenBot auf 127.0.0.1:8080.
Lass OPENBOT_TLS_CERT und OPENBOT_TLS_KEY leer.
Der Proxy muss:
- die Header
Origin,CookieundAuthorizationunverändert an OpenBot schicken, - Antworten nicht puffern, denn Turns können ihre Ausgabe als Server-Sent Events (SSE) streamen,
- lange Antworten erlauben.
GET /v1/sessions/:id/waitkann bis zu 30 Sekunden warten, und ein Stream dauert so lange wie sein Turn.
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 / { 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; }}api.example.com { reverse_proxy 127.0.0.1:8080 { flush_interval -1 }}Dein eigener Client auf demselben Origin
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 danachcompleteAppAuthorizationauf. 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/.
Sicherungen
Sichere zwei Dinge und bewahre sie zusammen auf:
- 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, Sessions und ihre Timelines und App-Verbindungen.
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.
Mit Compose machst du so eine Datenbank-Sicherung:
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml \ exec -T postgres pg_dump -U openbot -Fc openbot > openbot-$(date +%F).dumpZum 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:
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.dumpGitHub Actions
Der Workflow .github/workflows/ci.yml hat zwei Jobs. Der zweite Job läuft nur, wenn der erste erfolgreich ist.
| Job | Was er tut |
|---|---|
check |
Führt pnpm build, pnpm typecheck und pnpm -r test in devenv shell aus. |
images |
Baut, prüft, scannt und veröffentlicht die Docker-Images. |
Beide Jobs laufen auf ubuntu-latest. Sie installieren Nix mit dem Determinate Nix Installer und danach devenv 2.4.0. Magic Nix Cache speichert Nix-Build-Ergebnisse im Cache von GitHub Actions. So bauen spätere Läufe sie nicht noch einmal. Die Jobs laden auch fertig gebaute devenv-Pakete von devenv.cachix.org. Der Job check speichert den pnpm-Store in einem Cache.
Der Job images macht diese Schritte:
- hadolint und
docker buildx bake lintprüfen dasDockerfile. Der zweite führt die Docker-Build-Prüfungen aus. - Docker Bake baut beide Images. Die Build-Schichten bleiben im Cache von GitHub Actions, mit einem Cache pro Image. So bauen spätere Läufe nur, was sich geändert hat.
deploy/docker/check.shprüft die Images. Siehe Die Images prüfen.- dive prüft, dass die Image-Schichten keinen Platz verschwenden.
- Trivy scannt beide Images. Der Job schlägt fehl, wenn ein Image eine bekannte Schwachstelle der Stufe
HIGHoderCRITICALhat, für die es eine Korrektur gibt. Trivy sieht die Node.js-Version nicht, denn Node.js wird in das Image kopiert und nicht als Paket installiert. - Der Job speichert beide Images als Artefakt
images-<commit-sha>für sieben Tage. - Bei Pushes veröffentlicht der Job die Images. Er nutzt den Build-Cache und baut also nicht noch einmal.
Der Workflow läuft für Pull Requests, Pushes auf main und Tags wie v1.2.3. Er veröffentlicht Images nur bei Pushes:
| Ereignis | Veröffentlichte Tags |
|---|---|
Ein Push auf main |
<commit-sha> und latest |
Ein Tag wie v1.2.3 |
<commit-sha> und v1.2.3 |
Die Images landen in der GitHub Container Registry, unter ghcr.io/openbot-build/openbot und ghcr.io/openbot-build/openbot/protocol-test. Der Workflow bringt OpenBot nicht in Betrieb. Wenn du ein veröffentlichtes Image mit Compose nutzen willst, lade es herunter und gib ihm den Tag openbot:<tag>.
Die Doku-Seite veröffentlichen
Der Workflow .github/workflows/docs.yml veröffentlicht die Doku-Seite auf GitHub Pages unter openbot.build. Er läuft bei jedem Push auf main. Du kannst ihn auch von Hand im Tab „Actions“ starten.
| Job | Was er tut |
|---|---|
build |
Führt pnpm --filter "@openbot-build/docs..." build in devenv shell aus. Das baut die Doku und die Pakete, die sie braucht. |
deploy |
Schickt packages/docs/dist an GitHub Pages. |
Der Job build setzt DOCS_URL auf https://openbot.build. Astro nutzt den Wert für vollständige Seitenlinks, zum Beispiel in der Sitemap. Es läuft immer nur ein Deploy auf einmal.
Die Einstellungen des Repositorys müssen GitHub Actions als Quelle für Pages nutzen, mit openbot.build als eigener Domain. Der DNS-Eintrag für openbot.build muss auf GitHub Pages zeigen. Siehe Manage a custom domain.
Die Images prüfen
deploy/docker/check.sh startet compose.production.yaml mit Test-Einstellungen. Die zusätzliche Datei compose.check.yaml entfernt die Host-Ports und fügt zwei Dienste hinzu. Der Dienst setup führt das Einrichtungsprogramm mit Testwerten aus, nach migrate und bevor openbot startet. Der Dienst check führt die Prüfungen aus. check.env enthält die Test-Einstellungen. Keine davon ist ein echtes Geheimnis.
Der Dienst check führt check.mjs im Compose-Netzwerk aus, sobald OpenBot und der Protokolltest-Dienst gesund sind. Er prüft, dass:
/v1/sessionsohne Schlüssel und mit falschem Schlüssel401zurückgibt,/openapi.jsonfunktioniert,- der Catalog des Protokolltests den richtigen öffentlichen Origin hat,
- die MCP-Erkennung auf dem Protokolltest-Dienst funktioniert.
So beweist die Prüfung auch, dass Migrationen, das Einrichtungsprogramm, Geheimnis-Dateien und Health Checks im echten Produktivaufbau funktionieren. Am Ende entfernt das Skript die Container und die Test-Datenbank.
Führe dieselben Prüfungen auf deinem Computer aus:
devenv shell -- pnpm imagesdevenv shell -- pnpm images:checkdevenv shell -- hadolint deploy/docker/Dockerfiledevenv shell -- dive --ci --source docker openbot:localdevenv shell -- trivy image --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed openbot:local