Handbuch mit Bildern fuer alle Ablaeufe, darunter der Kern- Anwendungsfall und der Deployment-Zugang fuer Claude Code. Betriebsdoku zu Installation, authentik und Reverse Proxy sowie eine Bedrohungsanalyse mit Notfallplan fuer den Fall, dass sshkv selbst kompromittiert wird. Sicherung und Wiederherstellung als Skripte, auf einem Wegwerf-Stapel geprobt. Dabei fielen zwei Fehler auf: das Schema der Warteschlange liess sich nicht zurueckspielen, und ein Abbruch ohne Transaktion loeschte es halb. Jetzt nur Schema public, in einer Transaktion, mit Pruefwert des Master-Keys. Der Worker startet nicht, wenn der Master-Key nicht zur Datenbank passt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
93 lines
4.3 KiB
Markdown
93 lines
4.3 KiB
Markdown
# Sicherung und Wiederherstellung
|
||
|
||
Eine Sicherung von SSHKeyVault besteht aus **zwei Teilen, die getrennt aufbewahrt werden**:
|
||
|
||
| Teil | Inhalt | Wie oft | Wohin |
|
||
|---|---|---|---|
|
||
| **Datenbank** | Hosts, Schlüssel (Private Keys nur verschlüsselt), Zuweisungen, Protokoll, Einstellungen | täglich | normales Backup-Ziel (`/var/backups/sshkv`, von dort auf das Sicherungssystem) |
|
||
| **Master-Key** | 32 Byte, entschlüsselt alle Private Keys | einmalig nach der Installation und nach jeder Master-Key-Rotation | **getrennt:** Passwortmanager, Tresor, verschlüsselter Datenträger |
|
||
| `.env` | `SSHKV_APP_SECRET`, OIDC-Zugang, Datenbankpasswort | nach jeder Änderung | wie der Master-Key |
|
||
|
||
> **Ohne Master-Key ist jedes Datenbank-Backup wertlos** – die Private Keys lassen sich nicht mehr
|
||
> entschlüsseln. **Mit Master-Key neben dem Backup** gibt ein gestohlenes Backup alle Private Keys
|
||
> preis. Deshalb niemals beides am selben Ort.
|
||
>
|
||
> Ohne das richtige `SSHKV_APP_SECRET` gehen TOTP des Notfall-Admins, SMTP-Passwort und
|
||
> Webhook-Geheimnis verloren (neu einrichten genügt); Private Keys hängen nur am Master-Key.
|
||
|
||
## Sichern
|
||
|
||
```bash
|
||
cd /opt/sshkv # Verzeichnis mit docker-compose.yml und .env
|
||
sudo bash deploy/sichern.sh # nach /var/backups/sshkv
|
||
sudo bash deploy/sichern.sh /mnt/sicherung/sshkv
|
||
```
|
||
|
||
Das Skript
|
||
|
||
- schreibt `datenbank-<Stand>.sql.gz` (`pg_dump --clean --if-exists`, nur das Schema `public` – die
|
||
Warteschlange legt der Worker selbst neu an),
|
||
- legt `master-key-pruefwert-<Stand>.txt` daneben: den SHA-256 der Master-Key-Datei. Er verrät nichts
|
||
über den Schlüssel, zeigt beim Zurückspielen aber, ob der richtige bereitliegt,
|
||
- behält die letzten 14 Sicherungen (`SSHKV_SICHERUNGEN_BEHALTEN`),
|
||
- sichert den Master-Key **nicht** mit.
|
||
|
||
Als täglicher Cronjob auf dem Docker-Host:
|
||
|
||
```cron
|
||
15 3 * * * root cd /opt/sshkv && bash deploy/sichern.sh >/var/log/sshkv-sicherung.log 2>&1
|
||
```
|
||
|
||
## Master-Key sichern (einmalig)
|
||
|
||
```bash
|
||
sudo base64 /opt/sshkv/geheim/master.key # Ausgabe in den Passwortmanager, Eintrag „sshkv Master-Key“
|
||
sudo sha256sum /opt/sshkv/geheim/master.key # Prüfwert dazuschreiben
|
||
```
|
||
|
||
Zurück in eine Datei: `echo '<base64>' | base64 -d > geheim/master.key && chmod 400 geheim/master.key`
|
||
und den Eigentümer setzen (Container-Benutzer 1001 oder `SSHKV_WORKER_USER`).
|
||
|
||
## Wiederherstellen
|
||
|
||
```bash
|
||
cd /opt/sshkv
|
||
sudo bash deploy/wiederherstellen.sh /var/backups/sshkv # jüngste Sicherung
|
||
sudo bash deploy/wiederherstellen.sh /var/backups/sshkv 20261012-163958
|
||
```
|
||
|
||
Das Skript
|
||
|
||
1. prüft den Master-Key unter `SSHKV_MASTER_KEY_HOST_FILE` gegen den Prüfwert der Sicherung und
|
||
**bricht ab, wenn er nicht passt**,
|
||
2. fragt nach (`--ja` überspringt),
|
||
3. hält Weboberfläche und Worker an,
|
||
4. spielt die Datenbank **in einer Transaktion** zurück – scheitert etwas, bleibt der alte Stand
|
||
vollständig erhalten,
|
||
5. setzt die Warteschlange zurück und bricht offene Vorgänge ab (ihre Jobs gehören nicht zur
|
||
Sicherung),
|
||
6. startet die Dienste und prüft, dass der Worker den Master-Key akzeptiert.
|
||
|
||
Zusätzlich prüft der **Worker bei jedem Start**, ob er den Deployment-Key mit dem eingebundenen
|
||
Master-Key entschlüsseln kann, und startet sonst nicht („Der Master-Key passt nicht zur Datenbank“).
|
||
|
||
### Geprobt am 12.10.2026
|
||
|
||
Auf einem Wegwerf-Stapel (gleiches `docker-compose.yml`):
|
||
|
||
1. Markierung angelegt (Host `srv-probe`, Protokolleintrag), gesichert.
|
||
2. Markierung gelöscht, weiterer Protokolleintrag geschrieben.
|
||
3. Zurückgespielt → Host wieder da, Protokoll wieder auf dem gesicherten Stand, Hash-Kette
|
||
unversehrt (`protokoll_kette_pruefen()`), Weboberfläche gesund, Worker bereit.
|
||
4. Mit **falschem Master-Key** zurückgespielt → Abbruch vor jeder Änderung.
|
||
|
||
Dabei fielen zwei Fehler auf, die jetzt behoben sind: Das Schema der Warteschlange ließ sich mit
|
||
`--clean` nicht zurückspielen, und ein Abbruch ohne Transaktion hatte es halb gelöscht.
|
||
|
||
## Nach einer Wiederherstellung
|
||
|
||
- **„Jetzt abgleichen“** auf der Übersicht: Der Stand der Hosts kann neuer sein als die Sicherung.
|
||
- Zuweisungen, die nach der Sicherung ausgerollt wurden, kennt sshkv nicht mehr – der Abgleich zeigt
|
||
sie als unbekannte Schlüssel; übernehmen oder entfernen.
|
||
- Wurde nach der Sicherung ein Schlüssel widerrufen, steht er wieder als aktiv da: erneut widerrufen.
|