# Secrets rotieren Anleitung zum Austausch der Zugangsdaten, die versehentlich in `.env.production.save` im Git gelandet sind. **Grundregel:** Kein Befehl in dieser Anleitung gibt einen Geheimwert auf dem Bildschirm aus. Die neuen Werte werden direkt in die Datei geschrieben. Du siehst sie nie, ich sehe sie nie, und sie landen nicht in der Shell-History (dort steht nur der Befehl, nicht sein Ergebnis). --- ## Vorab: Was passiert mit den Daten? Kurz: **Es geht nichts verloren.** Im Einzelnen: | Was du änderst | Folge für die Daten | Folge für die Nutzer | |---|---|---| | `NEXTAUTH_SECRET` | keine | Alle werden ausgeloggt, Login danach normal möglich | | Datenbank-Passwort | keine | keine | | `SMTP_PASSWORD` | keine | keine | Wichtig zu verstehen: **Die Passwörter der Nutzer hängen nicht am `NEXTAUTH_SECRET`.** Sie liegen als bcrypt-Hashes in der Datenbank und bleiben davon völlig unberührt. `NEXTAUTH_SECRET` signiert nur die Sitzungs-Cookies. Wird es getauscht, sind die ausgestellten Cookies ungültig — jeder muss sich **einmal neu anmelden**, mit dem gewohnten Passwort. Danach ist alles wie vorher. Beim Datenbank-Passwort änderst du nur die *Zugangsdaten*, nicht die Datenbank. Tabellen und Inhalte bleiben unangetastet. --- ## Schritt 0 — Sicherheitsnetz Auf dem Container: ```bash cd /root/My-Weekly-ToDo-List cp .env .env.backup-$(date +%F) chmod 600 .env.backup-* ls -l .env.backup-* ``` Falls etwas schiefgeht, kommst du damit zurück. Die Sicherung liegt außerhalb von Git (`.env*` ist ignoriert) — bitte trotzdem später aufräumen. Zusätzlich ein Datenbank-Backup, bevor du am DB-Zugang drehst: ```bash bash /root/My-Weekly-ToDo-List/scripts/backup-db.sh ``` --- ## Schritt 1 — `NEXTAUTH_SECRET` neu erzeugen Ein Befehl, der den neuen Wert erzeugt und **direkt** in die Datei schreibt: ```bash cd /root/My-Weekly-ToDo-List sed -i "s|^NEXTAUTH_SECRET=.*|NEXTAUTH_SECRET=\"$(openssl rand -base64 32)\"|" .env ``` Kontrolle, ohne den Wert zu zeigen — es wird nur die Länge ausgegeben: ```bash awk -F= '/^NEXTAUTH_SECRET=/{v=substr($0,index($0,"=")+1); gsub(/"/,"",v); print "Länge:", length(v), "Zeichen"}' .env ``` Erwartet: **44 Zeichen** (32 Byte in Base64). Der alte Wert hatte 20 — also deutlich zu kurz. --- ## Schritt 2 — Datenbank-Passwort rotieren Das passiert bei Supabase, nicht auf dem Server: 1. Supabase-Projekt öffnen → **Settings** → **Database** 2. **Reset database password** — neues Passwort erzeugen lassen 3. Passwort in deinen Passwort-Manager, **nicht** in eine Datei kopieren 4. Supabase zeigt dir die fertigen Connection-Strings für `DATABASE_URL` (Pooler, Port 6543) und `DIRECT_URL` (direkt, Port 5432) Auf dem Container einsetzen — dieser Weg zeigt die Eingabe nicht an: ```bash cd /root/My-Weekly-ToDo-List read -rsp "Neue DATABASE_URL einfügen: " V && printf '\n' && \ sed -i "s|^DATABASE_URL=.*|DATABASE_URL=\"$V\"|" .env && unset V read -rsp "Neue DIRECT_URL einfügen: " V && printf '\n' && \ sed -i "s|^DIRECT_URL=.*|DIRECT_URL=\"$V\"|" .env && unset V ``` `read -rs` unterdrückt die Anzeige beim Tippen, `unset` räumt die Variable weg. Verbindung prüfen, ohne Zugangsdaten auszugeben: ```bash npx prisma db execute --stdin <<< "SELECT 1;" && echo "Datenbank erreichbar" ``` --- ## Schritt 3 — SMTP-Passwort rotieren 1. Beim Mail-Anbieter ein neues Passwort setzen (idealerweise ein App-Passwort) 2. Auf dem Container eintragen: ```bash cd /root/My-Weekly-ToDo-List read -rsp "Neues SMTP-Passwort: " V && printf '\n' && \ sed -i "s|^SMTP_PASSWORD=.*|SMTP_PASSWORD=\"$V\"|" .env && unset V ``` --- ## Schritt 4 — Übernehmen ```bash cd /root/My-Weekly-ToDo-List cp .env .next/standalone/.env pm2 restart my-weekly-todo --update-env pm2 save ``` Der Kopierschritt ist nötig, weil der Standalone-Build seine eigene `.env` neben `server.js` liest. Danach: einmal im Browser neu anmelden. Dass du ausgeloggt wurdest, ist der **Beweis**, dass das neue `NEXTAUTH_SECRET` greift. --- ## Schritt 5 — Die Datei aus dem Git entfernen ```bash cd /root/My-Weekly-ToDo-List # oder im Arbeitsrepo git rm --cached .env.production.save rm .env.production.save ``` `.gitignore` ergänzen: ``` .env* !.env.example ``` Committen, pushen, fertig. --- ## Schritt 6 — Historie: umschreiben oder nicht? Nach Schritt 5 ist die Datei aus dem *aktuellen* Stand verschwunden — in der **Historie** steht sie weiterhin. **Meine Empfehlung: Historie so lassen.** Begründung: - Das Repository ist **privat** (geprüft). - Nach den Schritten 1–3 sind die enthaltenen Werte **wertlos**, weil überall ersetzt. - Historie umschreiben ändert jeden Commit-Hash. Alle Klone (dein Rechner, der Container, Gitea) müssten neu geholt werden, alte Tags zeigen ins Leere. Das Risiko übersteigt den Nutzen deutlich. Rotieren schlägt Umschreiben: Ein rotiertes Geheimnis in der Historie ist harmlos, ein nicht rotiertes bleibt auch nach dem Umschreiben in jedem existierenden Klon. Falls du es trotzdem willst — nur bei Bedarf, mit vorherigem Voll-Backup: ```bash git filter-repo --path .env.production.save --invert-paths ``` Danach `git push --force` auf **beide** Remotes, und jeder Klon muss neu erstellt werden. --- ## Kontrolle zum Schluss ```bash cd /root/My-Weekly-ToDo-List git ls-files | grep -E "^\.env" || echo "OK: keine .env-Datei mehr im Git" grep -cE "^(NEXTAUTH_SECRET|DATABASE_URL|DIRECT_URL|SMTP_PASSWORD)=" .env ``` Die zweite Zeile muss `4` ergeben — vier gesetzte Schlüssel, ohne einen davon zu zeigen. Zum Schluss die Sicherungen aufräumen: ```bash shred -u .env.backup-* 2>/dev/null || rm -f .env.backup-* ```