[CRITICAL] Database Backup Strategy: CloudNativePG vs Hetzner Postgres #6

Closed
opened 2026-05-14 21:41:57 +00:00 by sorb · 3 comments
Owner

Decide on backup strategy and implement daily automated backups with monthly restore testing. Est. Time: 2-3 days

Decide on backup strategy and implement daily automated backups with monthly restore testing. Est. Time: 2-3 days
sorb added this to the aXion1337 Roadmap project 2026-05-14 21:48:02 +00:00
sorb added the priority:critical label 2026-05-14 21:48:52 +00:00
sorb moved this to backlog in aXion1337 Roadmap on 2026-05-14 21:55:28 +00:00
sorb added the area:database label 2026-05-14 21:57:57 +00:00
Author
Owner

Gekoppelt mit #15 - beide teilen sich dieselbe Loesung (Hetzner Storage Box BX11, 1TB, ~3.81 EUR/Monat, gebucht 2026-07-28), daher hier gemeinsam betrachtet statt getrennt.

Reality-Check (live gemessen, 2026-07-28):

  • Synapse DB: 36 MB
  • MAS DB: 18 MB
  • Synapse media_store: 121 MB
  • Authentik DB: nicht gemessen, aber bei 7 Nutzern ebenfalls im MB-Bereich

Zusammen aktuell deutlich unter 500 MB - die "kann ueber 100GB wachsen"-Sorge aus #15 ist eine Zukunftsfrage, keine aktuelle Realitaet. BX11 (1TB) ist damit grosszuegiges Headroom fuer Jahre Wachstum + viele aufbewahrte Snapshots, keine groessere Box noetig.

Synergie: Ein gemeinsamer K8s CronJob statt zwei getrennter Backup-Pfade:

  • pg_dump je DB (synapse, mas, authentik) -> Datei
  • Synapse media_store direkt
  • Beides in ein Repository auf der BX11

Tool-Empfehlung: Borg mit dediziertem, auf Borg+Append-Only beschraenktem SSH-Key (Hetzner Storage Box Feature - Angreifer/kompromittierter Server kann dann nur anhaengen, nicht alte Backups loeschen/ueberschreiben). Alternative: restic (einfacher, natives SFTP, aber ohne dieses Append-Only-Schutzfeature).

SSH-Key: dedizierter neuer Key (id_hetzner_storagebox_backup), nicht der persoenliche Server-Key - minimaler Blast-Radius falls kompromittiert.

Umsetzung noch offen (Tool-Entscheidung Borg vs. restic, CronJob-Manifest, Restore-Test).

**Gekoppelt mit #15** - beide teilen sich dieselbe Loesung (Hetzner Storage Box BX11, 1TB, ~3.81 EUR/Monat, gebucht 2026-07-28), daher hier gemeinsam betrachtet statt getrennt. **Reality-Check (live gemessen, 2026-07-28):** - Synapse DB: 36 MB - MAS DB: 18 MB - Synapse media_store: 121 MB - Authentik DB: nicht gemessen, aber bei 7 Nutzern ebenfalls im MB-Bereich Zusammen aktuell deutlich unter 500 MB - die "kann ueber 100GB wachsen"-Sorge aus #15 ist eine Zukunftsfrage, keine aktuelle Realitaet. BX11 (1TB) ist damit grosszuegiges Headroom fuer Jahre Wachstum + viele aufbewahrte Snapshots, keine groessere Box noetig. **Synergie:** Ein gemeinsamer K8s CronJob statt zwei getrennter Backup-Pfade: - pg_dump je DB (synapse, mas, authentik) -> Datei - Synapse media_store direkt - Beides in ein Repository auf der BX11 **Tool-Empfehlung:** Borg mit dediziertem, auf Borg+Append-Only beschraenktem SSH-Key (Hetzner Storage Box Feature - Angreifer/kompromittierter Server kann dann nur anhaengen, nicht alte Backups loeschen/ueberschreiben). Alternative: restic (einfacher, natives SFTP, aber ohne dieses Append-Only-Schutzfeature). SSH-Key: dedizierter neuer Key (`id_hetzner_storagebox_backup`), nicht der persoenliche Server-Key - minimaler Blast-Radius falls kompromittiert. Umsetzung noch offen (Tool-Entscheidung Borg vs. restic, CronJob-Manifest, Restore-Test).
Author
Owner

