Betrieb und Aktualisierung

Stack starten und stoppen, Logs, Health-Endpunkte, Updates, Versionierung und Entwicklungs-Stack

Zielgruppe: Technische Administration

Überblick

Für den täglichen Betrieb brauchst du zwei Skripte im Projektverzeichnis: start.sh und stop.sh. Dieses Kapitel beschreibt außerdem, wo du Logs und Zustand der Dienste findest, wie du oPBWeb aktualisierst und was du auf der opsi-Seite beachten musst. Alle Befehle führst du im Projektverzeichnis aus.

Stack starten und stoppen

start.sh

./start.sh [--build] [--logs] [--dev | --test] [--lang de|en]
OptionWirkung
(keine)startet den Produktiv-Stack (docker-compose.yml) mit den vorhandenen Images
--buildbaut die eigenen Images vor dem Start neu
--logsfolgt nach dem Start den Logs aller Container (logs -f --tail=50); Strg+C beendet nur die Anzeige
--devnimmt docker-compose.dev.yml hinzu (Entwicklungs-Stack, siehe unten); nur im Klon mit Quellen
--testnimmt docker-compose.test.yml hinzu: zwei opsi-Mocks als Configserver Test und Produktion, siehe Testumgebung
--lang de bzw. --lang enSprache der Ausgaben für diesen Aufruf (sonst OPBWEB_LANG aus der .env)
-h, --helpzeigt die Hilfe

Ablauf: Das Skript bricht ab, wenn .env fehlt („.env fehlt – bitte ./setup-opbweb.sh ausführen (im Entwickler-Checkout: ./setup-opbweb.sh –dev).“), ruft scripts/init-secrets.sh auf, führt docker compose up -d aus und zeigt mit docker compose ps den Status. Laufende Container, deren Konfiguration sich nicht geändert hat, bleiben dabei unberührt. start.sh holt keine neuen Fremd-Images; dafür siehe Aktualisieren .

stop.sh

./stop.sh

Das Skript hat keine Optionen. Es führt docker compose down mit docker-compose.yml und den vorhandenen Overlays (docker-compose.dev.yml, docker-compose.test.yml) aus und stoppt damit Produktiv-, Dev- und Testdienste gleichermaßen. Container und Netze werden entfernt, die Volumes mit Datenbank und Objektspeicher bleiben erhalten.

Einzelne Dienste neu starten

docker restart opbweb-worker
docker restart opbweb-frontend   # z. B. nach einem Zertifikatswechsel

Ein Neustart des Workers unterbricht laufende Jobs. Prüfe vorher unter Jobs, ob gerade Installationen laufen.

Container

ContainerDienstHinweis
opbweb-frontendnginxWeboberfläche, Handbuch, Proxy
opbweb-apiAPIführt beim Start die Migrationen aus
opbweb-workerWorkerJobs, Cron, opsi-Verbindung
opbweb-dbMariaDB
opbweb-redisRedis
opbweb-garageGarageObjektspeicher
opbweb-garage-initEinrichtung Garageläuft bei jedem Start kurz und endet mit Exit-Code 0
opbweb-opsi-mocknur Devnachgebauter opsiconfd (erstes opsi-System)
opbweb-opsi-mock2nur Devnachgebauter opsiconfd (zweites opsi-System)
opbweb-frontend-devnur DevVite-Dev-Server
opbweb-manual-devnur DevHugo-Vorschau des Handbuchs
opbweb-launcher-buildnur Devbaut die Launcher-ZIPs beim Start und endet mit Exit-Code 0
opbweb-launcher-devnur Devliefert die Launcher-ZIPs aus

Den Zustand zeigt docker compose ps (Produktiv-Stack) bzw. docker compose ps -a einschließlich beendeter Container wie garage-init.

Logs

docker logs -f --tail=100 opbweb-api
docker logs -f --tail=100 opbweb-worker
docker compose logs -f --tail=50          # alle Dienste
ContainerWas du dort findest
opbweb-apiMigrationen und Start von uvicorn, Anlegen des ersten Admins, HTTP-Zugriffe (eine Zeile je Anfrage), Probleme bei der LDAP-Anmeldung
opbweb-workerJob-Ausführung, opsi-Prüfung (Standard alle 5 Minuten), Fehler bei Verbindungen zu opsiconfd
opbweb-frontendWahl von HTTP oder HTTPS, Zugriffe und nginx-Fehler
opbweb-garage-initEinrichtung von Layout, Schlüssel und Bucket

