<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Technical Administration on oPBWeb Manual</title><link>/opbweb/manual/en/technical-admin/</link><description>Recent content in Technical Administration on oPBWeb Manual</description><generator>Hugo</generator><language>en</language><atom:link href="/opbweb/manual/en/technical-admin/index.xml" rel="self" type="application/rss+xml"/><item><title>Architecture</title><link>/opbweb/manual/en/technical-admin/architektur/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/en/technical-admin/architektur/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Audience:&lt;/strong&gt; Technical administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;oPBWeb runs as a single Docker Compose project named &lt;code&gt;opbweb&lt;/code&gt;. The file &lt;code&gt;docker-compose.yml&lt;/code&gt; describes production operation; &lt;code&gt;docker-compose.dev.yml&lt;/code&gt; extends it for development. This chapter shows which services exist, how they are connected and where each kind of data is stored.&lt;/p&gt;
&lt;h2 id="services"&gt;Services&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Service&lt;/th&gt;
 &lt;th&gt;Container&lt;/th&gt;
 &lt;th&gt;Image&lt;/th&gt;
 &lt;th&gt;Purpose&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;serves the web interface and the manual, forwards &lt;code&gt;/api&lt;/code&gt; to the API; the only service with published 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 and WebSocket (FastAPI/uvicorn on port 8000), sign-in, database migrations at startup, first administrator account&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;runs all jobs (arq on Redis); the only service that talks to the opsi config servers and decrypts their passwords&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;all application data (packages, versions, users, jobs, audit log, settings)&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 queue, worker heartbeat, opsi connection status, revocation list of signed-out tokens, depot locks&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-compatible object storage (single node, replication factor 1) for file contents and built packages&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;sets up the layout, the access key &lt;code&gt;opbweb&lt;/code&gt; and the bucket &lt;code&gt;packages&lt;/code&gt; on every start, then exits&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;API and worker use the same image; the worker just starts with a different command (&lt;code&gt;./start-worker.sh&lt;/code&gt;). The garage-init image carries the &lt;code&gt;:dev&lt;/code&gt; tag in production as well.&lt;/p&gt;</description></item><item><title>Configuration</title><link>/opbweb/manual/en/technical-admin/konfiguration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/en/technical-admin/konfiguration/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Audience:&lt;/strong&gt; Technical administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;oPBWeb splits its configuration into three levels:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt; in the project directory: non-secret settings such as ports, LDAP server, time limits. Docker Compose reads the file and inserts the values into &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;secrets/&lt;/code&gt;&lt;/strong&gt;: all passwords and keys as individual files. They reach the containers as Docker secrets and are never stored in &lt;code&gt;.env&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User interface&lt;/strong&gt;: the connections to the opsi config servers (URL, technical user, password, stage, CA certificate; in the &lt;strong&gt;Depots&lt;/strong&gt; view) and the defaults for new packages. These settings are stored in the database, see &lt;a href="/opbweb/manual/en/functional-admin/opsi-server/"&gt;Config servers&lt;/a&gt;
 and &lt;a href="/opbweb/manual/en/functional-admin/einstellungen/"&gt;Settings for new packages&lt;/a&gt;
