# 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.yml` liest das Passwort jetzt aus `${MINDFLUX_DB_PASSWORD}` (kein Klartext mehr im Repo). - Der Gitea-Workflow (`.gitea/workflows/mindflux.yml`) reicht das Secret `MINDFLUX_DB_PASSWORD` beim 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): ```powershell -join ((48..57) + (65..90) + (97..122) | Get-Random -Count 32 | ForEach-Object { [char]$_ }) ``` Oder auf dem Server (Linux): ```bash 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 1. Gitea öffnen → das **mindflux-Repository** aufrufen. 2. **Einstellungen** → **Actions** → **Secrets** (derselbe Ort, an dem schon `MINDFLUX_ADMIN_PASSWORD` und `MINDFLUX_ADMIN2_PASSWORD` liegen). 3. **„Neues Secret hinzufügen"**: - **Name:** `MINDFLUX_DB_PASSWORD` (exakt so – der Workflow referenziert diesen Namen) - **Wert:** das neue Passwort aus Schritt 1 4. 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`): ```bash 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 ps` nachsehen. DB-User ist `mindflux`, Datenbank `mindfluxdb` (siehe `docker-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: ```bash 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 ```bash 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_PASSWORD` bzw. eine (nicht eingecheckte) `.env`-Datei gesetzt (`application.properties` importiert 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_network` erreichbar (kein öffentlicher Port) – die Rotation ist trotzdem Pflicht (Defense in Depth).