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) und die Vorgaben für neue Pakete. 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.

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

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