<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Technische Administration on oPBWeb Handbuch</title><link>/opbweb/manual/technical-admin/</link><description>Recent content in Technische Administration on oPBWeb Handbuch</description><generator>Hugo</generator><language>de</language><atom:link href="/opbweb/manual/technical-admin/index.xml" rel="self" type="application/rss+xml"/><item><title>Architektur</title><link>/opbweb/manual/technical-admin/architektur/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/technical-admin/architektur/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Technische Administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="überblick"&gt;Überblick&lt;/h2&gt;
&lt;p&gt;oPBWeb läuft als ein Docker-Compose-Projekt mit dem Namen &lt;code&gt;opbweb&lt;/code&gt;. Die Datei &lt;code&gt;docker-compose.yml&lt;/code&gt; beschreibt den Produktivbetrieb, &lt;code&gt;docker-compose.dev.yml&lt;/code&gt; ergänzt sie für die Entwicklung. Dieses Kapitel zeigt, welche Dienste es gibt, wie sie miteinander verbunden sind und wo welche Daten liegen.&lt;/p&gt;
&lt;h2 id="dienste"&gt;Dienste&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Dienst&lt;/th&gt;
 &lt;th&gt;Container&lt;/th&gt;
 &lt;th&gt;Image&lt;/th&gt;
 &lt;th&gt;Aufgabe&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;frontend&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-frontend&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-frontend:latest&lt;/code&gt; (nginx:stable-alpine)&lt;/td&gt;
 &lt;td&gt;liefert die Weboberfläche und das Handbuch aus, leitet &lt;code&gt;/api&lt;/code&gt; an die API weiter; einziger Dienst mit veröffentlichten Ports&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;api&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-api&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-backend:latest&lt;/code&gt; (python:3.13-slim)&lt;/td&gt;
 &lt;td&gt;REST-API und WebSocket (FastAPI/uvicorn auf Port 8000), Anmeldung, Datenbankmigrationen beim Start, erstes Administrator-Konto&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;worker&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-worker&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-backend:latest&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;führt alle Jobs aus (arq auf Redis); einziger Dienst, der mit den opsi-Configservern spricht und deren Passwörter entschlüsselt&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;db&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-db&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;mariadb:11.4&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;alle Anwendungsdaten (Pakete, Versionen, Benutzer, Jobs, Protokoll, Einstellungen)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;redis&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-redis&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;redis:7-alpine&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Job-Warteschlange, Heartbeat des Workers, Status der opsi-Verbindung, Sperrliste abgemeldeter Tokens, Depot-Sperren&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;garage&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-garage&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;dxflrs/garage:v2.2.0&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;S3-kompatibler Objektspeicher (ein Knoten, Replikationsfaktor 1) für Dateiinhalte und gebaute Pakete&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;garage-init&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-garage-init&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;opbweb-garage-init:1.0.0&lt;/code&gt; (alpine:3.21)&lt;/td&gt;
 &lt;td&gt;richtet bei jedem Start Layout, Zugangsschlüssel &lt;code&gt;opbweb&lt;/code&gt; und Bucket &lt;code&gt;packages&lt;/code&gt; ein und beendet sich dann&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;API und Worker verwenden dasselbe Image; der Worker startet nur mit einem anderen Befehl (&lt;code&gt;./start-worker.sh&lt;/code&gt;). Das Image von garage-init trägt auch im Produktivbetrieb das Tag &lt;code&gt;:dev&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Konfiguration</title><link>/opbweb/manual/technical-admin/konfiguration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/technical-admin/konfiguration/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Technische Administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="überblick"&gt;Überblick&lt;/h2&gt;