Umgesetzt in f5e9fc5 + bccd265. Zwei CronJobs (synapse-backup in matrix, authentik-backup in authentik), Borg-Backups zur gebuchten Hetzner Storage Box BX11 (u641795.your-storagebox.de:23), je eigenes Repo + Passphrase. Retention: 7 daily / 4 weekly / 6 monthly. Details siehe Commit-Messages.

Bug unterwegs gefunden + gefixt: pg_dump bekam beim Job-Start sofort "Connection refused" - der NetworkPolicy-Controller braucht ein paar Sekunden, um die IP eines brandneuen Pods in die erlaubten Ingress-Regeln des Postgres-Ziels einzutragen. backup.sh wartet jetzt per pg_isready-Retry (bis zu 30s), bevor es dumpt (bccd265).

Vollstaendig live verifiziert:

  • Beide CronJobs manuell ausgeloest, beide erfolgreich (borg create + borg prune liefen durch)
  • Echter Restore-Test: Archiv aus beiden Repos extrahiert - Synapse-DB-Dump (807 TOC-Eintraege), MAS-DB-Dump (256 TOC-Eintraege) und alle media_store-Dateien (Original-Timestamps erhalten) intakt und wiederherstellbar
  • Keine Downtime, keine Aenderung an den laufenden Synapse/MAS-Pods (nur Lesezugriff)

Gebucht/eingerichtet vom User: BX11 (1TB, ~3.81EUR/Monat), dedizierter SSH-Key (nicht der persoenliche Server-Key), Hetzners eigener monatlicher Storage-Box-Snapshot bleibt zusaetzlich aktiv (Schutz der Borg-Repos selbst, komplementaer zur Retention).

Gekoppelt mit #15 (media_store), siehe dortiger Kommentar.

Umgesetzt in f5e9fc5 + bccd265. Zwei CronJobs (`synapse-backup` in `matrix`, `authentik-backup` in `authentik`), Borg-Backups zur gebuchten Hetzner Storage Box BX11 (`u641795.your-storagebox.de:23`), je eigenes Repo + Passphrase. Retention: 7 daily / 4 weekly / 6 monthly. Details siehe Commit-Messages. **Bug unterwegs gefunden + gefixt:** `pg_dump` bekam beim Job-Start sofort "Connection refused" - der NetworkPolicy-Controller braucht ein paar Sekunden, um die IP eines brandneuen Pods in die erlaubten Ingress-Regeln des Postgres-Ziels einzutragen. `backup.sh` wartet jetzt per `pg_isready`-Retry (bis zu 30s), bevor es dumpt (bccd265). **Vollstaendig live verifiziert:** - Beide CronJobs manuell ausgeloest, beide erfolgreich (`borg create` + `borg prune` liefen durch) - **Echter Restore-Test**: Archiv aus beiden Repos extrahiert - Synapse-DB-Dump (807 TOC-Eintraege), MAS-DB-Dump (256 TOC-Eintraege) und alle media_store-Dateien (Original-Timestamps erhalten) intakt und wiederherstellbar - Keine Downtime, keine Aenderung an den laufenden Synapse/MAS-Pods (nur Lesezugriff) Gebucht/eingerichtet vom User: BX11 (1TB, ~3.81EUR/Monat), dedizierter SSH-Key (nicht der persoenliche Server-Key), Hetzners eigener monatlicher Storage-Box-Snapshot bleibt zusaetzlich aktiv (Schutz der Borg-Repos selbst, komplementaer zur Retention). Gekoppelt mit #15 (media_store), siehe dortiger Kommentar.
sorb closed this issue 2026-07-28 18:42:44 +00:00
Author
Owner

Migriert nach git.lab: axion1337.chat/axion1337.chat-gitops#6 (nur im Lab bzw. via VPN erreichbar — das Lab ist seit 2026-08-01 die Quelle der Wahrheit, siehe gitops#48). Weiterarbeit dort; dieses Gitea-Issue bleibt als Verweis stehen.

**Migriert nach git.lab**: [axion1337.chat/axion1337.chat-gitops#6](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/6) (nur im Lab bzw. via VPN erreichbar — das Lab ist seit 2026-08-01 die Quelle der Wahrheit, siehe gitops#48). Weiterarbeit dort; dieses Gitea-Issue bleibt als Verweis stehen.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sorb/axion1337.chat-gitops#6