Cluster-side backups are healthier than assumed: three nightly Borg jobs to a Hetzner Storage Box, all completing with plausible volumes and working prune (synapse 199MB/247 files, authentik ~150MB, wikijs 223kB DB-only). No silent failures. Critical finding for #0030: the Borg passphrase and SSH key needed to READ those backups are SOPS-encrypted under a single age key that exists only in the cluster being backed up and on one laptop — no documented cold copy. Losing both makes all three repos permanently unreadable. Cold escrow must precede any restore drill. For #0010 this shrinks the work: the Storage Box + Borg pattern already exists and is proven, so Gitea needs only its own repo there. The disabled cron (no backups since 2026-07-30) remains separately urgent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c0a428f43d
commit
74f4fa91f0
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: issue
|
||||
id: "0030"
|
||||
status: open
|
||||
status: in-progress
|
||||
created: 2026-08-06
|
||||
milestone: M1
|
||||
priority: medium
|
||||
@@ -42,3 +42,53 @@ Der letzte Punkt ist hier besonders relevant: **Der SOPS-age-Schlüssel entschl
|
||||
Ich kenne den Sicherungsaufbau nur aus deiner Beschreibung und einem Screenshot, nicht aus eigener Anschauung. Der erste Schritt ist deshalb Bestandsaufnahme, nicht Bewertung.
|
||||
|
||||
*Aufgenommen am 2026-08-06 bei einer Bestandsaufnahme der Sicherheitslage.*
|
||||
|
||||
## Schritt 1 erledigt 2026-08-14 — Bestandsaufnahme (Cluster-Seite)
|
||||
|
||||
Wie im Issue gefordert zuerst „das Billigste": in die vorhandenen Sicherungen hineingeschaut,
|
||||
nichts erweitert. Geprüft wurde die **Matrix-Cluster-Seite** (Hetzner/K3s); die Homelab-Seite
|
||||
(GitLab auf Overmind → MinIO/DSM) ist von hier nicht erreichbar und weiterhin ungeprüft.
|
||||
|
||||
**Befund: die Sicherungen selbst sind besser als vermutet.** Drei nächtliche CronJobs, alle
|
||||
`Complete`, keiner suspendiert, alle **off-host** per Borg auf eine Hetzner Storage Box
|
||||
(`u641795@…your-storagebox.de:23`) — also genau das Muster, das #0010 für Gitea erst plant:
|
||||
|
||||
| Job | Zeit | Ziel-Repo | Volumen (letzter Lauf) | Bewertung |
|
||||
|---|---|---|---|---|
|
||||
| `synapse-backup` (matrix) | 03:00 | `/./synapse-backup` | 199,5 MB, 247 Dateien, Dedup-Delta 3,7 MB | plausibel ✅ |
|
||||
| `authentik-backup` (authentik) | 03:15 | `/./authentik-backup` | ~150 MB gesamt, Delta ~15 MB | plausibel ✅ |
|
||||
| `wikijs-backup` (matrix) | 03:30 | `/./wikijs-backup` | 223 kB | plausibel ✅ (nur Postgres; die Wiki-**Inhalte** liegen per git-storage in Gitea/git.lab) |
|
||||
|
||||
Retention greift nachweislich (`borg prune`, 7 daily / 4 weekly / 6 monthly, „Deleted data"
|
||||
in den Logs). Kein stiller Ausfall, keine leeren Archive — die Sicherung ist **keine bloße
|
||||
Vermutung mehr**, zumindest was Existenz und Inhalt angeht.
|
||||
|
||||
### ⚠️ Kritischer Befund: Zirkelabhängigkeit beim age-Schlüssel
|
||||
|
||||
Genau das vom Issue vorhergesagte Muster („der Dump ist da, aber der Schlüssel lag nur auf dem
|
||||
Host, der weg ist") liegt real vor:
|
||||
|
||||
1. Zum **Lesen** der Borg-Repos braucht man Borg-Passphrase **und** SSH-Key.
|
||||
2. Beide liegen in `synapse-backup-secret.yaml` / `authentik-backup-secret.yaml` — **SOPS-verschlüsselt**.
|
||||
3. Entschlüsselbar ist das nur mit **einem einzigen** age-Schlüssel
|
||||
(Empfänger `age14l0hw…`, siehe `.sops.yaml`).
|
||||
4. Dieser private Schlüssel existiert an **genau zwei Orten**, und beide sind „heiß":
|
||||
- `sops-age`-Secret in `flux-system` — **im Cluster, den das Backup schützen soll**
|
||||
- `~/.age/keys.txt` auf sorbs Mac — **ein einzelnes Gerät**
|
||||
|
||||
**Folge:** Gehen Cluster und Mac zusammen verloren (Totalschaden Hetzner + Laptop weg/defekt),
|
||||
sind **alle drei Borg-Repos dauerhaft unlesbar**. Die Sicherungen wären technisch einwandfrei
|
||||
und trotzdem wertlos. Eine Suche über `docs/` und `hosts/` findet **keine** dokumentierte
|
||||
Auslagerung (Escrow, Offline-Kopie, Passwort-Manager) des Schlüssels.
|
||||
|
||||
**Billigste wirksame Gegenmaßnahme (vor jedem Restore-Test):** eine **kalte Kopie** des
|
||||
age-Schlüssels außerhalb von Cluster und Mac anlegen — Passwort-Manager und/oder Ausdruck an
|
||||
sicherem Ort — und die Fundstelle in `hosts/` dokumentieren (nur *wo*, nie der Wert). Erst danach
|
||||
lohnt der eigentliche Restore-Durchlauf, sonst probt man einen Ablauf, dessen Voraussetzung
|
||||
selbst ungesichert ist.
|
||||
|
||||
### Nächste Schritte (unverändert nach Issue-Plan)
|
||||
|
||||
2. Restore-Verfahren schreiben (Reihenfolge, Herkunft von age-Key und kubeconfig).
|
||||
3. Einmal gegen eine Wegwerf-Umgebung durchspielen.
|
||||
4. Ergebnis nach `verfahren/` und Wiederholungsrhythmus festlegen.
|
||||
|
||||
Reference in New Issue
Block a user