&lt;p&gt;oPBWeb trennt die Konfiguration in drei Ebenen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt; im Projektverzeichnis: nicht geheime Einstellungen wie Ports, LDAP-Server, Zeitlimits. Docker Compose liest die Datei und setzt die Werte in &lt;code&gt;docker-compose.yml&lt;/code&gt; ein.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;secrets/&lt;/code&gt;&lt;/strong&gt;: alle Passwörter und Schlüssel als einzelne Dateien. Sie erreichen die Container als Docker-Secrets und werden nie in der &lt;code&gt;.env&lt;/code&gt; abgelegt.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oberfläche&lt;/strong&gt;: die Verbindungen zu den opsi-Configservern (URL, technischer Benutzer, Passwort, Stufe, CA-Zertifikat; in der Ansicht &lt;strong&gt;Depots&lt;/strong&gt;) und die Vorgaben für neue Pakete. Diese Einstellungen liegen in der Datenbank, siehe &lt;a href="/opbweb/manual/functional-admin/opsi-server/"&gt;Configserver&lt;/a&gt;
 und &lt;a href="/opbweb/manual/functional-admin/einstellungen/"&gt;Einstellungen für neue Pakete&lt;/a&gt;
.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Die &lt;code&gt;.env&lt;/code&gt; und die fehlenden Secrets erzeugt &lt;code&gt;./setup-opbweb.sh&lt;/code&gt;, siehe &lt;a href="/opbweb/manual/installation/installation/"&gt;Installation&lt;/a&gt;
. Du kannst die &lt;code&gt;.env&lt;/code&gt; danach direkt bearbeiten oder das Skript erneut aufrufen; die vorhandenen Werte sind dann die Vorgaben. Änderungen an &lt;code&gt;.env&lt;/code&gt; werden mit dem nächsten &lt;code&gt;./start.sh&lt;/code&gt; wirksam; Docker Compose erzeugt dabei die betroffenen Container neu.&lt;/p&gt;</description></item><item><title>LDAP-Anmeldung</title><link>/opbweb/manual/technical-admin/ldap/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/technical-admin/ldap/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Technische Administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="überblick"&gt;Überblick&lt;/h2&gt;
&lt;p&gt;Neben lokalen Konten kann oPBWeb Benutzer gegen ein LDAP-Verzeichnis oder Active Directory anmelden. Die Rolle in oPBWeb ergibt sich dann aus den Gruppenmitgliedschaften im Verzeichnis. Du konfigurierst die Anbindung über &lt;code&gt;LDAP_*&lt;/code&gt;-Variablen in der &lt;code&gt;.env&lt;/code&gt; und das Passwort des Dienstkontos in &lt;code&gt;secrets/ldap_bind_password.txt&lt;/code&gt;. In der Oberfläche gibt es dafür keine Einstellungen.&lt;/p&gt;
&lt;h2 id="so-läuft-die-anmeldung-ab"&gt;So läuft die Anmeldung ab&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Gibt es in oPBWeb ein &lt;strong&gt;lokales&lt;/strong&gt; Konto mit dem eingegebenen Benutzernamen, meldet oPBWeb ausschließlich lokal an. Das Verzeichnis wird nicht gefragt, auch wenn das Passwort falsch ist.&lt;/li&gt;
&lt;li&gt;Sonst, bei &lt;code&gt;LDAP_ENABLED=true&lt;/code&gt;, verbindet sich oPBWeb mit dem Dienstkonto (&lt;code&gt;LDAP_BIND_DN&lt;/code&gt;) oder anonym, wenn kein Bind-DN gesetzt ist.&lt;/li&gt;
&lt;li&gt;oPBWeb sucht mit &lt;code&gt;LDAP_USER_FILTER&lt;/code&gt; unterhalb von &lt;code&gt;LDAP_USER_SEARCH_BASE&lt;/code&gt; (leer: &lt;code&gt;LDAP_BASE_DN&lt;/code&gt;). Die Suche muss genau einen Eintrag liefern.&lt;/li&gt;
&lt;li&gt;Mit dem gefundenen DN und dem eingegebenen Passwort meldet sich oPBWeb als Benutzer an und prüft so das Passwort.&lt;/li&gt;
&lt;li&gt;Aus dem Attribut &lt;code&gt;memberOf&lt;/code&gt; bestimmt oPBWeb die Rolle (siehe unten). Ohne passende Gruppe gibt es keinen Zugang.&lt;/li&gt;
&lt;li&gt;Beim ersten erfolgreichen Login legt oPBWeb das Konto mit der Herkunft „Verzeichnis (LDAP)“ an. Anzeigename (&lt;code&gt;displayName&lt;/code&gt;), E-Mail (&lt;code&gt;mail&lt;/code&gt;) und Rolle werden bei &lt;strong&gt;jeder&lt;/strong&gt; Anmeldung neu aus dem Verzeichnis übernommen.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Lokale Konten bleiben also immer lokal, auch das erste Administrator-Konto. So kommst du auch bei einem Ausfall des Verzeichnisses noch an oPBWeb heran.&lt;/p&gt;</description></item><item><title>Betrieb und Aktualisierung</title><link>/opbweb/manual/technical-admin/betrieb/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/technical-admin/betrieb/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Technische Administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="überblick"&gt;Überblick&lt;/h2&gt;
&lt;p&gt;Für den täglichen Betrieb brauchst du zwei Skripte im Projektverzeichnis: &lt;code&gt;start.sh&lt;/code&gt; und &lt;code&gt;stop.sh&lt;/code&gt;. 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.&lt;/p&gt;
&lt;h2 id="stack-starten-und-stoppen"&gt;Stack starten und stoppen&lt;/h2&gt;
&lt;h3 id="startsh"&gt;start.sh&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./start.sh &lt;span style="color:#f92672"&gt;[&lt;/span&gt;--build&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;--logs&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;--dev | --test&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;--lang de|en&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Option&lt;/th&gt;
 &lt;th&gt;Wirkung&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;(keine)&lt;/td&gt;
 &lt;td&gt;startet den Produktiv-Stack (&lt;code&gt;docker-compose.yml&lt;/code&gt;) mit den vorhandenen Images&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--build&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;baut die eigenen Images vor dem Start neu&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--logs&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;folgt nach dem Start den Logs aller Container (&lt;code&gt;logs -f --tail=50&lt;/code&gt;); Strg+C beendet nur die Anzeige&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--dev&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;nimmt &lt;code&gt;docker-compose.dev.yml&lt;/code&gt; hinzu (Entwicklungs-Stack, siehe unten); nur im Klon mit Quellen&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--test&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;nimmt &lt;code&gt;docker-compose.test.yml&lt;/code&gt; hinzu: zwei opsi-Mocks als Configserver Test und Produktion, siehe &lt;a href="/opbweb/manual/installation/testumgebung/"&gt;Testumgebung&lt;/a&gt;
&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--lang de&lt;/code&gt; bzw. &lt;code&gt;--lang en&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Sprache der Ausgaben für diesen Aufruf (sonst &lt;code&gt;OPBWEB_LANG&lt;/code&gt; aus der &lt;code&gt;.env&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-h&lt;/code&gt;, &lt;code&gt;--help&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;zeigt die Hilfe&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Ablauf: Das Skript bricht ab, wenn &lt;code&gt;.env&lt;/code&gt; fehlt („.env fehlt – bitte ./setup-opbweb.sh ausführen (im Entwickler-Checkout: ./setup-opbweb.sh &amp;ndash;dev).“), ruft &lt;code&gt;scripts/init-secrets.sh&lt;/code&gt; auf, führt &lt;code&gt;docker compose up -d&lt;/code&gt; aus und zeigt mit &lt;code&gt;docker compose ps&lt;/code&gt; den Status. Laufende Container, deren Konfiguration sich nicht geändert hat, bleiben dabei unberührt. &lt;code&gt;start.sh&lt;/code&gt; holt keine neuen Fremd-Images; dafür siehe &lt;a href="#aktualisieren"&gt;Aktualisieren&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>Sicherung und Wiederherstellung</title><link>/opbweb/manual/technical-admin/sicherung/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/technical-admin/sicherung/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Technische Administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="überblick"&gt;Überblick&lt;/h2&gt;
&lt;p&gt;Die Daten von oPBWeb liegen an zwei Stellen, die zusammengehören: In der Datenbank stehen alle Metadaten, im Objektspeicher die Dateiinhalte. Die Datenbank verweist über SHA-256-Prüfsummen und Schlüssel auf Objekte im Speicher (&lt;code&gt;blobs/…&lt;/code&gt;, &lt;code&gt;artifacts/…&lt;/code&gt;). Eine Sicherung ist nur brauchbar, wenn beide Teile &lt;strong&gt;aus demselben Zeitpunkt&lt;/strong&gt; stammen und die &lt;strong&gt;passenden Secrets&lt;/strong&gt; dabei sind.&lt;/p&gt;
&lt;div class="alert alert-info" role="alert"&gt;&lt;div class="h4 alert-heading" role="heading"&gt;Hinweis&lt;/div&gt;
&lt;p&gt;Die Befehle in diesem Kapitel sind Beispiele. Die Datenbank-Sicherung mit &lt;code&gt;mariadb-dump&lt;/code&gt; und das Sichern der Garage-Volumes bei gestopptem Stack sind der vorgesehene Weg; die konkreten Befehle für Volumes und Wiederherstellung sind daraus abgeleitet. Passe Pfade und Namen an deine Umgebung an und teste die Wiederherstellung, bevor du dich darauf verlässt.&lt;/p&gt;</description></item><item><title>Fehlersuche</title><link>/opbweb/manual/technical-admin/fehlersuche/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/technical-admin/fehlersuche/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Technische Administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="überblick"&gt;Überblick&lt;/h2&gt;
&lt;p&gt;Dieses Kapitel ordnet typische Störungen nach Symptom. Zu jedem Symptom findest du die wahrscheinliche Ursache und die Abhilfe. Am Ende steht eine Tabelle mit wichtigen Fehlermeldungen. Die Meldungen des Servers erscheinen in der Sprache der Oberfläche; dieses Kapitel zitiert sie in der deutschen Fassung.&lt;/p&gt;
&lt;h2 id="erste-anlaufstellen"&gt;Erste Anlaufstellen&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Quelle&lt;/th&gt;
 &lt;th&gt;Inhalt&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Seite &lt;strong&gt;Systemstatus&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Zustand von Datenbank, Redis, Objektspeicher, Worker und opsi-Server, siehe &lt;a href="/opbweb/manual/functional-admin/systemstatus/"&gt;Systemstatus&lt;/a&gt;
&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Seite &lt;strong&gt;Jobs&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;vollständiges Protokoll jedes Jobs mit Fehlermeldung, siehe &lt;a href="/opbweb/manual/user-guide/jobs/"&gt;Jobs&lt;/a&gt;
&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;docker compose ps -a&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;welche Container laufen, welche beendet sind (mit Exit-Code)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-api&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Start, Migrationen, Anmeldung, LDAP&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-worker&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Jobs, opsi-Verbindung&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-garage-init&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Einrichtung des Objektspeichers&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Statusleiste der Oberfläche&lt;/td&gt;
 &lt;td&gt;„Backend nicht verbunden“, wenn die API nicht antwortet; orangefarbener Hinweis bei Problemen mit dem opsi-Server&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="stack-startet-nicht"&gt;Stack startet nicht&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Symptom&lt;/th&gt;
 &lt;th&gt;Ursache&lt;/th&gt;
 &lt;th&gt;Abhilfe&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;start.sh&lt;/code&gt; meldet „.env fehlt – bitte ./setup-opbweb.sh ausführen (im Entwickler-Checkout: ./setup-opbweb.sh &amp;ndash;dev).“&lt;/td&gt;
 &lt;td&gt;keine &lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;./setup-opbweb.sh&lt;/code&gt; (oder &lt;code&gt;cp .env.example .env&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API startet nicht, Log: „Secret file not found: …“&lt;/td&gt;
 &lt;td&gt;Secret-Datei fehlt, etwa weil der Stack mit &lt;code&gt;docker compose&lt;/code&gt; statt mit &lt;code&gt;./start.sh&lt;/code&gt; gestartet wurde&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;./start.sh&lt;/code&gt; verwenden oder &lt;code&gt;./scripts/init-secrets.sh&lt;/code&gt; ausführen&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API beendet sich nach etwa 60 Sekunden, Log: „Database not reachable: …“&lt;/td&gt;
 &lt;td&gt;MariaDB nicht bereit oder Passwort passt nicht zum Volume&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-db&lt;/code&gt; prüfen; bei geändertem &lt;code&gt;db_password.txt&lt;/code&gt; siehe &lt;a href="/opbweb/manual/technical-admin/konfiguration/"&gt;Konfiguration&lt;/a&gt;
&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;api, worker und frontend starten nicht, garage-init mit Exit-Code ungleich 0&lt;/td&gt;
 &lt;td&gt;Einrichtung des Objektspeichers fehlgeschlagen&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-garage-init&lt;/code&gt;; „ERROR: No admin token found“ bedeutet fehlendes &lt;code&gt;secrets/garage_admin_token.txt&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;garage-init meldet dauerhaft „Not ready yet, retrying in 2s&amp;hellip;“&lt;/td&gt;
 &lt;td&gt;Garage startet nicht oder das Admin-Token passt nicht&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-garage&lt;/code&gt;; Token in &lt;code&gt;secrets/&lt;/code&gt; nicht nachträglich ändern&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Log der API: „No users and no ADMIN_PASSWORD configured - no initial admin created“&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;secrets/admin_password.txt&lt;/code&gt; leer oder fehlt bei leerer Benutzertabelle&lt;/td&gt;
 &lt;td&gt;Datei füllen bzw. von &lt;code&gt;init-secrets.sh&lt;/code&gt; anlegen lassen, Stack neu starten&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="anmeldung"&gt;Anmeldung&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;„Benutzername oder Passwort falsch.“&lt;/strong&gt; Bei lokalen Konten zählt jeder Fehlversuch. Nach 5 Fehlversuchen von derselben Adresse ist das Konto für diese Adresse 15 Minuten gesperrt: „Konto gesperrt bis HH:MM Uhr.“ Von anderen Adressen kann sich der Benutzer weiter anmelden; für alle gesperrt wird das Konto erst nach 50 Fehlversuchen. Nach 20 Fehlversuchen von einer Adresse (über alle Konten) antwortet oPBWeb mit „Zu viele fehlgeschlagene Anmeldungen von dieser Adresse.“ Ein Administrator hebt die Sperre unter &lt;strong&gt;Benutzer und Rollen&lt;/strong&gt; mit &lt;strong&gt;Sperre aufheben&lt;/strong&gt; auf; auch &lt;strong&gt;Passwort setzen&lt;/strong&gt; entsperrt das Konto. Siehe &lt;a href="/opbweb/manual/functional-admin/benutzer-und-rollen/"&gt;Benutzer und Rollen&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>Build und Auslieferung</title><link>/opbweb/manual/technical-admin/build-und-auslieferung/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/technical-admin/build-und-auslieferung/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Technische Administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="überblick"&gt;Überblick&lt;/h2&gt;
&lt;p&gt;oPBWeb besteht aus drei eigenen Images: Backend (für api und worker), Frontend (nginx mit Oberfläche und Handbuch) und garage-init. Du baust sie entweder lokal mit &lt;code&gt;./start.sh --build&lt;/code&gt; oder lässt sie von der GitLab-CI bauen und in die Projekt-Registry schieben. Die CI erzeugt außerdem das Handbuch als PDF. Dieses Kapitel beschreibt die Images, die Pipeline und wie du das Handbuch lokal baust.&lt;/p&gt;
&lt;h2 id="images"&gt;Images&lt;/h2&gt;
&lt;p&gt;Alle Dockerfiles verwenden das Projektverzeichnis als Build-Kontext. &lt;code&gt;.dockerignore&lt;/code&gt; hält unter anderem &lt;code&gt;secrets/&lt;/code&gt;, &lt;code&gt;certs/&lt;/code&gt;, &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;node_modules/&lt;/code&gt; sowie die Hugo-Ausgaben und &lt;code&gt;manual/.doc-state/&lt;/code&gt; aus dem Kontext heraus.&lt;/p&gt;</description></item></channel></rss>