Zálohy — architektura, provoz, ověřování
Stav k 2026-07-31. Ten den proběhl audit, při kterém se ukázalo, že tři nezávislé cesty selhávaly potichu (viz §6). Všechno níž je změřené, ne převzaté z dřívější dokumentace.
1. Tři vrstvy, tři lokality
| # | Vrstva | Kde | Účel | Retence |
|---|---|---|---|---|
| 1 | lokální | sentinel, /var/backups/ — Norimberk |
okamžité obnovení | PG 14 dní, volumes 7 dní |
| 2 | zrcadlo | Storage Box u560655.your-storagebox.de — Falkenstein |
přežití ztráty serveru | = lokální (rsync --delete) |
| 3 | archiv | Object Storage hel1 bucket s60backup — Helsinky |
přežití katastrofy lokality | denní 30 → týdenní 180 → měsíční 730 dní |
Proč tři a proč Helsinky: vrstva 2 je --delete zrcadlo, takže off-site retence je jen tak dlouhá jako lokální — když disk vynutí krátkou retenci, přijdeš i o historii. Vrstva 3 to odděluje a je navíc v jiné zemi (sentinel NBG, storage box FSN — obojí Německo). Latence hel1 je 23 ms vs 2,6 ms na fsn1, což je pro zálohy nepodstatné (rozhoduje propustnost, ne odezva).
2. Co se zálohuje
PostgreSQL (/usr/local/bin/s60-backup.sh, dump jako s60admin na pg-alfa :5432, --no-owner --no-acl):
s60_auth_{hub,prod,dev}, s60_pulse_{hub,prod,dev}, s60_mail_{hub,prod,dev}, s60_n8n_{hub,prod}, s60_badwolf_{hub,prod,dev}, s60_billit_{hub,prod,dev}, s60_vault_prod, s60_ai_prod, s60_auth, s60_badwolf, bwcs, s60_keycloak, zoe_ledger, glitchtip, fess_context, s60_n8n_staging, s60_cs_kb, s60_kb ← poslední čtyři doplněny 2026-07-31
Docker volumes (deploy/docker-volume-backup.sh): hub + prod, kontejnery se na ~1 s pauznou, tar se stáhne přes rsync do /var/backups/docker-volumes/{hub,prod}/
Konfigurace (deploy/config-backup.sh, týdně): /var/backups/configs/
⚠️ Seznam databází je STATICKÝ
Nová DB se do záloh nedostane sama. Přesně takhle uteklo s60_kb (375 MB, jediný domov znalostní báze) — odhalilo se to jen proto, že se agent kb náhodou zeptal. Pouštěj tuhle kontrolu při každém auditu:
ssh root@100.125.3.121 "sudo -u postgres psql -tAc \"SELECT datname FROM pg_database WHERE NOT datistemplate AND datname NOT IN ('postgres')\"" \
| while read db; do [ -n "$db" ] && { grep -q "^ $db\b" /usr/local/bin/s60-backup.sh || echo "CHYBÍ: $db"; }; done
⚠️ Grep musí být kotvený (^ $db\b). Volná varianta hlásí s60_billit jako pokrytý, protože ho najde uvnitř s60_billit_hub.
Vědomě nezálohované (ověřeno 2026-07-31 — 0 tabulek, 0 řádků, velikost 7574 kB = prázdná DB): s60_billit, s60_n8n, s60_auth_staging, s60_keycloak_test, bazarai, kiwi, s60_badwolf_staging. Plus hive_scrapper (5 tabulek, 0 řádků — ostrá data na Mac Mini). Libor 2026-08-01: NECHAT — nemažou se, jen se o nich ví. Kontrola pokrytí je bude hlásit i nadále, což je očekávané, ne nález.
3. Rozvrh (cron, root@sentinel)
0 4 * * 0 config-backup.sh # týdně
0 4 * * * docker-volume-backup.sh all
30 4 * * * s60-backup.sh # PG dumpy
0 5 * * * s60-storagebox-sync.sh # → Falkenstein
30 5 * * * s60-objectstorage-sync.sh # → Helsinky
Pořadí je záměrné: nejdřív vznikne lokální kopie, pak se zrcadlí, nakonec archivuje.
4. Alerting — zálohy hlásí selhání OKAMŽITĚ
/root/scripts/monitoring/backup-alert.sh "<titulek>" "<detail>" [critical]
- posílá Telegram přes sdílený
notify.py(bot @s60_sentinel_bot od 2026-07-31),criticalnavíc mailem přes Resend - vždy
exit 0— selhání notifikace nesmí shodit volající skript - loguje do
/var/backups/logs/backup-alerts.log
Zapojeno ve všech třech skriptech: PG dumpy (critical), docker volumes (critical), oba synce (critical).
5. Object Storage — provozní detaily
Credentials: /root/secrets/objectstorage/hel1.env (600). Nástroj: rclone (v1.60.1).
Struktura bucketu — vrstva se volí podle data: 1. v měsíci → monthly/YYYY-MM/, pondělí → weekly/YYYY-Www/, jinak daily/YYYY-MM-DD/. Retence maže výhradně ve vlastních prefixech.
⚠️ Hetzner hel1 vrací pod souběhem přechodné HTTP 403 AccessDenied. Není to chyba práv — soubory nakonec dosednou (ověřeno: běh hlásil selhání, přesto bylo nahráno 363 z 379 objektů). Proto --transfers 2 --low-level-retries 20. Nezvyšovat bez testu.
Skript po nahrání ověří počet objektů na druhé straně (rclone ls), nespoléhá na návratový kód. Poučení z téhož dne: „skončilo to zeleně" ≠ „data jsou tam".
6. Co se 2026-07-31 našlo rozbité (a proč to nikdo nevěděl)
| Porucha | Trvání | Proč byla neviditelná |
|---|---|---|
docker-volume-backup.sh posílal na ARGUS=100.110.6.46 — vyřazený stroj |
od 2026-07-16 | selhání se jen zalogovalo jako WARN; archivy zůstávaly v /tmp (mizí při rebootu) a nikdy se nedostaly ani lokálně, ani off-site |
s60-backup.sh posílal alert na relay port 3020 (mrtvý, spojení se nenaváže) |
neznámo | chybu polykal \|\| true |
s60-storagebox-sync.sh nekontroloval návratový kód rsyncu |
neznámo | error code 23 (chybějící /var/backups/configs) se jen vypsal do logu |
s60_kb (375 MB) nebyla v rotaci |
od migrace 2026-04-10 | statický seznam DB; nikdo nekontroloval pokrytí |
Společný jmenovatel: žádná z těch poruch se neuměla ozvat. Proto §4.
7. Obnovení
# PG (lokální kopie)
gunzip -c /var/backups/postgres/<db>_<datum>.sql.gz | psql -h 100.125.3.121 -p 5432 -U s60admin -d <db>
# PG z archivu (Helsinky)
source /root/secrets/objectstorage/hel1.env
export RCLONE_CONFIG_HEL_TYPE=s3 RCLONE_CONFIG_HEL_PROVIDER=Other RCLONE_CONFIG_HEL_REGION=$S3_REGION \
RCLONE_CONFIG_HEL_ENDPOINT=$S3_ENDPOINT RCLONE_CONFIG_HEL_ACCESS_KEY_ID=$S3_ACCESS_KEY \
RCLONE_CONFIG_HEL_SECRET_ACCESS_KEY=$S3_SECRET_KEY
rclone ls hel:s60backup/monthly/ # co je k dispozici
rclone copy hel:s60backup/daily/2026-07-31/postgres/<soubor> /tmp/
# Docker volume
tar -xzf /var/backups/docker-volumes/prod/<archiv>.tar.gz -C /tmp/obnova
8. Otevřené (stav 2026-07-31)
- Obnovitelnost se nikdy netestovala. Dump, který nikdo nezkusil obnovit, není záloha — jen soubor. Chce to periodický restore test do dočasné DB.
- Chybí hlídač „záloha vůbec neproběhla". Alerting §4 zabere jen když skript doběhne a selže. Když cron přestane běžet, ticho vypadá jako úspěch — přesně tenhle režim způsobil poruchy v §6. Řešení: kontrola stáří nejnovější zálohy.
- ~~8 prázdných databází ke smazání~~ — Libor rozhodl nechat je být (2026-08-01).
- Obojí je práce pro plánovaného agenta backup & monitoring →
monitoring-audit-20260731.md§8.
Související
postgres.md— pg-alfa, přístupy, kontrola pokrytímonitoring-audit-20260731.md— audit monitoringu a návrh agenta../services/telegram/INDEX.md— bot pro alerty