Skip to content

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.deFalkenstein přežití ztráty serveru = lokální (rsync --delete)
3 archiv Object Storage hel1 bucket s60backupHelsinky 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), critical naví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.46vyř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)

  1. Obnovitelnost se nikdy netestovala. Dump, který nikdo nezkusil obnovit, není záloha — jen soubor. Chce to periodický restore test do dočasné DB.
  2. 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.
  3. ~~8 prázdných databází ke smazání~~ — Libor rozhodl nechat je být (2026-08-01).
  4. Obojí je práce pro plánovaného agenta backup & monitoringmonitoring-audit-20260731.md §8.

Související