Konfiguration

Variablen in der .env, Secrets, TLS, Ports, Zeitlimits und Image-Overrides

Zielgruppe: Technische Administration

Überblick

oPBWeb trennt die Konfiguration in drei Ebenen:

  • .env im Projektverzeichnis: nicht geheime Einstellungen wie Ports, LDAP-Server, Zeitlimits. Docker Compose liest die Datei und setzt die Werte in docker-compose.yml ein.
  • secrets/: alle Passwörter und Schlüssel als einzelne Dateien. Sie erreichen die Container als Docker-Secrets und werden nie in der .env abgelegt.
  • Oberfläche: die Verbindungen zu den opsi-Configservern (URL, technischer Benutzer, Passwort, Stufe, CA-Zertifikat; in der Ansicht Depots) die Vorgaben für neue Pakete und die Vorlagen des Installer-Assistenten. Diese Einstellungen liegen in der Datenbank, siehe Configserver und Einstellungen für neue Pakete .

Die .env und die fehlenden Secrets erzeugt ./setup-opbweb.sh, siehe Installation . Du kannst die .env danach direkt bearbeiten oder das Skript erneut aufrufen; die vorhandenen Werte sind dann die Vorgaben. Änderungen an .env werden mit dem nächsten ./start.sh wirksam; Docker Compose erzeugt dabei die betroffenen Container neu.

Variablen in der .env

Die Vorlage .env.example enthält alle Variablen der folgenden Tabellen; auskommentierte Zeilen zeigen den Standardwert. Fehlt eine Variable in der .env, gilt der Standardwert. setup-opbweb.sh schreibt die Variablen für Datenbank, Redis, Objektspeicher und CORS_ORIGINS nur, wenn sie schon in der bisherigen .env standen; Variablen, die das Skript nicht kennt, behält es am Ende der Datei.

Allgemein und Anmeldung

VariableStandardDienstBedeutung
TZEurope/BerlinalleZeitzone der Container, auch für die Uhrzeit des täglichen Aufräumens (siehe Einstellungen → Worker )
LOG_LEVELINFOapi, workerDetailgrad der Logs: DEBUG, INFO, WARNING oder ERROR. Ab INFO protokolliert die API den Start von uvicorn, jede HTTP-Anfrage und Probleme bei der LDAP-Anmeldung, siehe Logs
DEBUGfalseapi, workertrue startet uvicorn mit --reload (Hot Reload der API) und den Worker mit Dateiüberwachung und schaltet zusätzlich die Debug-Ausgaben von httpx und python-opsi ein; nur für die Entwicklung. setup-opbweb.sh warnt außerhalb von --dev, wenn der Wert true ist
OPBWEB_LANGLocale des SystemsSkripteSprache von setup-opbweb.sh, start.sh und scripts/init-secrets.sh: de oder en. Setzt setup-opbweb.sh (Option --lang); fehlt der Wert, entscheidet die Locale (de… → Deutsch, sonst Englisch). Die Oberfläche von oPBWeb betrifft das nicht
ADMIN_USERNAMEadminapiName des ersten Administrator-Kontos; wirkt nur, solange die Benutzertabelle leer ist
COOKIE_SECUREfalseapi, workersetup-opbweb.sh setzt true, weil oPBWeb immer per HTTPS läuft (siehe TLS und COOKIE_SECURE ); false nur im Entwicklungs-Stack
CORS_ORIGINS["http://localhost:3100"]apierlaubte Ursprünge als JSON-Liste; nur für den Vite-Dev-Server nötig, im Produktivbetrieb kommt alles über denselben Ursprung
ACCESS_TOKEN_MINUTES15apiGültigkeit des Zugriffs-Tokens in Minuten (wird im Browser automatisch erneuert)
REFRESH_TOKEN_DAYS7apiGültigkeit des Refresh-Cookies in Tagen, also wie lange eine Anmeldung ohne erneute Passworteingabe hält
ACCOUNT_MAX_FAILED_ATTEMPTS5apiFehlversuche, nach denen ein lokales Konto für die Adresse gesperrt wird, von der sie kamen. Von einer Adresse sind insgesamt viermal so viele Fehlversuche erlaubt (alle Konten, auch LDAP), danach antwortet die API mit 429. Gesperrt für alle Adressen wird ein Konto erst nach zehnmal so vielen Fehlversuchen.
ACCOUNT_LOCKOUT_MINUTES15apiDauer der Sperren und Zeitraum, in dem Fehlversuche zählen
LDAP_*–apiAnmeldung über LDAP/AD, siehe LDAP-Anmeldung

