# Two-Bucket DR Backup Strategy ## Architecture ### Layer 1: Provider-Level (automated snapshots) | Asset | Backup Method | Retention | Coverage | |---|---|---|---| | **Hetzner Cloud VPS** | Hetzner snapshot (API/CLI) | Keep latest + 7-day auto | Full OS recovery | | **Hetzner dedicated** | Robot backup service | 7 days | Full system | | **RunCloud servers** | RunCloud built-in backup | Their retention | Web apps, WordPress, databases | | **CCR routers** | RouterOS API export → S3 (daily) | 365 days per lifecycle rule | Config + logs only | These protect against OS corruption, accidental config wipe, bad update — NOT data loss. ### Layer 2: Application-Level (S3 — two-bucket DR) | Asset | Primary Bucket | DR Bucket | Frequency | |---|---|---|---| | **Hermes** (config, sessions, skills) | `hermes-vps-backups` (us-east-1) | `hermes-vps-backups-dr` (us-west-2) | Daily | | **Portal** (DB, uploads, configs) | `itpropartner-backups` (us-east-1) | `itpropartner-backups-dr` (us-west-2) | Daily | | **CCR router configs** | `mikrotik-ccr-backups` (us-east-1) | `mikrotik-ccr-backups-dr` (us-west-2) | Daily | ### Layer 3: Hudu (source of truth) Hudu has its own backup export in Admin settings. Export to Wasabi bucket periodically. Hudu is the canonical record for passwords, configs, network diagrams, and procedures. ## Two-Bucket Pattern 1. **Primary bucket** — versioning ON, 365-day lifecycle for router configs, 90-day for Hermes/portal 2. **DR bucket** (different Wasabi region) — Cross-Region Replication from primary, Object Lock (7 day immutable) 3. **Same provider** (Wasabi), different regions — two providers is overkill for MSPs 4. **Cost:** ~$5-8/mo per bucket for small MSP portal + config backups ### Retention policy (from user decisions) - **Router configs**: 365 days (1 year). Versioning ON. Lifecycle: expire current versions after 365 days, expire delete markers after 30 days. - Config files are small (~15-20KB each) — 365 exports per router = ~5-7MB/year. Storage cost at Wasabi is essentially zero. - **Hermes backups**: 90 days primary, 90 days DR (Object Lock 7-day immutability). - **Portal backups**: 90 days primary, 90 days DR (Object Lock 7-day immutability). - **Hetzner snapshots**: Keep latest weekly, auto-delete older than 7 days. - Provider snapshots are NOT a substitute for application S3 backups — they restore the OS, not the data. ### Bucket naming convention ``` {service}-backups # Primary (us-east-1) {service}-backups-dr # DR (us-west-2) ``` ### Wasabi-specific notes - Wasabi is 100% AWS S3 API compatible — standard `aws s3` / `boto3` commands with `--endpoint-url` - Must specify `--endpoint-url https://s3..wasabisys.com` for every call - Credentials in `~/.aws/credentials` in standard format - Bucket names are globally unique — handle `BucketAlreadyExists` gracefully ## Key practices - **Versioning ON** on all primary buckets (accidental deletion = recoverable) - Verified working: `aws s3api put-bucket-versioning --bucket name --versioning-configuration Status=Enabled --endpoint-url ...` - **Object Lock** on DR buckets (7 day immutability — ransomware can't touch them) - **Lifecycle**: 30-90 day retention on primary, 90 days on DR, then delete or glacier - **Restore drill**: Periodically test that a backup download + extract + restore actually works - **Staging directory**: Use disk-backed path (e.g. `/root/.hermes/.backups/`), NOT `/tmp` (tmpfs fills up) ## Hermes backup fixes (from experience) - `/tmp` is tmpfs (RAM-backed, ~1GB). Hermes state.db + profiles easily exceeds it. - Always verify with `df -h /tmp` if you see "No space left on device" but `df -h /` shows free space. - Fix: `BACKUP_DIR` and `ARCHIVE` both go to `~/.hermes/.backups/` on root disk. - Also check Python scripts' `config.yaml temp_dir` — they may independently write to `/tmp`.