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: "0010"
|
||||
status: open
|
||||
status: in-progress
|
||||
created: 2026-08-01
|
||||
milestone: M1
|
||||
priority: medium
|
||||
@@ -32,3 +32,33 @@ Quelle: [hosts/cfgmon.md](https://git.lab/axion1337.chat/management/-/blob/main/
|
||||
|
||||
---
|
||||
*Übernommen aus dem Backlogs-Markdown beim Framework-Umbau 2026-08-01 (voller Wortlaut: Git-Historie der Datei).*
|
||||
|
||||
## In Arbeit 2026-08-14 — Muster existiert bereits (Aufwand deutlich kleiner als geplant)
|
||||
|
||||
Bei der Bestandsaufnahme für #0030 zeigte sich: **Borg auf Hetzner Storage Box läuft im
|
||||
Matrix-Cluster bereits produktiv** — der für dieses Issue geplante Aufbau muss also nicht
|
||||
erfunden, sondern nur auf Gitea übertragen werden.
|
||||
|
||||
**Vorhandenes Muster (erprobt, nächtlich, verifiziert):**
|
||||
- Storage Box `u641795@u641795.your-storagebox.de:23`, drei getrennte Repos
|
||||
(`/./synapse-backup`, `/./authentik-backup`, `/./wikijs-backup`).
|
||||
- Image `rohana.axion1337.de/sorb/axion-backup:v2`; Retention `borg prune` 7d/4w/6m.
|
||||
- Credentials (Borg-Passphrase + SSH-Key) als SOPS-Secret, per Env in den Job.
|
||||
|
||||
**Konsequenz für Gitea:** kein neuer Storage-Box-Vertrag nötig — ein zusätzliches Repo
|
||||
`/./gitea-backup` auf derselben Box (oder ein Sub-Account) genügt. Der Host braucht weiterhin
|
||||
einen eigenen SSH-Key (CFGMON ist **nicht** der Cluster), dessen Public Key in der Storage Box
|
||||
hinterlegt wird. Wie im Issue vorgesehen: Dump **unkomprimiert** an Borg geben (`gzip` aus
|
||||
`backup/gitea-backup.sh` entfernen), sonst greift die Deduplizierung nicht.
|
||||
|
||||
⚠️ **Unverändert akut:** Der nächtliche Cron auf CFGMON ist seit 2026-07-30 auskommentiert —
|
||||
seit über zwei Wochen läuft **kein** Gitea-Backup, der letzte Stand ist
|
||||
`/opt/backup/gitea-dump-2026-07-30.tar.gz`. Das ist unabhängig von der Borg-Umstellung sofort
|
||||
behebbar (Cron wieder einkommentieren) und sollte **nicht** auf das Off-host-Projekt warten.
|
||||
|
||||
⚠️ **Vorrang laut #0030:** Bevor Backups erweitert werden, muss die kalte Kopie des
|
||||
age-Schlüssels stehen (dort dokumentierte Zirkelabhängigkeit) — sonst wächst nur die Menge
|
||||
potenziell unlesbarer Sicherungen.
|
||||
|
||||
**Offen (nur mit Host-Zugang, kein SSH zu CFGMON von hier):** Cron reaktivieren; SSH-Key auf
|
||||
CFGMON erzeugen + in der Storage Box hinterlegen; `gitea-backup.sh` auf Borg umstellen.
|
||||
|
||||
@@ -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