Den Detailgrad von api und worker steuert LOG_LEVEL in der .env (DEBUG, INFO, WARNING, ERROR; Standard INFO). Eine Änderung wird mit dem nächsten ./start.sh wirksam.

Bei der LDAP-Anmeldung protokolliert die API, woran eine Anmeldung scheitert: Benutzer nicht gefunden (null Treffer für den Suchfilter) und falsches Passwort auf Stufe INFO, keine Gruppe mit einer Rolle auf Stufe WARNING. Mit LOG_LEVEL=WARNING oder ERROR siehst du die ersten beiden Fälle also nicht. Zum Beispiel:

docker logs opbweb-api 2>&1 | grep "LDAP login"

python-opsi und der HTTP-Client httpx geben nur Warnungen und Fehler aus. Ihre Debug-Ausgaben schaltet erst DEBUG=true ein; das startet die API aber auch mit Hot Reload und ist nur für die Entwicklung gedacht, siehe Konfiguration .

Das vollständige Protokoll jedes Jobs findest du zusätzlich in der Oberfläche unter Jobs, siehe Jobs .

Zustand prüfen

EndpunktAnmeldungAntwort
/healthneinstatisch healthy von nginx; prüft nur, ob nginx antwortet
/api/healthnein{"status":"ok","version":"…"}; die API ist über nginx erreichbar
/api/health/detailsja (Bearer-Token)Prüfungen database, redis, storage, worker, opsi mit ok, Details und Dauer
/api/system/databaseja, AdminZeilen und Größe je Datenbanktabelle
/api/system/storageja, AdminBelegung des Objektspeichers je Bereich, Deduplizierung, nicht verwendete und fehlende Blobs
/api/system/storage/objectsja, AdminObjekte eines Bereichs mit den Paketversionen, die sie verwenden (Grundlage des Bucket-Browsers)
Seite Systemstatusja, alle Rollendieselben Prüfungen als Tabelle, alle 10 Sekunden aktualisiert

Für ein einfaches Monitoring eignet sich /api/health:

curl -fsS https://opbweb.example.local/api/health

Die Detailprüfung bewertet so:

PrüfungFehler, wenn …
Datenbankkeine Verbindung; die Details nennen sonst MariaDB-Version und Schema-Revision
Rediskeine Verbindung
Objektspeicherkeine Verbindung oder Bucket fehlt („Bucket ‘…’ fehlt“)
Workerkein Heartbeat („kein Lebenszeichen“) oder letzter Heartbeat älter als 90 Sekunden
opsi-Servernoch nicht geprüft, kein Configserver eingerichtet oder bei mindestens einem Configserver: Verbindung fehlgeschlagen, keine Admin-Rechte, neues CA-Zertifikat noch nicht übernommen oder Warnung vor dem Ablauf

Administratoren sehen im Systemstatus zusätzlich Tabellengrößen der Datenbank, die Belegung des Objektspeichers und den Bucket-Browser, siehe Systemstatus .

Zeitgesteuerte Aufgaben

Der Worker führt diese Aufgaben selbst aus; einen Cron-Eintrag auf dem Host brauchst du nicht.

AufgabeZeitpunktWirkung
Heartbeatalle 30 SekundenLebenszeichen für den Systemstatus
opsi-Prüfungalle 5 Minuten (Standard)Verbindung, Depot-Abgleich, CA-Vergleich, Ablaufwarnung 60 Tage vorher
Aufräumen temporärer Dateientäglich 03:17 Uhr (Standard)löscht uploads/ und downloads/ älter als 24 Stunden

Die Zeiten der opsi-Prüfung und des Aufräumens stellst du unter Einstellungen → Worker ein; sie gelten ohne Neustart.