opsi und Pakete

VariableStandardDienstBedeutung
OPSI_TIMEOUT_SECONDS60workerZeitlimit in Sekunden für die übrigen opsi-Aufrufe (JSON-RPC, Auflisten per WebDAV)
OPSI_INSTALL_TIMEOUT_SECONDS3600workerZeitlimit in Sekunden für den Upload ins Repository und für depot_installPackage bzw. depot_uninstallPackage
JOB_TIMEOUT_SECONDS28800workerObergrenze in Sekunden für einen ganzen Job, z. B. eine Installation auf mehreren Depots einschließlich Wartezeit auf belegte Depots
BUILD_COMPRESSIONzstdworkerKompression gebauter .opsi-Dateien: zstd (Standard von opsi 4.3) oder gzip

BUILD_COMPRESSION wirkt nur auf neue Builds. Bereits gebaute Pakete behalten ihre Kompression bis zum nächsten Bauen.

Frontend und Images

VariableStandardBedeutung
FRONTEND_HTTP_PORT80Host-Port für HTTP
FRONTEND_HTTPS_PORT443Host-Port für HTTPS
BACKEND_IMAGEopbweb-backend:latest (Dev: :dev)Image für api und worker
FRONTEND_IMAGEopbweb-frontend:latestImage für frontend
GARAGE_INIT_IMAGEopbweb-garage-init:1.0.0Image für garage-init
OPBWEB_REGISTRYRegistry der GitLab-CI (registry.gitlab.open-mind.space/pages/opsipackagebuilder-web)nur für setup-opbweb.sh: Präfix, aus dem das Skript die Image-Namen bildet (<Präfix>/backend:<Version> usw.); auch als Umgebungsvariable beim Aufruf des Skripts möglich

Bleiben die drei Image-Variablen leer, gelten die lokal gebauten Images, siehe Image-Overrides und Registry-Mirror .

Datenbank, Redis, Objektspeicher

Diese Variablen musst du normalerweise nicht setzen. Sie sind für Sonderfälle da, etwa externe Dienste statt der mitgelieferten Container; in .env.example stehen sie auskommentiert.

VariableStandardBedeutung
DB_NAMEopbwebName der Datenbank, die MariaDB beim ersten Start anlegt
DB_USERopbwebDatenbankbenutzer
DATABASE_URLmysql+asyncmy://opbweb@db:3306/opbwebVerbindung der Anwendung (ohne Passwort; das Passwort fügt die Anwendung aus dem Secret ein)
DATABASE_URL_SYNCmysql+pymysql://opbweb@db:3306/opbwebVerbindung für die Migrationen
REDIS_URLredis://redis:6379/0Redis (ohne Passwort)
S3_ENDPOINTgarage:3900S3-Endpunkt von Garage
S3_BUCKETpackagesBucket; garage-init legt ihn unter diesem Namen an
S3_SECUREfalseTLS zum S3-Endpunkt

Secrets

scripts/init-secrets.sh legt fehlende Secrets im Verzeichnis secrets/ an. setup-opbweb.sh und start.sh rufen das Skript auf, start.sh bei jedem Start. Vorhandene Dateien überschreibt es nie. Gib Inhalte von Secrets nicht in Tickets oder Logs weiter.

Das Verzeichnis secrets/ hat die Rechte 750, die Dateien 444; das Skript setzt sie bei jedem Lauf neu. Docker reicht die Secret-Dateien mit den Rechten des Hosts in die Container durch, deren Prozesse unter anderen Benutzern laufen (MariaDB, Redis, die Anwendung als appuser mit UID 1000). Mit 600 könnten sie die Dateien auf einem Linux-Host nicht lesen. Andere Benutzer des Hosts hält das Verzeichnis mit 750 fern.

