platform/docs/adr/0006-decoupled-backup-streams.md
Bart Van Geyt 9f819df4d9 Phase 0: architecture docs, ADRs, and repo scaffold
Establish the design foundation for the heleosv2 multi-tenant hosting
platform before any implementation code:

- Monorepo skeleton: docs/, platform-infra/, site-templates/,
  deployments/, control-panel/ with orientation READMEs.
- docs/: roadmap index, architecture + threat model, naming conventions,
  site profiles, provisioning workflow, backup & DR runbook, repo/GitOps
  layout, and the approved architecture plan.
- docs/adr/: 9 ADRs recording the rationale for single-host Compose,
  Traefik edge, nginx+fpm split, shared MariaDB, ZFS-per-customer,
  decoupled backup streams, Forgejo, CLI-first, and SFTP-only.
- Secrets hygiene: .gitignore (only *.enc.* committed) and .gitattributes
  (LF for scripts/Dockerfiles/YAML run on the Linux host).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 12:26:00 +02:00

35 lines
1.7 KiB
Markdown

# ADR 0006 — Decoupled backup streams (files vs DB vs logs)
**Status:** Accepted
## Context
An earlier proposal wrote per-database dumps *into* each customer's ZFS dataset
just before snapshotting, so one snapshot contained files + DB. Problem: the dump
changes every night even for a static site, so every incremental `zfs send`
would ship a fresh dump — defeating the cheap-incremental goal of
[ADR 0005](0005-zfs-per-customer.md). Logs in the dataset cause the same bloat.
## Decision
Back up each data type with the mechanism that fits its change pattern, in
**three decoupled streams**:
1. **Web files** → ZFS snapshot + `zfs send` offsite (truly incremental;
near-zero when unchanged).
2. **Databases****automysqlbackup** produces per-database dumps with
daily/weekly/monthly rotation into `tank/platform/db-backups/<customer>`, then
**rsync** offsite. Per-database dumps preserve per-customer restore
granularity.
3. **Logs** → shipped to **Loki** via Promtail; never stored in the customer
dataset.
## Consequences
- ✅ Unchanged sites cost almost nothing to back up offsite.
- ✅ Each stream is independently tunable (retention, cadence, target).
- ❌ Restoring a customer is a **two-step** operation (files from ZFS, DB from
the dump repo) rather than a single snapshot rollback — documented in the
[DR runbook](../06-backup-and-dr.md).
- ⚠️ The streams are **crash-consistent, not atomically consistent**. Schedule
the nightly DB dump close to the ZFS snapshot; the small window is harmless for
PHP/WordPress (files-on-disk + DB-rows).
- ↔️ Optional future: place `db-backups` on its own dataset and `zfs send` it for
checksummed/immutable offsite instead of rsync.