90 lines
4.5 KiB
Markdown
90 lines
4.5 KiB
Markdown
# 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).
|