Nicht mehr verwendete Paketdateien (Blobs) und Build-Ergebnisse entfernt die automatische Aufgabe nicht. Das macht ein Administrator bei Bedarf mit Bereinigen … im Systemstatus : erst ein Probelauf, dann das bestätigte Löschen.

Aktualisieren

  1. Sichere Datenbank und Objektspeicher, siehe Sicherung und Wiederherstellung . Datenbankmigrationen lassen sich nicht ohne Weiteres rückgängig machen.

  2. Prüfe unter Jobs, dass keine Installationen laufen.

  3. Hole den neuen Stand, zum Beispiel mit git pull oder mit einem neuen Stack-ZIP , das du über die Installation entpackst. .env, secrets/ und certs/ enthält das ZIP nicht, sie bleiben erhalten.

  4. Bringe die .env auf den neuen Stand:

    ./setup-opbweb.sh --updateonly
    

    Das Skript übernimmt alle vorhandenen Werte, ergänzt neue Variablen mit ihrem Standardwert und legt neue Secrets an; vorhandene Secrets bleiben unverändert. Willst du dabei Werte ändern, rufe ./setup-opbweb.sh ohne Option auf.

  5. Aktualisiere die Images und starte den Stack:

    • Lokal gebaute Images:

      ./start.sh --build
      

      --build nutzt den Build-Cache von Docker. Sicherheitsupdates der Basis-Images und der Systempakete kommen so nicht unbedingt an. Bau deshalb bei einem Sicherheitsupdate ohne Cache und mit frischen Basis-Images, danach ./start.sh:

      docker compose build --pull --no-cache
      
    • Images aus einer Registry: Trage die neuen Image-Versionen ein, entweder interaktiv mit ./setup-opbweb.sh (Fragen nach den Versionen der Images; die Vorgabe ist die bisherige Version) oder direkt in BACKEND_IMAGE, FRONTEND_IMAGE und GARAGE_INIT_IMAGE in der .env. --updateonly behält die bisherigen Versionen. Liegt eine versions.env daneben (Stack-ZIP), sind ihre Versionen die Vorgaben, auch für --updateonly; das Entpacken eines neuen ZIPs und --updateonly stellen die Images also auf dessen Versionen um. Danach:

      docker compose pull
      ./start.sh
      

      Verwendest du die Tags latest, genügen docker compose pull und ./start.sh.

  6. Die API führt beim Start automatisch alembic upgrade head aus. Prüfe danach das Log:

    docker logs opbweb-api 2>&1 | head -50
    
  7. Kontrolliere in der Oberfläche die Versionen in der Statusleiste („Frontend …“, „Backend …“) und den Systemstatus.

Neue Versionen der Fremd-Images (MariaDB 11.4, Redis 7, Garage v2.2.0) innerhalb ihrer Tags holt start.sh nicht automatisch. Beispiel, bei Bedarf auszuführen:

docker compose pull db redis garage
./start.sh

Um auch die Basis-Images der eigenen Images (node, nginx, python) zu aktualisieren, baue mit docker compose build --pull und starte danach mit ./start.sh. Das betrifft nur lokal gebaute Images.

Versionierung

Backend und Frontend haben getrennte Versionsnummern nach dem Schema MAJOR.MINOR.PATCH (Meilenstein, Phase, Fehlerbehebung). Die Oberfläche zeigt beide in der Statusleiste, /api/health liefert die Backend-Version.

Gesetzt werden die Versionen mit set-version.sh; welche Dateien betroffen sind, steht in version.yaml (Backend: backend/src/core/version.py und backend/pyproject.toml, Frontend: frontend/package.json über npm version).

AufrufWirkung
./set-version.shzeigt die aktuellen Versionen
./set-version.sh 0.14.0setzt alle Komponenten (mit Rückfrage; --force ohne)
./set-version.sh --backend 0.13.1setzt nur das Backend
./set-version.sh --frontend 0.13.1setzt nur das Frontend
./set-version.sh --component <name> <version>setzt eine Komponente aus version.yaml
./set-version.sh --config <datei>verwendet eine andere Konfigurationsdatei

Eine geänderte Versionsdatei auf dem Standard-Branch löst in der GitLab-CI den Build des passenden Images aus, siehe Build und Auslieferung .

