Diagram zachycuje: EP21 DB Backup Engine jako centrální systém, jeho externí závislosti (PostgreSQL zdroje, Contabo S3, Docker daemon), a aktéry (Cron, Admin/DevOps). První draft — Mermaid flowchart.
flowchart TB
admin(["👤 Admin / DevOps"])
cron(["⏰ Cron"])
subgraph sys ["EP21 DB Backup Engine"]
engine["🐳 Backup Container\n(scheduler, pg_dump, restic)"]
end
brew["🍺 Brew PostgreSQL\n(host)"]
docker_pg["🐳 Docker PostgreSQL\n(kontejnery na hostu)"]
docker_daemon["🐳 Docker Daemon\n(/var/run/docker.sock)"]
contabo["☁️ Contabo S3\n(remote object storage)"]
local_fs["💾 VM Filesystem\nbkup_data/, restic-repo/"]
cron -->|"spouští daily run"| engine
admin -->|"wrapper skripty\n(start, status, logs...)"| engine
engine -->|"pg_dump přes host-gateway"| brew
engine -->|"docker exec pg_dump"| docker_pg
docker_daemon -->|"docker ps / inspect"| engine
engine -->|"restic backup"| contabo
engine -->|"SQL dumpy + snapshoty"| local_fs
Diagram zachycuje: čtyřvrstvou interní architekturu systému (Orchestration → Primary → Secondary → Lifecycle), tokový pohled na data (detect → dump → restic → prune), a vazby na fyzická úložiště (bkup_data, restic-repo, meta, logs). První draft — Mermaid flowchart.
flowchart TD
subgraph orch ["Orchestration Layer"]
sched["scheduler.sh\n(cron entry point)"]
lock["Lock Manager\n(daily.lock)"]
daily["daily.sh"]
end
subgraph primary ["Primary Layer"]
detect["Source Detection\n(Brew PG + Docker PG)"]
dump["pg_dump\n(per DB)"]
naming["Artifact Naming\nSHA256 dedup"]
end
subgraph secondary ["Secondary Layer"]
restic["restic backup\n(encrypted snapshot)"]
posthook["restic post-hook\n(prune remote)"]
end
subgraph lifecycle ["Lifecycle Layer"]
retention["Retention Engine\n(prune local dumps)"]
meta["Metadata Writer\n(run.json, inventory)"]
end
subgraph storage ["Storage"]
bkup["bkup_data/\n(SQL dumpy)"]
repo["restic-repo/\n(šifrované snapshoty)"]
metadir["meta/\n(JSON inventář)"]
logs["logs/"]
s3["☁️ Contabo S3"]
end
sched --> lock --> daily
daily --> detect --> dump --> naming --> bkup
naming --> meta --> metadir
daily --> restic --> repo
restic --> posthook --> s3
daily --> retention --> bkup
daily --> meta
daily --> logs
PostgreSQL databáze na VM prostředí potřebují pravidelné, auditovatelné zálohy s:
EP21 DB Backup Engine nasadí jako Docker kontejner na každý VM. Kontejner:
1. detekuje lokální PostgreSQL zdroje (Brew + Docker containers)
2. provede dump každé databáze s metadaty a checksumem
3. snapshot dumpů uloží do restic repozitáře (lokální nebo remote S3)
4. prune staré lokální dumpy po ověření v restic
| Aktér / Systém | Typ | Role v systému |
|---|---|---|
Cron daemon | Interní (Docker) | Spouští |
Admin / DevOps | Člověk | Instaluje, konfiguruje, monitoruje; spouští ad-hoc příkazy přes wrapper skripty v |
PostgreSQL (Brew) | Externí systém | Lokální databázový zdroj na macOS dev prostředí; detekován přes |
PostgreSQL (Docker) | Externí systém | Kontejnerizovaný databázový zdroj na produkčním VM; detekován přes Docker socket |
Docker runtime | Platforma | Hostuje backup kontejner; poskytuje socket pro source detection Docker kontejnerů |
Restic | Externí nástroj | Sekundární zálohovací vrstva; deduplikace, šifrování, snapshot management a retention |
Contabo S3 | Externí systém | Remote object storage pro terciární kopii restic repozitáře (volitelné) |
Systém je organizován do čtyř explicitně oddělených vrstev. Každá vrstva má vlastní skript, vlastní exit kód a vlastní metadata výstup.
detect → plan → backup → metadata
pg_dump každé DB s SHA256 checksumem a SQL logickým fingerprinterestic snapshot → retention enforce → tag
restic backup adresářů bkup_data, meta, logsep21, db-bkup, <machine_name_uniq>keep_daily=30 / keep_monthly=12 / keep_yearly=7restic_run.json metadataverify restic snapshot → prune local dumps
keep_local z conf/retention.db_bkup.json (nebo env override)local_prune.json metadatalock → layer1 → layer2 → layer3 → unlock
db_exit, restic_exit, prune_exit)overall_exit není maskován — fail v kterékoli vrstvě je viditelný cronuPostgreSQL (Brew/Docker)
│
│ pg_dump
▼
bkup_data/<machine>/<source>/<db>/<YYYY-MM>/
├── <timestamp>.dump ← SQL dump
├── <timestamp>.sha256 ← SHA256 artefaktu
├── <timestamp>.meta.json ← metadata per dump
├── latest.dump ← symlink na poslední dump
└── meta.latest.json ← symlink na poslední meta
│
│ restic backup
▼
restic repository (lokální nebo Contabo S3)
└── snapshot tagged: ep21, db-bkup, <machine_name_uniq>
│
│ po úspěšném restic
▼
prune lokálních dumpů
└── zachovat keep_local=2 (konfigurovatelné)
Metadata tok:
meta/inventory/
├── sources.<timestamp>.json ← detekované zdroje
├── plan.<timestamp>.json ← zálohovací plán
├── run.<timestamp>.json ← výsledek primary vrstvy
├── restic_run.<timestamp>.json ← výsledek secondary vrstvy
└── local_prune.<timestamp>.json← výsledek lifecycle vrstvy
meta/db/<source_id>/<db>/<timestamp>.json ← per-DB metadata
conf/
machine.json ← machine_name_uniq (generováno, persistováno)
retention.db_bkup.json ← local retention policy (keep_local=2)
retention.restic.json ← restic retention policy (30/12/7)
meta/inventory/
run.*.json ← výsledek každého denního běhu
sources.*.json ← detekované zdroje
plan.*.json ← zálohovací plán
restic_run.*.json ← výsledek restic vrstvy
local_prune.*.json ← výsledek prune vrstvy
*.latest.json ← symlinky na poslední verzi
meta/db/<source_id>/<db>/<timestamp>.json
bkup_data/<machine_name_uniq>/db_data/<source_id>/<db>/<YYYY-MM>/
<timestamp>.dump
<timestamp>.sha256
<timestamp>.meta.json
latest.dump
meta.latest.json
logs/
machine/
source/
db/
scheduler/
restic/
Systém běží jako jeden Docker kontejner na každém cílovém VM.
Image: registry.gitlab.com/<org>/ep21-db-bkup:<version>
Povinné volume mounty:
DB_BKUP_ROOT volume → /bkup (data + meta + logs)/restic-repoRESTIC_PASSWORD_FILE → /run/secrets/restic-password/var/run/docker.sock → /var/run/docker.sock (Docker source detection)/etc/localtime → /etc/localtime:ro (timezone)Entrypoint příkazy:
daily | backup | report | retention-report | storage-report | restic-posthook | prune-local | cron-daemon | shell
Cron daemon mode: kontejner startuje s cron-daemon, interní cron spouští daily podle DAILY_CRON env (default: 0 2 * * *).
Docker packaging detail: viz ADR-0007 (Docker packaging) a ADR-0008 (container runtime connectivity).
| Vrstva | Policy soubor | Klíčové parametry | Kde se aplikuje |
|---|---|---|---|
Local dumps |
|
|
|
Restic snapshots |
|
|
|
Remote (Contabo S3) | shodné s restic policy | Kopie restic repozitáře přes |
|
Každý dump má dvě úrovně integrity:
SHA256 artefaktu (artifact.sha256)
SQL Logical Fingerprint (fingerprint.sql_v1)
Change tracking:
run.changed: true/false — zda byl dump v tomto běhu jinýrun.changed_reason — SHA256 / fingerprint / nový_db / první_runOrchestrace (db_bkup_daily.sh) vede separátní exit kódy pro každou vrstvu:
db_exit — výsledek primary vrstvy (dump)restic_exit — výsledek secondary vrstvy (restic snapshot)prune_exit — výsledek lifecycle vrstvy (local prune)overall_exit je bitový OR všech tří — fail v kterékoli vrstvě je viditelný cronu a neblokuje ostatní vrstvy.
Princip: partial success je lepší než žádný backup. Pokud restic selže, local dumpy zůstanou. Pokud prune selže, data nejsou ztracena — jen se nezrušily staré dumpy.
Restic repozitář je šifrován heslem z RESTIC_PASSWORD_FILE (nikdy z env proměnné přímo)
Heslo se nikdy neprintuje do logů — logy obsahují path/status, ne hodnotu
Docker socket mount je privilegovaná operace — kontejner musí běžet s oprávněním číst socket
Dump soubory jsou chráněny oprávněními file systému (pouze root/backup user čte)
Contabo S3 přihlašovací údaje jsou předávány jako env proměnné (RESTIC_AWS_ACCESS_KEY_ID, RESTIC_AWS_SECRET_ACCESS_KEY) — doporučeno použít Docker secrets nebo Vault
Trivy security scan: výsledky a CVE analýza v SECURITY_FINDINGS.md
meta/inventory/run.latest.json — výsledek posledního primary backup běhu
meta/inventory/restic_run.latest.json — výsledek posledního restic snapshotu
meta/inventory/local_prune.latest.json — výsledek posledního prune
logs/scheduler/daily.*.log — kompletní log denního orchestračního běhu
logs/restic/restic.*.log — restic operace (snapshot, forget, check)
Wrapper skript scripts/backup-container-status.sh — rychlý přehled stavu
Wrapper skript scripts/backup-container-report.sh — report detekce a zálohovacího plánu
Každý VM má jedinečný identifikátor machine_name_uniq uložený v conf/machine.json. Identifikátor je:
conf/machine.jsontag: <machine_name_uniq>)bkup_data/<machine_name_uniq>/Roadmap: centrální API pro ověření uniqueness machine ID při bootstrapu VM; při detekci duplicity alert pro SOC.
[Planned] Centrální API pro machine ID uniqueness check (ADR-0010 — deferred sharding placeholder)
[Planned] Alerting integrace — email/Slack/webhook notifikace při selhání backup běhu
[Planned] Restore testing skript — pravidelný automated restore smoke test pro ověření integrity
[Planned] Restic integrity check v cronu — restic check jako scheduled job s reportingem
[Planned] Sharding pro velká prostředí s mnoha VM (ADR-0010 — deferred)
[Omezení] Restore je manuální proces — žádný automated restore workflow neexistuje
[Omezení] Monitoring konzola chybí — status je dostupný jen přes wrapper skripty nebo čtením JSON meta souborů
| ID | Titulek | Accepted ver. | Aktuální ver. | Stav |
|---|---|---|---|---|
ADR-0001 | Metadata-First Backup Inventory | 1.0.0 | 1.1.0 | ✓ Migrováno — draft amendment: cron orchestrace TODO, git metadata backup idea |
ADR-0002 | Source Detection Model — EP21 Backup Agent, Port-Based Discovery, Extensible DB Support | 1.0.0 | 1.1.0 | ✓ Migrováno — draft amendment v1.1.0: port-based detekce, agent model, extensible DB (neschváleno) |
ADR-0003 | Artifact Naming, SHA256 and Symlink Strategy | 1.0.0 | 1.1.0 | ✓ Migrováno — draft amendment: SHA jako Level 1 restore validace, JSON history lifecycle TODO |
ADR-0004 | Partial Run Status — Always-Written Run Metadata | 1.0.0 | 1.0.0 | ✓ Migrováno |
ADR-0005 | Skip Storing Duplicate Dump by SHA (SKIP_IF_SAME_SHA) | 1.0.0 | 1.0.0 | ✓ Migrováno |
ADR-0006 | SQL-Based Logical Fingerprint (fingerprint.sql_v1) | 1.0.0 | 1.0.0 | ✓ Migrováno |
ADR-0007 | Docker Packaging — EP21 VM Backup Engine | 1.0.0 | 1.0.0 | ✓ Migrováno |
ADR-0008 | Container Runtime Connectivity and Ops Wrappers | 1.0.0 | 1.0.2 | ✓ Migrováno — follow-up links na ADR-0011, ADR-0012 |
ADR-0009 | Daily Locking and Stale Lock Recovery | 1.0.0 | 1.0.0 | ✓ Migrováno |
ADR-0010 | Multi-Root Merge, Remote Object Storage, and Sharding Placeholder | 1.0.0 | 1.0.0 | ✓ Migrováno |
ADR-0011 | Docker Discovery Privilege Isolation — Sidecar Model | None | 0.1.0 | Draft — follow-up z ADR-0008, rozhodnutí TBD |
ADR-0012 | VM Hardening Guidelines for Backup Agent | None | 0.1.0 | Draft — follow-up z ADR-0008, rozhodnutí TBD |
| Version | Date | Author | Note |
|---|---|---|---|
| 1.3.0 | 2026-04-10 | claude-sonnet-4-6 | Přidány Mermaid diagramy: system-context.mmd a architecture-overview.mmd (první draft). Diagram sekce aktualizovány ze status=planned na status=ready. |
| 1.2.0 | 2026-04-09 | claude-sonnet-4-6 | Přidány ADR-0011 a ADR-0012 (oba draft) do related_docs a ADR index tabulky. Aktualizována verze ADR-0008 na 1.0.2. |
| 1.1.0 | 2026-04-09 | david.sorf + claude-sonnet-4-6 | Aktualizován ADR index: všech 10 ADR migrováno do design/adr/ JSON formátu. ADR-0001/0002/0003 mají draft amendments (v1.1.0). Přidány related_docs linky na všechny ADR. ADR index tabulka rozšířena o accepted_version, aktuální verzi a stav migrace. |
| 1.0.0 | 2026-04-09 | david.sorf + claude-sonnet-4-6 | Initial version. Migrace obsahu ze SolutionDesign.md do DAK struktury. Rozšířeno o: actors tabulku, data flow diagram, system context, deployment model, machine identity sekci. Diagram placeholdery pro System Context a Architecture Overview (TBD). ADR index ukazuje na existující Markdown ADR v doc/ADR/ — nutno migrovat do design/adr/ JSON formátu. |