DateiErzeugtVerwendet vonZweck
db_password.txtZufallswert (hex)db, api, workerPasswort des MariaDB-Benutzers opbweb
db_root_password.txtZufallswert (hex)dbRoot-Passwort von MariaDB, auch für Dumps
redis_password.txtZufallswert (hex)redis, api, workerPasswort für Redis
redis.aclaus redis_password.txtredisACL-Datei von Redis
jwt_secret_key.txtZufallswert (hex, 64 Zeichen)apiSignatur der Anmelde-Tokens
opsi_key_public.pemRSA-Schlüssel (3072 Bit), öffentlicher Teilapi, workerverschlüsselt das gespeicherte opsi-Passwort
opsi_key_private.pemRSA-Schlüssel (3072 Bit), privater Teilworkerentschlüsselt das opsi-Passwort; nur der Worker spricht mit opsi
settings_encryption_key.txtZufallswert (hex, 64 Zeichen)workerAES-256-Schlüssel der Versionen vor 0.18.6; der Worker liest damit alte Einträge und verschlüsselt sie beim Start neu
garage_rpc_secret.txtZufallswert (hex, 64 Zeichen)garageRPC-Secret von Garage
garage_admin_token.txtZufallswert (hex, 64 Zeichen)garage, garage-initToken der Garage-Admin-API
admin_password.txt20 ZeichenapiPasswort des ersten Administrators; wird beim Anlegen einmal angezeigt
ldap_bind_password.txtleer; setup-opbweb.sh schreibt das eingegebene Passwort hineinapiPasswort des LDAP-Dienstkontos

Die S3-Zugangsdaten stehen nicht in secrets/. garage-init erzeugt den Schlüssel in Garage und schreibt ihn in das Volume garage-credentials.

Secrets nachträglich ändern

Nicht jedes Secret lässt sich nach dem ersten Start einfach austauschen:

DateiFolge einer Änderung
db_password.txt, db_root_password.txtMariaDB übernimmt die Passwörter nur bei der ersten Initialisierung. Eine geänderte Datei passt danach nicht mehr zur Datenbank; das Passwort müsstest du zusätzlich in MariaDB selbst ändern.
redis_password.txtstart.sh erzeugt redis.acl beim nächsten Start aus dem neuen Passwort und startet Redis neu.
jwt_secret_key.txtAlle Sitzungen werden ungültig, alle müssen sich neu anmelden.
opsi_key_private.pem, opsi_key_public.pemNur als Paar austauschen (beide löschen, init-secrets.sh erzeugt ein neues Paar). Die gespeicherten opsi-Passwörter lassen sich danach nicht mehr entschlüsseln; trage sie unter Depots → Configserver für jeden Configserver neu ein.
settings_encryption_key.txtWird nur für Einträge aus Versionen vor 0.18.6 gebraucht; nicht ändern, solange solche Einträge umgestellt werden müssen.
garage_rpc_secret.txt, garage_admin_token.txtNicht ändern; sie gehören zum vorhandenen Objektspeicher.
admin_password.txtWirkt nur, solange kein Benutzer existiert. Später ändert der Administrator sein Passwort in der Oberfläche.
ldap_bind_password.txtUnkritisch; nach der Änderung den Stack neu starten.

Die Dateien sind schreibgeschützt (444). Zum Ändern hebst du den Schutz kurz auf und setzt ihn danach wieder, zum Beispiel:

chmod u+w secrets/ldap_bind_password.txt
# Datei bearbeiten
chmod 444 secrets/ldap_bind_password.txt

Das LDAP-Passwort kannst du auch mit ./setup-opbweb.sh neu eingeben. Die Dienste lesen die Secrets beim Start. Starte nach einer Änderung den Stack neu (./stop.sh, dann ./start.sh).

TLS und COOKIE_SECURE

Der Frontend-Container entscheidet bei jedem Start anhand der Dateien im Verzeichnis certs/:

Vorhandennginx liefert aus
certs/fullchain.pem und certs/key.pemHTTPS auf Container-Port 443 (Host: FRONTEND_HTTPS_PORT), HTTP/2, TLS 1.2 und 1.3; Container-Port 80 (Host: FRONTEND_HTTP_PORT) leitet mit 301 auf https://<Host>:<FRONTEND_HTTPS_PORT> weiter
eine oder beide Dateien fehlennur HTTP auf Container-Port 80 (nur im Entwicklungs-Stack oder bei einer von Hand angelegten .env)

