Konfiguration
Zielgruppe: Technische Administration
Überblick
oPBWeb trennt die Konfiguration in drei Ebenen:
.envim Projektverzeichnis: nicht geheime Einstellungen wie Ports, LDAP-Server, Zeitlimits. Docker Compose liest die Datei und setzt die Werte indocker-compose.ymlein.secrets/: alle Passwörter und Schlüssel als einzelne Dateien. Sie erreichen die Container als Docker-Secrets und werden nie in der.envabgelegt.- 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
| Variable | Standard | Dienst | Bedeutung |
|---|---|---|---|
TZ | Europe/Berlin | alle | Zeitzone der Container, auch für die Uhrzeit des täglichen Aufräumens (siehe Einstellungen → Worker ) |
LOG_LEVEL | INFO | api, worker | Detailgrad 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 |
DEBUG | false | api, worker | true 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_LANG | Locale des Systems | Skripte | Sprache 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_USERNAME | admin | api | Name des ersten Administrator-Kontos; wirkt nur, solange die Benutzertabelle leer ist |
COOKIE_SECURE | false | api, worker | setup-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"] | api | erlaubte Ursprünge als JSON-Liste; nur für den Vite-Dev-Server nötig, im Produktivbetrieb kommt alles über denselben Ursprung |
ACCESS_TOKEN_MINUTES | 15 | api | Gültigkeit des Zugriffs-Tokens in Minuten (wird im Browser automatisch erneuert) |
REFRESH_TOKEN_DAYS | 7 | api | Gültigkeit des Refresh-Cookies in Tagen, also wie lange eine Anmeldung ohne erneute Passworteingabe hält |
ACCOUNT_MAX_FAILED_ATTEMPTS | 5 | api | Fehlversuche, 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_MINUTES | 15 | api | Dauer der Sperren und Zeitraum, in dem Fehlversuche zählen |
LDAP_* | – | api | Anmeldung über LDAP/AD, siehe LDAP-Anmeldung |
opsi und Pakete
| Variable | Standard | Dienst | Bedeutung |
|---|---|---|---|
OPSI_TIMEOUT_SECONDS | 60 | worker | Zeitlimit in Sekunden für die übrigen opsi-Aufrufe (JSON-RPC, Auflisten per WebDAV) |
OPSI_INSTALL_TIMEOUT_SECONDS | 3600 | worker | Zeitlimit in Sekunden für den Upload ins Repository und für depot_installPackage bzw. depot_uninstallPackage |
JOB_TIMEOUT_SECONDS | 28800 | worker | Obergrenze in Sekunden für einen ganzen Job, z. B. eine Installation auf mehreren Depots einschließlich Wartezeit auf belegte Depots |
BUILD_COMPRESSION | zstd | worker | Kompression 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
| Variable | Standard | Bedeutung |
|---|---|---|
FRONTEND_HTTP_PORT | 80 | Host-Port für HTTP |
FRONTEND_HTTPS_PORT | 443 | Host-Port für HTTPS |
BACKEND_IMAGE | opbweb-backend:latest (Dev: :dev) | Image für api und worker |
FRONTEND_IMAGE | opbweb-frontend:latest | Image für frontend |
GARAGE_INIT_IMAGE | opbweb-garage-init:1.0.0 | Image für garage-init |
OPBWEB_REGISTRY | Registry 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.
| Variable | Standard | Bedeutung |
|---|---|---|
DB_NAME | opbweb | Name der Datenbank, die MariaDB beim ersten Start anlegt |
DB_USER | opbweb | Datenbankbenutzer |
DATABASE_URL | mysql+asyncmy://opbweb@db:3306/opbweb | Verbindung der Anwendung (ohne Passwort; das Passwort fügt die Anwendung aus dem Secret ein) |
DATABASE_URL_SYNC | mysql+pymysql://opbweb@db:3306/opbweb | Verbindung für die Migrationen |
REDIS_URL | redis://redis:6379/0 | Redis (ohne Passwort) |
S3_ENDPOINT | garage:3900 | S3-Endpunkt von Garage |
S3_BUCKET | packages | Bucket; garage-init legt ihn unter diesem Namen an |
S3_SECURE | false | TLS zum S3-Endpunkt |
Ändere DB_NAME und DB_USER nicht nach dem ersten Start. MariaDB legt Datenbank und Benutzer nur bei der ersten Initialisierung des Volumes an. Außerdem enthalten die Standard-URLs den Datenbanknamen opbweb fest; wer DB_NAME ändert, muss DATABASE_URL und DATABASE_URL_SYNC passend setzen.
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.
| Datei | Erzeugt | Verwendet von | Zweck |
|---|---|---|---|
db_password.txt | Zufallswert (hex) | db, api, worker | Passwort des MariaDB-Benutzers opbweb |
db_root_password.txt | Zufallswert (hex) | db | Root-Passwort von MariaDB, auch für Dumps |
redis_password.txt | Zufallswert (hex) | redis, api, worker | Passwort für Redis |
redis.acl | aus redis_password.txt | redis | ACL-Datei von Redis |
jwt_secret_key.txt | Zufallswert (hex, 64 Zeichen) | api | Signatur der Anmelde-Tokens |
opsi_key_public.pem | RSA-Schlüssel (3072 Bit), öffentlicher Teil | api, worker | verschlüsselt das gespeicherte opsi-Passwort |
opsi_key_private.pem | RSA-Schlüssel (3072 Bit), privater Teil | worker | entschlüsselt das opsi-Passwort; nur der Worker spricht mit opsi |
settings_encryption_key.txt | Zufallswert (hex, 64 Zeichen) | worker | AES-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.txt | Zufallswert (hex, 64 Zeichen) | garage | RPC-Secret von Garage |
garage_admin_token.txt | Zufallswert (hex, 64 Zeichen) | garage, garage-init | Token der Garage-Admin-API |
admin_password.txt | 20 Zeichen | api | Passwort des ersten Administrators; wird beim Anlegen einmal angezeigt |
ldap_bind_password.txt | leer; setup-opbweb.sh schreibt das eingegebene Passwort hinein | api | Passwort 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:
| Datei | Folge einer Änderung |
|---|---|
db_password.txt, db_root_password.txt | MariaDB ü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.txt | start.sh erzeugt redis.acl beim nächsten Start aus dem neuen Passwort und startet Redis neu. |
jwt_secret_key.txt | Alle Sitzungen werden ungültig, alle müssen sich neu anmelden. |
opsi_key_private.pem, opsi_key_public.pem | Nur 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.txt | Wird 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.txt | Nicht ändern; sie gehören zum vorhandenen Objektspeicher. |
admin_password.txt | Wirkt nur, solange kein Benutzer existiert. Später ändert der Administrator sein Passwort in der Oberfläche. |
ldap_bind_password.txt | Unkritisch; 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/:
| Vorhanden | nginx liefert aus |
|---|---|
certs/fullchain.pem und certs/key.pem | HTTPS 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 fehlen | nur 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:
| Betrieb | COOKIE_SECURE |
|---|---|
| HTTPS | true |
| nur HTTP | false; bei true speichert der Browser das Cookie nicht, und die Sitzung lässt sich nicht erneuern |
Ports
| Port im Container | Host-Port | Dienst |
|---|---|---|
| 80 | FRONTEND_HTTP_PORT (80) | nginx, HTTP |
| 443 | FRONTEND_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
| Grenze | Wert | Einstellbar |
|---|---|---|
| Upload und Installation/Deinstallation auf dem Depot | 3600 s | OPSI_INSTALL_TIMEOUT_SECONDS |
| Übrige opsi-Aufrufe | 60 s | OPSI_TIMEOUT_SECONDS |
| Laufzeit eines Jobs | 8 h (28800 s) | JOB_TIMEOUT_SECONDS |
| Parallele Jobs im Worker | 10 | nein |
| Dateimanager-Aufrufe API → Worker | 60 s | nein |
| Warten auf ein belegtes Depot | bis 6 h | nein |
| Uploadgröße über nginx | 20 GB | nein (client_max_body_size in frontend/nginx/common.inc) |
| nginx-Timeout zur API | 660 s ohne Datenfluss | nein |
| Download-Links | 2 min | nein |
| Textdateien im Editor | 5 MB (Paketdateien), 2 MB (Dateimanager) | nein |
OPSI_INSTALL_TIMEOUT_SECONDS begrenzt einen einzelnen opsi-Aufruf, JOB_TIMEOUT_SECONDS den ganzen Job – bei einer Installation also alle Depots nacheinander einschließlich der Wartezeit auf belegte Depots (bis 6 h). Setze JOB_TIMEOUT_SECONDS daher deutlich höher als die Wartezeit. Überschreitet ein Job das Limit oder wird der Worker beendet, bricht der Job mit „Abgebrochen: Zeitlimit des Jobs überschritten oder Worker beendet.“ ab und gilt als fehlgeschlagen.
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