opsiconfd: admin-networks

Der Worker ruft opsiconfd mit Admin-Rechten auf. Ist in der Konfiguration von opsiconfd die Option admin-networks gesetzt, muss die Absenderadresse des Workers darin liegen, sonst antwortet opsiconfd mit HTTP 403.

Welche Adresse opsiconfd sieht, hängt vom Standort ab (abgeleitet aus dem Docker-Netzverhalten, bitte im opsiconfd-Log gegenprüfen):

  • oPBWeb auf dem Configserver selbst: die Adresse des Workers im Docker-Netz opbweb_opsi-net. Das Subnetz zeigt:

    docker network inspect opbweb_opsi-net --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
    
  • oPBWeb auf einem anderen Host: in der Regel die Adresse des Docker-Hosts, weil Docker ausgehenden Verkehr maskiert.

./stop.sh entfernt die Docker-Netze; beim nächsten Start kann opbweb_opsi-net ein anderes Subnetz bekommen. Trage daher entweder den gesamten Adressbereich ein, aus dem Docker seine Netze vergibt, oder prüfe das Subnetz nach jedem Neustart. Die Syntax der Option beschreibt das opsi-Handbuch; nach der Änderung muss opsiconfd neu starten.

Entwicklungs-Stack

Der Entwicklungs-Stack ist für die Weiterentwicklung gedacht, nicht für den Betrieb. In einem frischen Entwickler-Checkout legst du zuerst die .env an (aus .env.example, ohne Rückfragen) und startest dann mit lokal gebauten Images:

./setup-opbweb.sh --dev
./start.sh --dev --build

Er ergänzt den Produktiv-Stack um Hot Reload (Quellen als Bind-Mounts, DEBUG=true), zwei nachgebaute opsiconfd, eine Vorschau des Handbuchs und die Launcher-ZIPs. API und Worker laufen mit dem Image opbweb-backend:dev.

WasAdresse
Vite-Dev-Server (Oberfläche mit Hot Reload)http://localhost:3100
Handbuch-Vorschau (manual-dev, über den Vite-Proxy)http://localhost:3100/manual/
Launcher-ZIPs (launcher-dev, über den Vite-Proxy)http://localhost:3100/downloads/
API mit OpenAPI-Oberflächehttp://localhost:8100/api/docs
nginx-FrontendPort aus FRONTEND_HTTP_PORT bzw. FRONTEND_HTTPS_PORT
MariaDBPort 3307
RedisPort 6380
Garage S3Port 3910
opsiconfd-Mock (opsi-mock)opsi-config.mock und depot1.mock, nur im Docker-Netz
zweiter opsiconfd-Mock (opsi-mock2)opsi-config2.mock und depot2.mock, nur im Docker-Netz

Jeder Mock bildet einen Configserver und ein Depot nach, einschließlich Installieren, Deinstallieren und WebDAV. opbweb-opsi-mock ist das erste opsi-System: Solange kein Configserver eingerichtet ist, trägt die API ihn beim Start als „opsiconfd-Mock“ mit der Stufe Test ein (URL http://opsi-config.mock:4447, Benutzer opsiadm, Passwort mock, ohne TLS-Prüfung). opbweb-opsi-mock2 ist ein zweites, unabhängiges opsi-System für Tests mit mehreren Configservern; er wird nicht automatisch eingetragen. Wer ihn in der Oberfläche nutzen will, legt ihn unter Depots mit + an (URL http://opsi-config2.mock:4447, Benutzer opsiadm, Passwort mock, TLS-Prüfung aus).

Die End-to-End-Tests tragen beide Mocks selbst als Configserver ein (als „t-Mock 1“ und „t-Mock 2“, falls noch nicht vorhanden), entfernen sie danach wieder und arbeiten nur auf deren Depots. Sie setzen nicht voraus, dass der Mock der einzige oder voreingestellte Configserver ist, und laufen auch dann, wenn zusätzlich ein echter opsi-Server eingerichtet ist. Die Handbuch-Vorschau aktualisiert sich nicht von selbst; lade die Seite nach einer Änderung neu.