.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;./setup-opbweb.sh&lt;/code&gt; creates &lt;code&gt;.env&lt;/code&gt; and the missing secrets, see &lt;a href="/opbweb/manual/en/installation/installation/"&gt;Installation&lt;/a&gt;
. Afterwards you can edit &lt;code&gt;.env&lt;/code&gt; directly or run the script again; the existing values are then the defaults. Changes to &lt;code&gt;.env&lt;/code&gt; take effect with the next &lt;code&gt;./start.sh&lt;/code&gt;; Docker Compose then recreates the affected containers.&lt;/p&gt;</description></item><item><title>LDAP Sign-in</title><link>/opbweb/manual/en/technical-admin/ldap/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/en/technical-admin/ldap/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Audience:&lt;/strong&gt; Technical administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;In addition to local accounts, oPBWeb can sign users in against an LDAP directory or Active Directory. The role in oPBWeb is then derived from the group memberships in the directory. You configure the connection with &lt;code&gt;LDAP_*&lt;/code&gt; variables in &lt;code&gt;.env&lt;/code&gt; and the password of the service account in &lt;code&gt;secrets/ldap_bind_password.txt&lt;/code&gt;. There are no settings for this in the user interface.&lt;/p&gt;
&lt;h2 id="how-sign-in-works"&gt;How sign-in works&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;If oPBWeb has a &lt;strong&gt;local&lt;/strong&gt; account with the entered user name, oPBWeb signs in locally only. The directory is not queried, even if the password is wrong.&lt;/li&gt;
&lt;li&gt;Otherwise, with &lt;code&gt;LDAP_ENABLED=true&lt;/code&gt;, oPBWeb connects with the service account (&lt;code&gt;LDAP_BIND_DN&lt;/code&gt;), or anonymously if no bind DN is set.&lt;/li&gt;
&lt;li&gt;oPBWeb searches with &lt;code&gt;LDAP_USER_FILTER&lt;/code&gt; below &lt;code&gt;LDAP_USER_SEARCH_BASE&lt;/code&gt; (empty: &lt;code&gt;LDAP_BASE_DN&lt;/code&gt;). The search must return exactly one entry.&lt;/li&gt;
&lt;li&gt;oPBWeb binds as the user with the DN it found and the entered password, which verifies the password.&lt;/li&gt;
&lt;li&gt;oPBWeb determines the role from the &lt;code&gt;memberOf&lt;/code&gt; attribute (see below). Without a matching group, there is no access.&lt;/li&gt;
&lt;li&gt;On the first successful sign-in, oPBWeb creates the account with the source &lt;strong&gt;Directory (LDAP)&lt;/strong&gt;. Display name (&lt;code&gt;displayName&lt;/code&gt;), email (&lt;code&gt;mail&lt;/code&gt;) and role are taken from the directory again on &lt;strong&gt;every&lt;/strong&gt; sign-in.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Local accounts therefore always stay local, including the first administrator account. This way you can still get into oPBWeb if the directory is down.&lt;/p&gt;</description></item><item><title>Operation and Updates</title><link>/opbweb/manual/en/technical-admin/betrieb/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/en/technical-admin/betrieb/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Audience:&lt;/strong&gt; Technical administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;For day-to-day operation you need two scripts in the project directory: &lt;code&gt;start.sh&lt;/code&gt; and &lt;code&gt;stop.sh&lt;/code&gt;. This chapter also describes where to find logs and service status, how to update oPBWeb and what to keep in mind on the opsi side. Run all commands in the project directory.&lt;/p&gt;
&lt;h2 id="starting-and-stopping-the-stack"&gt;Starting and stopping the stack&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;Effect&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;(none)&lt;/td&gt;
 &lt;td&gt;starts the production stack (&lt;code&gt;docker-compose.yml&lt;/code&gt;) with the existing 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;rebuilds your own images before starting&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;follows the logs of all containers after starting (&lt;code&gt;logs -f --tail=50&lt;/code&gt;); Ctrl+C only ends the output&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;adds &lt;code&gt;docker-compose.dev.yml&lt;/code&gt; (development stack, see below); only in a clone with the sources&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;adds &lt;code&gt;docker-compose.test.yml&lt;/code&gt;: two opsi mocks as config servers Test and Production, see &lt;a href="/opbweb/manual/en/installation/testumgebung/"&gt;Test Environment&lt;/a&gt;