setup-opbweb.sh sorgt außerhalb des Entwicklungs-Stacks immer für ein Zertifikat: mitgebracht (fullchain.pem und key.pem neben dem Skript), vorhanden oder self-signed, siehe Installation . Das Log des Containers zeigt die Wahl: „TLS-Zertifikat gefunden – HTTPS auf Port 443“ bzw. „Kein TLS-Zertifikat – HTTP auf Port 80“. fullchain.pem enthält das Serverzertifikat mit allen Zwischenzertifikaten. Den Zielport der Weiterleitung bekommt der Container als HTTPS_PORT (= FRONTEND_HTTPS_PORT).

Mit HTTPS sendet nginx den Header Strict-Transport-Security (ein Jahr). Browser, die oPBWeb einmal per HTTPS geöffnet haben, verweigern danach HTTP für diesen Hostnamen.

Nach dem Austausch eines Zertifikats (neue Dateien neben das Skript legen und ./setup-opbweb.sh --updateonly, oder direkt in certs/ ersetzen) genügt ein Neustart des Frontends:

docker restart opbweb-frontend

Zusätzlich lässt nginx pro Adresse höchstens 10 Anmeldeversuche pro Minute durch (kurzzeitig 10 mehr). Beide Grenzen setzen voraus, dass oPBWeb die echte Adresse der Clients sieht; steht ein weiterer Proxy davor oder verdeckt Docker die Adressen, teilen sich alle Benutzer eine Adresse.

COOKIE_SECURE steuert das Secure-Flag des Refresh-Cookies opbweb_refresh (7 Tage gültig, httpOnly, SameSite=Strict). Kommt die Anmeldung über HTTPS, setzt die API das Flag immer, auch bei false. Für die Einstellung gilt:

BetriebCOOKIE_SECURE
HTTPStrue
nur HTTPfalse; bei true speichert der Browser das Cookie nicht, und die Sitzung lässt sich nicht erneuern

Ports

Port im ContainerHost-PortDienst
80FRONTEND_HTTP_PORT (80)nginx, HTTP
443FRONTEND_HTTPS_PORT (443)nginx, HTTPS

Beide Ports werden immer veröffentlicht, aber nur einer antwortet. Alle anderen Dienste sind im Produktivbetrieb nicht von außen erreichbar. Die zusätzlichen Ports des Entwicklungs-Stacks stehen unter Betrieb und Aktualisierung .

Ausgehend braucht der Worker HTTPS auf Port 4447 zum opsi-Configserver und zu den Depots.

Installer-Analyse (opsi-setup-detector)

Der Assistent Paket aus Installer erzeugen analysiert Installer im Worker. Die Werkzeuge dafür sind im Backend-Image enthalten, eine Konfiguration in der .env ist nicht nötig:

WerkzeugHerkunft im ImageWofür
pefilePython-Paket aus requirements.txtVersionsressource und Architektur von Windows-Programmen
msiinfoDebian-Paket msitoolsEigenschaften und Tabellen von MSI-Dateien
innoextracteigene Build-Stufe innoextract im backend/DockerfileSetup-Header von Inno-Setup-Installern
7z bzw. 7zzDebian-Paket 7zipeingebettetes MSI aus Wrapper-Installern (InstallShield mit MSI, Advanced Installer, WiX-Bundles) auspacken
dpkg-debBasis-ImageMetadaten von Debian-Paketen
rpmDebian-Paket rpmMetadaten von RPM-Paketen
diec (Detect-It-Easy)nicht enthaltenoptionale zweite Meinung zum Installertyp

Fehlt ein Werkzeug, bricht die Analyse nicht ab; sie vermerkt einen Hinweis und arbeitet mit dem, was sie lesen kann. Welche Werkzeuge der Container findet, liefert GET /api/detector/tools (angemeldet) als Pfad je Werkzeug, null für fehlende. Externe Aufrufe brechen nach 300 Sekunden ab.

Detect-It-Easy nachrüsten

Detect-It-Easy braucht rund 550 MB Qt-Bibliotheken und ist deshalb nicht im Image. oPBWeb verwendet es, wenn diec im PATH des Worker-Containers liegt oder die Umgebungsvariable DIEC_PATH auf die ausführbare Datei zeigt. Die .env reicht DIEC_PATH nicht an die Container durch. Zum Nachrüsten baust du ein eigenes Backend-Image auf Basis von opbweb-backend mit Detect-It-Easy und trägst es als BACKEND_IMAGE ein (siehe Image-Overrides ), oder du ergänzt am Dienst worker in einer eigenen Compose-Datei ein Volume mit Detect-It-Easy und DIEC_PATH.

