9.8 KiB
IT Pro Partner — Disaster Recovery Plan v3 (Consolidated)
Author: Sho'Nuff / Network Services Team, incorporating third-party DR review Date: July 10, 2026 Status: LIVE — replaces v1.0 Supersedes: server-dr-plans.md v1.0, server-provisioning-standard-v1.md, hermes-dr-plan-v2.md
Table of Contents
- Architecture & Shared Dependencies
- Server Standards
- Backup Strategy
- Failover / Failback
- Monitoring & Alerting
- Restore Runbooks
- Testing & Validation
- Security
- Immediate Action Items
- Appendix: Third-Party Review Responses
1. Architecture & Shared Dependencies
Internet -- Cloudflare -- Caddy -- Service (HTTP/HTTPS)
|
+-----------+-----------+
| | |
SSH/WG Tailscale Management
(itpp- (Core <-> VPN (WireGuard
infra) app1-bu) to home router)
| | |
+-----------+-----------+
|
+-----------+-----------+
| |
S3 Primary S3 Secondary
(Wasabi us-east-1) (Wasabi us-west-2
versioning ON or Backblaze B2)
object lock ON object lock ON
Shared Dependencies
| Dependency | Primary | Backup / Fallback | Credentials Location |
|---|---|---|---|
| SSH access | itpp-infra key (Hetzner vault) | Rescue mode / console | ~/.hermes/.env + Hudu |
| DNS | Cloudflare (API token in .env) | Manual via web UI | ~/.hermes/.env |
| S3 backup (primary) | Wasabi us-east-1 | Wasabi us-west-2 (to be created) | ~/.aws/credentials |
| S3 backup (secondary) | Wasabi us-west-2 | Backblaze B2 (evaluate) | TBD |
| SMTP relay | mail.germainebrown.com:2525 | Direct MXroute (port 465/587) | ~/.hermes/.env |
| Auth/SSO | Cloudflare Access | Local portal auth fallback | Cloudflare dashboard |
| Monitoring | Prometheus node_exporter | Uptime Kuma (docker box) | N/A (pull model) |
| VPN management | WireGuard (wg0, port 51821) | Tailscale direct tunnel | /etc/wireguard/ |
2. Server Standards
2.1 Tier Definitions
| Tier | Spec | OS | Use | Cost |
|---|---|---|---|---|
| Standard | RS 4000 G12 (12C/32G/1TB) | Debian 13 | app1, app2, app3 | ~$44/mo |
| Light | RS 2000 G12 (8C/16G/512GB) | Debian 13 | Core | ~$24/mo |
| Standby | CPX21 (4C/8G/80GB) | Debian 13 | app1-bu | ~$14/mo |
| Legacy | Variable Hetzner | Debian 12 | Existing (migrate on rebuild) | ~$8-44/mo |
2.2 Base Install -- Verified Checklist
# S1: hostname + timezone
hostnamectl set-hostname <name>
timedatectl set-timezone America/New_York
# S2: system update
apt update && apt upgrade -y
# S3: security baseline
apt install -y fail2ban ufw
ufw default deny incoming; ufw default allow outgoing
ufw allow ssh; ufw --force enable
# S4: monitoring
apt install -y prometheus-node-exporter
# S5: standard user + key
adduser ippadmin && usermod -aG sudo ippadmin
echo "ssh-ed25519 AAA... itpp-infra" >> /home/ippadmin/.ssh/authorized_keys
# S6: harden SSH
sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^PermitRootLogin yes/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
systemctl restart sshd
# S7: Docker (if needed)
curl -fsSL https://get.docker.com | bash
apt install -y docker-compose-plugin
2.3 Application Data Paths
Every server must document:
- What data lives where (volumes, bind mounts, databases, uploads, .env files)
- What can be rebuilt vs what must be restored
- Secrets location
- Caddy/nginx configs
- Cron jobs
- External API dependencies
3. Backup Strategy
3.1 Backup Matrix
| Data Type | Frequency | Target | Retention | Status |
|---|---|---|---|---|
| Hermes state | Every 15 min | S3 primary (live/) | 48 hours | ✅ LIVE |
| Hermes full | Daily 5 AM | S3 primary (full/) | 90 days | ✅ LIVE |
| Memory snapshots | Every 10 min | S3 primary (memories/) | 48 hours | ✅ LIVE |
| Memory history | Every 10 min | S3 primary (memories/history/) | 90 days | ✅ LIVE |
| Router configs | Daily 6 AM | S3 primary (mikrotik/) | 90 days | ✅ LIVE |
| System configs | Daily | S3 primary (/) | 90 days | 🔲 NOT AUTOMATED |
| Docker volumes | Daily | S3 primary (/) | 90 days | ❌ NOT DONE |
| Database dumps | Every 6 hours | S3 primary (/) | 90 days | ❌ NOT DONE |
| Application data | Per-app | S3 primary (/) | 90 days | 🔲 PARTIAL |
| S3 secondary | Daily sync | Wasabi us-west-2 | 90 days | ❌ NOT SET UP |
3.2 Backup Security
- Versioning: ON (all 3 buckets)
- Object Lock: NOT enabled
- Delete protection: NOT configured
- Backup credentials: Admin-level (can delete) -- NOT write-only
- Encryption: Server-side only (Wasabi default)
4. Failover / Failback
4.1 Warm Standby Timing (Corrected)
Old: Check every 5 min, failover after 2 min unreachable (impossible -- can't detect 2-min outage at 5-min intervals)
New: Check every 30 seconds, failover after 4 failed checks (~2 min detection) + 45-90s sync = ~3-3.5 min actual, 5 min committed RTO
4.2 Health Check -- Two Layers
Layer 1 (Ping): ICMP to Core (152.53.192.33) every 30s Layer 2 (HTTP): GET /healthz on Tailscale IP -- checks Gateway heartbeat, SQLite PRAGMA, local Ollama
4.3 Split-Brain Prevention
S3 active-lock.json mechanism:
{"active_node": "core", "heartbeat": "<timestamp>", "lock_holder": "core"}
Core writes heartbeat every 30s while healthy. Failover only proceeds after:
- Core unreachable for 4 consecutive checks (app1-bu local)
- External monitor independently confirms Core down
- active-lock.json heartbeat stale (>90s)
- app1-bu writes itself as lock_holder
- Gateway starts
- Operator alerted
If Core can be reached for fencing, app1-bu SSHes in and stops/masks Hermes before taking over.
4.4 Failback Protocol
No auto-failback. Sequence:
- Confirm app1-bu is active node
- Keep Core stopped -- no auto-start
- Restore Core OS + stack
- Sync latest state from app1-bu/S3 into Core
- Validate sync timestamp
- Start Core in passive mode
- Stop app1-bu gateway
- Update active-lock.json: "active_node": "core"
- Start Core gateway
- 5 consecutive health checks pass
- Release standby lock
- Monitor 30 min before closing
Rollback: If Core fails health checks mid-failback, revert immediately -- restore app1-bu as active, keep Core in maintenance.
4.5 Provider/Account Outage
If entire netcup account is unavailable:
- app1-bu (Hetzner) takes over
- DNS records pointed to app1-bu IP
- No auto-failback -- human decision
5. Per-Server RTO/RPO Targets
| System | RTO | RPO | Notes |
|---|---|---|---|
| Core (Hermes) | 5 min | 15 min | Via warm standby (app1-bu) |
| app1-bu (standby) | N/A | <=15 min | Recovery path for Core |
| app1/2/3 (Standard tier) | 60 min | 24h | Rebuild from S3 + docker compose |
| wphost02 (WordPress) | 2h | 24h | DB restore from dump |
| fleettracker360 | 2h | 24h | DB restore from dump |
| Legacy Hetzner hosts | 4h | 24h | Via rescue mode or S3 |
6. Immediate Action Items
P0 -- This Week
| # | Action | Details |
|---|---|---|
| 1 | Clean AI server disk | 92% full -- purge old Docker images/logs |
| 2 | Create S3 write-only IAM user | PutObject only, no delete/list |
| 3 | Enable S3 Object Lock | 7-day minimum retention |
| 4 | Deploy Docker volume backup | All Docker hosts |
| 5 | Deploy DB dump cron | wphost02 + fleettracker360 (MariaDB) |
| 6 | Deploy 30s watchdog | Currently documented, need deployment |
P1 -- Next 2 Weeks
| # | Action |
|---|---|
| 7 | Document Tony's Hermes config + backup to S3 |
| 8 | Provision secondary S3 bucket (Wasabi us-west-2) |
| 9 | Extend snapshot retention from 48h to 30 days |
| 10 | Add backup success/failure monitoring to ops portal |
P2 -- Next 30 Days
| # | Action |
|---|---|
| 11 | Full DR simulation for Core failover |
| 12 | Monthly restore testing schedule begins |
| 13 | Deploy Prometheus + Grafana stack |
| 14 | Add disk threshold alerts for all servers |
| 15 | Begin netcup migration |
7. Restore Runbooks (Summary)
Full per-server restore runbooks with exact commands are in the Per-Server Runbooks document (companion doc 3 of the v3 DR stack). Each covers:
- Purpose + dependencies
- DNS records, firewall ports, backup path
- Required secrets
- Step-by-step restore commands
- DB restore with pre-import dump verification
- Docker volume restore
- Health checks
- Known failure modes
Hosts covered: Core, app1-bu, app1/2/3, wphost02, fleettracker360, Legacy Hetzner hosts.
8. Third-Party Review Responses
Reviewer 1 Findings -- Addressed
| Finding | Addressed In |
|---|---|
| Failover timing mismatch (5min check did not equal 2min RTO) | Section 4.1 -- Corrected to 30s checks |
| Backup compliance gap (standard says daily but not happening) | Section 3.1 -- Gap closure plan |
| AI server 92% disk critical | Section 6 -- P0 action item #1 |
| Memory consolidation data loss risk | Separate docs per priority-tagging proposal |
| Tony's Hermes undocumented | Section 6 -- P1 action item #7 |
Reviewer 2 Findings -- Addressed
| Finding | Addressed In |
|---|---|
| S3 single point of failure | Section 1 + Section 3.1 -- Two-region plan |
| Backup frequency vs RPO mismatch | Section 5 -- RPO per data type |
| Restore procedures not detailed | Section 7 -- Full runbooks reference |
| Failback under-defined | Section 4.4 -- Protocol |
| No backup restore testing | Separate testing schedule doc |
| Retention too short (48h snapshots) | Section 6 -- P1 action item #9 |
| Backup security not described | Section 3.2 |
| Application backup details vague | Section 2.3 |
| Secrets recovery not documented | Section 1 (shared deps table) |
| Provider/account outage missing | Section 4.5 |
This plan is ACTIVE. Review quarterly or after any infrastructure change.