&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--lang de&lt;/code&gt; or &lt;code&gt;--lang en&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;language of the messages for this run (otherwise &lt;code&gt;OPBWEB_LANG&lt;/code&gt; from &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;shows the help&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Sequence: the script aborts if &lt;code&gt;.env&lt;/code&gt; is missing („.env fehlt – bitte ./setup-opbweb.sh ausführen (im Entwickler-Checkout: ./setup-opbweb.sh &amp;ndash;dev).“ – .env is missing, please run ./setup-opbweb.sh, in a developer checkout ./setup-opbweb.sh &amp;ndash;dev), calls &lt;code&gt;scripts/init-secrets.sh&lt;/code&gt;, runs &lt;code&gt;docker compose up -d&lt;/code&gt; and shows the status with &lt;code&gt;docker compose ps&lt;/code&gt;. Running containers whose configuration has not changed are left untouched. &lt;code&gt;start.sh&lt;/code&gt; does not pull new third-party images; for that, see &lt;a href="#aktualisieren"&gt;Updating&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>Backup and Restore</title><link>/opbweb/manual/en/technical-admin/sicherung/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/en/technical-admin/sicherung/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Audience:&lt;/strong&gt; Technical administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;oPBWeb&amp;rsquo;s data lives in two places that belong together: the database holds all metadata, the object storage holds the file contents. The database refers to objects in the storage via SHA-256 checksums and keys (&lt;code&gt;blobs/…&lt;/code&gt;, &lt;code&gt;artifacts/…&lt;/code&gt;). A backup is only usable if both parts come &lt;strong&gt;from the same point in time&lt;/strong&gt; and the &lt;strong&gt;matching secrets&lt;/strong&gt; are included.&lt;/p&gt;
&lt;div class="alert alert-info" role="alert"&gt;&lt;div class="h4 alert-heading" role="heading"&gt;Note&lt;/div&gt;
&lt;p&gt;The commands in this chapter are examples. Backing up the database with &lt;code&gt;mariadb-dump&lt;/code&gt; and backing up the Garage volumes while the stack is stopped is the intended approach; the specific commands for volumes and restore are derived from it. Adapt paths and names to your environment and test the restore before you rely on it.&lt;/p&gt;</description></item><item><title>Troubleshooting</title><link>/opbweb/manual/en/technical-admin/fehlersuche/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/en/technical-admin/fehlersuche/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Audience:&lt;/strong&gt; Technical administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;This chapter sorts typical problems by symptom. For each symptom you find the likely cause and the fix. At the end there is a table of important error messages. Messages of the server follow the interface language; this chapter quotes them as shown in the English interface. Messages of the shell scripts and container logs are German and are quoted with an English translation.&lt;/p&gt;
&lt;h2 id="first-places-to-look"&gt;First places to look&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Source&lt;/th&gt;
 &lt;th&gt;Content&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;System status&lt;/strong&gt; page&lt;/td&gt;
 &lt;td&gt;status of database, Redis, object storage, worker and opsi server, see &lt;a href="/opbweb/manual/en/functional-admin/systemstatus/"&gt;System status&lt;/a&gt;
&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Jobs&lt;/strong&gt; page&lt;/td&gt;
 &lt;td&gt;complete log of every job with error message, see &lt;a href="/opbweb/manual/en/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;which containers are running and which have exited (with 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;startup, migrations, sign-in, 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 connection&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;object storage setup&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Status bar of the user interface&lt;/td&gt;
 &lt;td&gt;&amp;ldquo;Backend not connected&amp;rdquo; if the API does not respond; orange notice for problems with the opsi server&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="stack-does-not-start"&gt;Stack does not start&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Symptom&lt;/th&gt;
 &lt;th&gt;Cause&lt;/th&gt;
 &lt;th&gt;Fix&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; reports „.env fehlt – bitte ./setup-opbweb.sh ausführen (im Entwickler-Checkout: ./setup-opbweb.sh &amp;ndash;dev).“ (.env is missing, run the setup script)&lt;/td&gt;
 &lt;td&gt;no &lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;./setup-opbweb.sh&lt;/code&gt; (or &lt;code&gt;cp .env.example .env&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API does not start, log: &amp;ldquo;Secret file not found: …&amp;rdquo;&lt;/td&gt;
 &lt;td&gt;secret file missing, for example because the stack was started with &lt;code&gt;docker compose&lt;/code&gt; instead of &lt;code&gt;./start.sh&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;use &lt;code&gt;./start.sh&lt;/code&gt; or run &lt;code&gt;./scripts/init-secrets.sh&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API exits after about 60 seconds, log: &amp;ldquo;Database not reachable: …&amp;rdquo;&lt;/td&gt;
 &lt;td&gt;MariaDB not ready, or the password does not match the volume&lt;/td&gt;
 &lt;td&gt;check &lt;code&gt;docker logs opbweb-db&lt;/code&gt;; if &lt;code&gt;db_password.txt&lt;/code&gt; was changed, see &lt;a href="/opbweb/manual/en/technical-admin/konfiguration/"&gt;Configuration&lt;/a&gt;
&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;api, worker and frontend do not start, garage-init has a non-zero exit code&lt;/td&gt;
 &lt;td&gt;object storage setup failed&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-garage-init&lt;/code&gt;; &amp;ldquo;ERROR: No admin token found&amp;rdquo; means &lt;code&gt;secrets/garage_admin_token.txt&lt;/code&gt; is missing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;garage-init keeps reporting &amp;ldquo;Not ready yet, retrying in 2s&amp;hellip;&amp;rdquo;&lt;/td&gt;
 &lt;td&gt;Garage does not start or the admin token does not match&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker logs opbweb-garage&lt;/code&gt;; do not change the token in &lt;code&gt;secrets/&lt;/code&gt; afterwards&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API log: &amp;ldquo;No users and no ADMIN_PASSWORD configured - no initial admin created&amp;rdquo;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;secrets/admin_password.txt&lt;/code&gt; is empty or missing while the user table is empty&lt;/td&gt;
 &lt;td&gt;fill the file or let &lt;code&gt;init-secrets.sh&lt;/code&gt; create it, restart the stack&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="anmeldung"&gt;Sign-in&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;“Wrong user name or password.”&lt;/strong&gt; For local accounts, every failed attempt counts. After 5 failed attempts from the same address the account is locked for that address for 15 minutes: “Account locked until HH:MM.” The user can still sign in from other addresses; the account is locked for everyone only after 50 failed attempts. After 20 failed attempts from one address (across all accounts) oPBWeb answers “Too many failed sign-ins from this address.” An administrator removes the lock under &lt;strong&gt;Users and roles&lt;/strong&gt; with &lt;strong&gt;Unlock&lt;/strong&gt;; &lt;strong&gt;Set password&lt;/strong&gt; also unlocks the account. See &lt;a href="/opbweb/manual/en/functional-admin/benutzer-und-rollen/"&gt;Users and roles&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>Build and Delivery</title><link>/opbweb/manual/en/technical-admin/build-und-auslieferung/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/opbweb/manual/en/technical-admin/build-und-auslieferung/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Audience:&lt;/strong&gt; Technical administration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;oPBWeb consists of three images of its own: backend (for api and worker), frontend (nginx with user interface and manual) and garage-init. You either build them locally with &lt;code&gt;./start.sh --build&lt;/code&gt; or let GitLab CI build them and push them to the project registry. The CI also generates the manual as PDF. This chapter describes the images, the pipeline and how to build the manual locally.&lt;/p&gt;
&lt;h2 id="images"&gt;Images&lt;/h2&gt;
&lt;p&gt;All Dockerfiles use the project directory as build context. Among other things, &lt;code&gt;.dockerignore&lt;/code&gt; keeps &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; as well as the Hugo output and &lt;code&gt;manual/.doc-state/&lt;/code&gt; out of the context.&lt;/p&gt;</description></item></channel></rss>