4.5 KiB
Anleitung: DB-Passwort rotieren & Gitea-Secret anlegen
Status 2026-07-12: In Produktion abgeschlossen. Das Secret ist angelegt, die DB-Rolle wurde rotiert und Workflow 43 erfolgreich ausgeführt. Diese Anleitung bleibt als Betriebs- und Notfalldokumentation erhalten.
Warum? Das alte Datenbank-Passwort mindflux_pass stand im Klartext in docker-compose.yml – und bleibt über die Git-Historie für immer einsehbar. Es gilt daher als kompromittiert und muss ersetzt werden.
Die Technik ist bereits vorbereitet:
docker-compose.ymlliest das Passwort jetzt aus${MINDFLUX_DB_PASSWORD}(kein Klartext mehr im Repo).- Der Gitea-Workflow (
.gitea/workflows/mindflux.yml) reicht das SecretMINDFLUX_DB_PASSWORDbeim Deploy durch – genau wie die Admin-Passwörter.
Wichtig: Bis das Secret angelegt ist, bricht das nächste Deployment mit der Meldung
MINDFLUX_DB_PASSWORD muss als Secret gesetzt sein ab. So wird kein App-Container mit
einem leeren Datenbank-Passwort gestartet. Die folgenden 5 Schritte dauern ca. 5 Minuten.
Schritt 1: Starkes Passwort erzeugen
PowerShell (Windows):
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 32 | ForEach-Object { [char]$_ })
Oder auf dem Server (Linux):
openssl rand -base64 24
Das Ergebnis kopieren – es wird in Schritt 2 und Schritt 3 gebraucht. Nirgendwo einchecken, nicht in Dateien im Repo speichern.
Schritt 2: Gitea-Secret anlegen
- Gitea öffnen → das mindflux-Repository aufrufen.
- Einstellungen → Actions → Secrets (derselbe Ort, an dem schon
MINDFLUX_ADMIN_PASSWORDundMINDFLUX_ADMIN2_PASSWORDliegen). - „Neues Secret hinzufügen":
- Name:
MINDFLUX_DB_PASSWORD(exakt so – der Workflow referenziert diesen Namen) - Wert: das neue Passwort aus Schritt 1
- Name:
- Speichern.
Schritt 3: Passwort in der Produktions-Datenbank ändern
Der Gitea-Workflow gleicht das Passwort vor jedem Deployment automatisch mit dem Secret ab.
Beim ersten Deployment nach der Rotation führt der Runner das entsprechende ALTER USER aus;
ein separater SSH-Zugang ist deshalb nicht erforderlich.
Der folgende Befehl ist nur noch ein manueller Notfallweg, falls der Runner-Schritt einmal nicht verfügbar sein sollte:
Auf dem Server (dort, wo der Postgres-Container läuft – er heißt im Backend-Netz postgres):
docker exec -it postgres psql -U mindflux -d mindfluxdb -c "ALTER USER mindflux WITH PASSWORD 'HIER_DAS_NEUE_PASSWORT';"
Falls der Container anders heißt: mit
docker psnachsehen. DB-User istmindflux, Datenbankmindfluxdb(siehedocker-compose.yml).Achtung bei Sonderzeichen: Das Passwort steht in einfachen Anführungszeichen im SQL – ein
'im Passwort müsste verdoppelt werden (''). Am einfachsten: Passwort ohne'erzeugen (die Generatoren aus Schritt 1 tun das).
Schritt 4: Deployment auslösen
Einfach einen Push auf main machen (oder den Workflow in Gitea manuell erneut ausführen). Der Deploy-Schritt exportiert das Secret und startet den Container neu:
docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up -d
Zwischen Schritt 3 und dem Neustart gibt es ein kurzes Fenster, in dem der noch laufende alte Container seine bestehenden DB-Verbindungen behält – das ist unkritisch. Sollte die App nach dem Neustart nicht hochkommen, prüfen ob Secret-Wert (Schritt 2) und DB-Passwort (Schritt 3) wirklich identisch sind, dann erneut
docker compose up -d.
Schritt 5: Verifizieren
docker ps # Container "mindflux" muss nach ~40 s "healthy" zeigen (Actuator-Healthcheck)
docker logs mindflux --tail 30 # keine "password authentication failed"-Fehler
Danach im Browser einloggen – wenn Login und Dashboard funktionieren, ist die Rotation abgeschlossen. ✅
Hinweise
- Lokale Entwicklung: lokal wird das Passwort über die Umgebungsvariable
MINDFLUX_DB_PASSWORDbzw. eine (nicht eingecheckte).env-Datei gesetzt (application.propertiesimportiert sie automatisch). Die lokale Datenbank kann ein eigenes, anderes Passwort haben. - Warum die Historie nicht bereinigen? Das alte Passwort ließe sich nur per Force-Push/History-Rewrite aus Git entfernen – aufwendig und riskant. Rotation ist der richtige Weg: Das alte Passwort darf ruhig bekannt sein, wenn es nirgends mehr gilt.
- Die Postgres-Instanz ist nur im internen
backend_networkerreichbar (kein öffentlicher Port) – die Rotation ist trotzdem Pflicht (Defense in Depth).