Vorlagen und Installertabelle

Beides stammt aus den Quellen des opsi-setup-detectors (Repository opsi-org/lazarus, Ordner opsi-misc/opsisetupdetector, AGPL-3.0) und liegt im Image unter src/detector/resources/ (im Repository backend/src/detector/resources/):

  • installers.toml: die Installertabelle mit Erkennungsmustern, Silent- und Unattended-Parametern, Deinstallationsprogramm, Exit-Code-Funktion und Hinweisen je Installertyp. Sie wird mit backend/tools/osd_installers_to_toml.py aus osdbasedata.pas erzeugt und nicht von Hand bearbeitet.
  • templates/: die Script-Vorlagen (template-files) als <Kanal>/<Gruppe>/<Datei>. Beim Start kopiert die API sie in die Tabelle detector_templates; ab dann arbeiten Generator und die Ansicht Vorlagen mit der Datenbank, siehe Vorlagen für den Installer-Assistenten .

Eine neuere Fassung der Vorlagen kann ein Administrator ohne neues Image als ZIP importieren. Die Installertabelle ändert sich nur mit einem neuen Image. Wie beides im Quellcode aktualisiert wird, beschreibt backend/src/detector/resources/README.md; kurz:

git clone --depth 1 --filter=blob:none --sparse https://github.com/opsi-org/lazarus.git /tmp/lazarus
git -C /tmp/lazarus sparse-checkout set opsi-misc/opsisetupdetector
python3 backend/tools/osd_installers_to_toml.py /tmp/lazarus/opsi-misc/opsisetupdetector/osdbasedata.pas
rsync -a --delete /tmp/lazarus/opsi-misc/opsisetupdetector/template-files/ backend/src/detector/resources/templates/

rsync --delete entfernt dabei die winget-Vorlagen, die oPBWeb selbst mitbringt (im Original fehlen sie); stell sie danach aus Git wieder her. Bringt die neue Installertabelle einen neuen Installertyp mit, braucht er eine ID im Skript und gegebenenfalls Code in src/detector/analyze.py.

Zeitlimits und Größen

GrenzeWertEinstellbar
Upload und Installation/Deinstallation auf dem Depot3600 sOPSI_INSTALL_TIMEOUT_SECONDS
Übrige opsi-Aufrufe60 sOPSI_TIMEOUT_SECONDS
Laufzeit eines Jobs8 h (28800 s)JOB_TIMEOUT_SECONDS
Parallele Jobs im Worker10nein
Dateimanager-Aufrufe API → Worker60 snein
Warten auf ein belegtes Depotbis 6 hnein
Uploadgröße über nginx20 GBnein (client_max_body_size in frontend/nginx/common.inc)
nginx-Timeout zur API660 s ohne Datenflussnein
Download-Links2 minnein
Textdateien im Editor5 MB (Paketdateien), 2 MB (Dateimanager)nein
Externe Werkzeuge der Installer-Analyse300 s je Aufrufnein
Einzelne Vorlage, Vorlagen-ZIP16 MB je Datei, 5000 Dateien je ZIPnein

Image-Overrides und Registry-Mirror

Ohne Overrides baut ./start.sh --build die eigenen Images lokal und nennt sie opbweb-backend:latest, opbweb-frontend:latest und opbweb-garage-init:1.0.0. Mit BACKEND_IMAGE, FRONTEND_IMAGE und GARAGE_INIT_IMAGE verwendest du stattdessen fertige Images, zum Beispiel aus der GitLab-Registry (siehe Build und Auslieferung ). setup-opbweb.sh setzt die drei Variablen, wenn du bei der Frage nach den Images r wählst; das Präfix kommt aus OPBWEB_REGISTRY. Von Hand sieht das so aus (Beispiel, an deine Registry anzupassen):

BACKEND_IMAGE=registry.example.com/gruppe/opsipackagebuilder-web/backend:<version>
FRONTEND_IMAGE=registry.example.com/gruppe/opsipackagebuilder-web/frontend:<version>
GARAGE_INIT_IMAGE=registry.example.com/gruppe/opsipackagebuilder-web/garage-init:latest

Danach holst du die Images und startest ohne --build:

docker login registry.example.com
docker compose pull
./start.sh