Self-Hosting
Betrieb & Fehlerbehebung
Betreiben Sie selbst gehostetes Keyright in Produktion: geplante Jobs, Observability, Sicherheitshärtung, Skalierung und Lastverteilung, Backup und Wiederherstellung, Upgrades, vollständig netzwerkisolierter (air-gapped) Betrieb sowie eine Fehlerbehebung/FAQ für das, was bei einem ersten Deployment auftritt.
Alles, was Sie brauchen, sobald die Instanz läuft: sie gesund halten, skalieren, sichern, aktualisieren, netzwerkisoliert (air-gapped) betreiben und beheben, was nicht grün hochgekommen ist. Wenn Sie sie noch aufsetzen, beginnen Sie mit dem Bereitstellungsleitfaden.
Betrieb
Geplante Jobs
Der tägliche Ablauf-/Platz-Scan und die Webhook-Zustellung laufen auf prozessinternen Timern. Auf Hosts, die Hintergrund-Timer in den Leerlauf versetzen (einige Serverless-Plattformen), steuern Sie sie stattdessen über einen externen Scheduler an — setzen Sie KEYRIGHT_CRON_SECRET und rufen Sie auf:
curl -X POST -H "X-Cron-Secret: $SECRET" $BASE/internal/notifications/run
curl -X POST -H "X-Cron-Secret: $SECRET" $BASE/internal/webhooks/deliver
Observability
- Liveness:
GET /health(statisches 200 — nimmt einen Knoten nie wegen eines vorübergehenden DB-Aussetzers aus dem Betrieb). Readiness:GET /health/ready(prüft zusätzlich die DB-Konnektivität — 503, wenn nicht erreichbar). - Logs: strukturiertes JSON auf stdout (Docker-/K8s-Treiber oder das Windows-Ereignisprotokoll über ANCM). Achten Sie auf die Startzeilen, die angewendete Migrationen und den Status der Selbstlizenz bestätigen.
- Monitoring:
/healthder App, Verfügbarkeit/Verbindungen/Festplatte von PostgreSQL und den Zertifikatsablauf am Load Balancer.
Diagnose (2.2.0)
-
GET /admin/self-diagnostics(Admin-Token) — ein Gesundheits-Snapshot in einem Aufruf für die Triage: Version, Erreichbarkeit der Datenbank + ausstehende Migrationen, Phase der Selbstlizenz, aktivierte Funktionen, ob SMTP/Benachrichtigungen konfiguriert sind, und Uptime. Wie/admin/self-licensebleibt er auch bei gesperrter Instanz erreichbar, sodass Sie einen Lizenzierungsstopp diagnostizieren können.{ "version": "2.2.0", "uptimeSeconds": 3600, "database": { "reachable": true, "error": null, "pendingMigrations": 0 }, "selfLicense": { "status": "valid", "phase": "active", "isTrial": false, "daysUntilExpiry": 320, "runtimeBlocked": false }, "features": { "operatorMode": false, "sso": true, "whitelabel": true, "airgap": true }, "smtpConfigured": true, "alerts": { "rulesEnabled": 3, "errorsAlerted24h": 0 } } -
Fehler-Korrelations-IDs — jeder unbehandelte Serverfehler (HTTP 500) wird einmal mit einer kurzen ID protokolliert und gibt diese ID im Response-Header
X-Keyright-Error-Idan den Aufrufer zurück (sowie als FelderrorIdim Body). Meldet ein Kunde einen Fehler, ordnet diese ID seine Meldung genau einer Logzeile zu.
E-Mail-Benachrichtigungen (2.2.0)
Lassen Sie sich per E-Mail informieren, wenn etwas passiert — konfiguriert im Dashboard → Settings → Email alerts (oder über die API):
- SMTP — hinterlegen Sie im Dashboard Ihren eigenen SMTP-Host/Port/Benutzer/Passwort/Absender (
POST /admin/alerts/smtp); das Passwort wird KEK-verschlüsselt gespeichert und ist write-only (wird nie zurückgegeben). Wenn Sie es nicht setzen, fallen die Benachrichtigungen auf die UmgebungskonfigurationKEYRIGHT_SMTP_*zurück. - Regeln pro Ereignis — aktivieren Sie genau die Ereignisse, die Sie möchten, und geben Sie jedem seine eigene Empfängerliste (
POST /admin/alerts/rules), sodass verschiedene Ereignisse an verschiedene Adressen gehen. Ein Button „send test email“ prüft Ihre Einstellungen. - Ereignisse umfassen kundenbezogene (Lizenz läuft ab/abgelaufen, Platzlimit erreicht, widerrufen) und — besonders wichtig für Self-Hosting — die Lizenz Ihrer eigenen Instanz, wenn sie sich dem Ablauf nähert, in die Kulanzfrist eintritt oder gesperrt wird — damit eine fail-closed Instanz nie unerwartet stoppt — sowie Systemereignisse (Serverfehler, Datenbankfehler, Fehlschlag eines geplanten Jobs). Wiederkehrende Zustände werden dedupliziert, sodass sie einmal pro Zeitfenster eine E-Mail auslösen, nicht bei jedem Scan.
Sicherheitshärtung
- Bewahren Sie
KEYRIGHT_ADMIN_TOKEN,KEYRIGHT_KEKundKEYRIGHT_SIGNING_KEYin einem Secrets-Manager auf — nie in einem Image oder in der Quellcodeverwaltung. - Stellen Sie öffentlich nur
:443(über den Load Balancer) bereit./admin/*und/internal/*sollten nur für Sie/Ihr Netzwerk erreichbar sein; der Client-Pfad/v1/*ist der einzige, den Ihre Kunden brauchen. - Beschränken Sie den Netzwerkzugriff auf die Datenbank auf die App-Knoten und verlangen Sie TLS zur Datenbank.
Skalierung & Lastverteilung
Die App ist CPU-schonend und zustandslos; bei der Skalierung geht es um Redundanz und Datenbankkapazität, nicht um den Durchsatz der App.
| Größenordnung | Aktive Lizenzen | App-Knoten | PostgreSQL | Load Balancer |
|---|---|---|---|---|
| Evaluierung | beliebig | 1 (0,5 vCPU / 512 MB) | mitgeliefert | keiner |
| Klein | bis ~50k | 1 (1 vCPU / 1 GB) | 2 vCPU / 2 GB verwaltet | optionaler TLS-Proxy |
| Standard-HA | bis ~500k | 2–3 (1 vCPU / 1 GB) | HA (Primary+Standby) | ja |
| Groß | 1M+ | 3–5+ Autoscaling | 4–8 vCPU / 16 GB+ HA + PgBouncer | ja |
Betreiben Sie 2+ App-Knoten hinter einem beliebigen HTTP-Load-Balancer. Da die App zustandslos ist und Clients offline prüfen, ist keine Session-Affinität nötig — senden Sie jede Anfrage an einen beliebigen Knoten. Terminieren Sie TLS am Balancer und leiten Sie X-Forwarded-For (echte Client-IP) und X-Forwarded-Proto weiter (damit Dashboard/Portal https-URLs erzeugen); die App respektiert beides. Nebenläufigkeit ist über Knoten hinweg sicher — Credits und Plätze verwenden serialisierbares Prüfen-und-Abziehen, sodass keine zwei Knoten ein Guthaben oder einen Platz doppelt verbrauchen können.
Backup & Wiederherstellung
Alles liegt in PostgreSQL — Standard-pg_dump / pg_restore. Sichern Sie außerdem KEYRIGHT_KEK und KEYRIGHT_SIGNING_KEY separat und sicher: Ohne den KEK lassen sich die verschlüsselten Signaturschlüssel in der Datenbank nicht wiederherstellen.
Upgrades
- Sichern Sie die Datenbank (und vergewissern Sie sich, dass Sie den KEK/Signaturschlüssel haben).
- Holen Sie die neue Version (
docker compose pull/ das Helm-image.taganheben / das neue Windows-Bundle einspielen). - Starten Sie neu. Migrationen werden beim Start automatisch angewendet — ein Schritt, kein manuelles SQL.
curl /health(prüfen Sieversion) und vergewissern Sie sich, dass/admin/self-licenseweiterhin Ihre Lizenz meldet.
Upgrades sind innerhalb einer Minor-Linie abwärtskompatibel; mit 2+ Knoten können Sie für null Ausfallzeit einen Knoten nach dem anderen aktualisieren. Downgrades, nachdem eine Migration gelaufen ist, werden nicht unterstützt — deshalb ist Schritt 1 wichtig.
Air-Gapped-Betrieb
Nichts hiervon braucht zur Laufzeit das Internet. Ihre Lizenz und die Lizenzen Ihrer Kunden werden offline gegen eingebettete öffentliche Schlüssel geprüft; Credits für nicht verbundene Maschinen verwenden signierte Air-Gapped-Credit-Blöcke (eine Enterprise-Funktion): einen signierten Block ausstellen, offline einlösen, bei erneuter Verbindung abgleichen. Zwei Dinge für einen sauberen Air-Gapped-Betrieb:
- GeoIP deaktivieren: Setzen Sie
KEYRIGHT_GEOIP_URL=(leer), damit die Maschinenstandort-Abfrage des Dashboards nichts nach außen versucht. - Images hineinbringen: Auf einem verbundenen Host
docker save ghcr.io/delta1-labs/keyright:2.2.2(undpostgres:16, falls Sie die mitgelieferte DB verwenden) in ein Tarball, danndocker loadinnerhalb des netzwerkisolierten Netzes.
Fehlerbehebung & FAQ
Der Container beendet sich beim Start mit der Meldung, der KEK müsse gesetzt sein. Setzen Sie KEYRIGHT_KEK auf einen base64-kodierten 32-Byte-Wert (openssl rand -base64 32). Beachten Sie, dass die App sich zuerst mit der Datenbank verbindet und Migrationen ausführt, sodass ein DB-Verbindungsfehler vor diesem auftaucht.
Startfehler bei der Verbindung zur Datenbank / „relation does not exist“. Prüfen Sie KEYRIGHT_DB (Host, Port, Datenbank, Zugangsdaten, SSL Mode). Die Rolle muss Tabellen anlegen können (Konfiguration → Datenbank); vergewissern Sie sich, dass die Datenbank beim ersten Start leer ist und die Rolle ihr Eigentümer ist (oder auf PG15+ CREATE ON SCHEMA public hat).
Der Pod ist in CrashLoopBackOff / der Container startet ständig neu, die Logs zeigen Npgsql Name or service not known / connection refused / einen Timeout. Die App führt ihre Migrationen beim Start aus und beendet sich daher (und startet neu), wenn sie die Datenbank beim Hochfahren nicht erreichen kann — Sie bekommen keinen laufenden, aber nicht bereiten Pod. Bei einer frischen Evaluierungsinstallation mit mitgeliefertem Postgres sind ein paar Neustarts zu erwarten, während Postgres Ready wird, und lösen sich von selbst. Andernfalls ist es fast immer ein Konnektivitätsproblem, kein Bug: (1) Der DB-Host wird nicht aufgelöst oder ist vom App-Knoten aus nicht erreichbar (prüfen Sie DNS/Egress sowie jede NSG-/Firewall-Regel oder die Regel „Azure-Dienste zulassen“ bei einer verwalteten DB); (2) TLS-Mismatch — die meisten verwalteten Postgres-Angebote benötigen SSL Mode=Require (ergänzen Sie ;Trust Server Certificate=true, wenn Sie die CA nicht validieren); (3) falsche Zugangsdaten/falscher Datenbankname. Vorabprüfung vor dem Deployment: Vergewissern Sie sich von einem Pod im selben Netzwerk aus, dass die App den DB-Host und -Port auflösen und erreichen kann. Sobald die DB erreichbar ist, wird der Pod von selbst Ready.
Jede Anfrage liefert 402. Ihre Instanz ist gesperrt — kein gültiger Lizenz-/Testschlüssel (Lizenzierung). Prüfen Sie /admin/self-license; installieren Sie einen Schlüssel über KEYRIGHT_SELF_LICENSE und starten Sie neu.
/admin/* liefert 401. Senden Sie X-Admin-Token: $KEYRIGHT_ADMIN_TOKEN. Der Client-Pfad /v1/* benötigt es nie.
Enthält das Image eine Datenbank? Nein — es enthält nur die App. Betreiben Sie PostgreSQL daneben (siehe die Architekturübersicht und Konfiguration → Datenbank).
Die Apps meiner Kunden können nicht aktivieren. Vergewissern Sie sich, dass die Service-URL des SDK auf Ihre Instanz zeigt (Ihr Produkt verbinden) und dass Produkt-Slug + eingebetteter öffentlicher Schlüssel zu dem Produkt passen, für das Sie Schlüssel ausstellen.
Meine Lizenz ist abgelaufen — was passiert? Eine bezahlte Lizenz erhält eine 15-tägige schreibgeschützte Kulanzfrist (Runtime + Lesezugriffe arbeiten weiter); eine Testversion stoppt sofort. Nach der Kulanzfrist stoppt die Instanz vollständig, bis Sie einen erneuerten Schlüssel installieren (Lizenzierung).
Brauche ich einen Load Balancer? Nur bei 2+ App-Knoten (Skalierung). Ein einzelner Knoten nicht (Sie möchten vielleicht trotzdem einen TLS-terminierenden Proxy davorschalten).
Bereit, Keyright in Ihrer eigenen Umgebung zu betreiben? Sprechen Sie mit dem Vertrieb für eine Testversion oder eine Standard-/Enterprise-Lizenz, oder sehen Sie sich die Preise an.