Files

13 KiB

IT Pro Partner — Per-Server Disaster Recovery Plan

Author: Sho'Nuff / Network Services Team Date: July 9, 2026 Version: 1.0 Supersedes: hermes-dr-plan-v2.md (Hermes-specific); server-provisioning-standard-v1.md (base install)


DR Architecture Overview

Internet ──► Cloudflare ──► Caddy ──► Service (HTTP/HTTPS)
                          │
                    SSH/WG ──► Management plane (via itpp-infra key)
                          │
                    S3 (Wasabi) ──► Backup plane (all servers)

Shared dependencies:

  • SSH access: itpp-infra key (Hetzner vault or deployed per-server)
  • DNS: Cloudflare (primary) / SiteGround (legacy for itpropartner.com)
  • Backup storage: Wasabi S3 (us-east-1)
  • SMTP relay: mail.germainebrown.com:2525 (MXroute)
  • Auth/SSO: Cloudflare Access (DRE portal)
  • Monitoring: Prometheus node_exporter on each server
  • VPN: WireGuard for management access

Server 1: Core (netcup RS 2000 G12)

Hostname: core IP: 152.53.192.33 Provider: netcup (RS 2000 G12, 8C EPYC 9645, 16GB RAM, 512GB NVMe) OS: Debian 13 Status: 🟢 LIVE — Primary Hermes host

Purpose

Main operations server. Runs Hermes, Docker services, ops portal, WireGuard hub, SMTP relay, local LLM fallback.

Services Running

Service Type Port Notes
Hermes Agent systemd Telegram Primary agent - deepseek-chat via admin-ai
Caddy systemd 80/443 Reverse proxy for all domains
WireGuard (wg0) systemd 51821/udp Tunnel to home router (10.77.0.1)
MySQL tunnel autossh 33060→wphost02:3306 Apex database access
SearXNG Docker 8888 Self-hosted search
DocuSeal Docker 3000 Document signing
Vaultwarden Docker 8080/tailscale Password manager
Ollama systemd 11434 Local LLM fallback (llama3.2:3b)
Ops Portal systemd 8090 FastAPI backend
node_exporter systemd 9100 Prometheus metrics

Docker Containers

  • searxng, docuseal, vaultwarden (compass), + others under /root/docker/

Backup

  • Hermes state: Every 15 min to s3://hermes-vps-backups/live/ (state.db + config)
  • Full Hermes: Daily 5 AM to s3://hermes-vps-backups/hermes-full-backup/
  • Memory snapshots: Every 10 min to s3://hermes-vps-backups/live/memories/
  • Docker volumes: Manual (not automated)

Restore Procedure

# 1. Provision RS 2000 G12 (or better) on netcup
# 2. Install Debian 13, apply base standard (see server-provisioning-standard-v1.md)
# 3. Install Hermes:
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
# 4. Restore from S3 backup:
aws s3 cp s3://hermes-vps-backups/hermes-full-backup/<latest> /root/restore.tar.gz \
  --endpoint-url https://s3.us-east-1.wasabisys.com
tar -xzf /root/restore.tar.gz -C /root/.hermes/
# 5. Restore Docker stacks:
cd /root/docker/searxng && docker compose up -d
cd /root/docker/docuseal && docker compose up -d
cd /root/docker/vaultwarden && docker compose up -d
# 6. Restore Caddy config from S3:
aws s3 cp s3://hermes-vps-backups/live/config/Caddyfile /etc/caddy/ \
  --endpoint-url https://s3.us-east-1.wasabisys.com
# 7. Restart services:
systemctl restart caddy
systemctl restart hermes
# 8. Verify: ops.itpropartner.com, Teleegram, WG tunnel

Failover

  • app1-bu (5.161.114.8) is warm standby. Checks Core every 5 min.
  • If Core unreachable for 2 min → app1-bu syncs S3 state + starts Hermes gateway.
  • Restore Core, then manually fail back.

Server 2: wphost02 (Hetzner CPX21)

Hostname: wphost02 IP: 5.161.62.38 Provider: Hetzner (CPX21, 3C/4G/80GB) OS: Debian 12 (RunCloud managed) Status: 🟡 LIVE — Recently reconnected after SSH firewall fix

Purpose

Apex Predators Track Experience WordPress site. RunCloud-managed. WPForms registration + notification emails.

Services Running

  • nginx-rc (RunCloud) — 80/443
  • MariaDB — 3306
  • Postfix — 25 (relay via mail.germainebrown.com:2525)
  • httpd — 81 (RunCloud internal)
  • RunCloud agent — 34210
  • node_exporter — 9100

Docker Containers

None. RunCloud manages PHP directly.

Backup

  • RunCloud backup: Daily via RunCloud panel
  • MariaDB dumps: Not automated externally
  • WordPress files: Managed by RunCloud

Restore Procedure

# 1. Provision CPX21 (or better) on Hetzner
# 2. Install Debian 12
# 3. Connect to RunCloud via their panel
# 4. RunCloud provisions nginx, MariaDB, PHP
# 5. Restore WordPress from RunCloud backup
# 6. Add itpp-infra SSH key in RunCloud → SSH Access
# 7. Whitelist Core IP (152.53.192.33) in RunCloud firewall
# 8. Restore Postfix relay config:
#    - relayhost = mail.germainebrown.com:2525
#    - SASL auth with email@redacted
# 9. Verify: apextrackexperience.com loads, forms submit

Dependencies

  • Core MySQL tunnel connects here (port 33060→3306)
  • Apex mail watchdog monitors via SSH

Server 3: ai.itpropartner.com (Hetzner CPX41)

Hostname: ai IP: 178.156.167.181 Provider: Hetzner (CPX41, 4C/16G/226GB) OS: Debian 12 Status: 🟡 LIVE — 🔴 92% disk full (18G free)

⚠️ CRITICAL: Disk at 92%. Needs cleanup before migration.

Purpose

Critical infrastructure. Runs LiteLLM proxy that ALL Hermes instances use for model inference (deepseek-chat, claude-opus). Also runs:

  • Open WebUI — AI chat interface
  • Ollama — local LLM inference
  • Qdrant — vector database
  • Caddy — reverse proxy

Services Running

  • LiteLLM — systemd service, port varies (API at admin-ai.itpropartner.com)
  • Docker containers: openwebui, litellm, litellm_postgres, caddy, qdrant, ollama
  • node_exporter — 9100

Backup

  • LiteLLM config: In /root/. hermes/.env and config.yaml (API key: sk-lbh...)
  • Docker volumes: Not backed up to S3
  • Ollama models: Would need re-pull (cache only)

Restore Procedure

# 1. Provision CPX41 (or better) on netcup as part of migration
# 2. Install Debian 13, Docker
# 3. Deploy LiteLLM Docker stack:
#    - From /opt/litellm/docker-compose.yml
#    - Restore postgres data for LiteLLM routes
# 4. Deploy Ollama:
#    - Pull model: ollama pull llama3.2:3b
# 5. Deploy Open WebUI:
#    - From /opt/openwebui/docker-compose.yml
# 6. Deploy Caddy config for admin-ai.itpropartner.com
# 7. Update DNS: admin-ai.itpropartner.com → new IP
# 8. Update Hermes config.yaml on all profiles to point to new IP
# 9. Verify: curl https://admin-ai.itpropartner.com/v1/models
# 10. Decommission old Hetzner server

🔴 Pre-Reboot Checklist

# Before ANY reboot or migration of this server:
# 1. Verify at least ONE alternative model provider works:
curl https://admin-ai.itpropartner.com/v1/chat/completions \
  -H "Authorization: Bearer sk-lbh..." \
  -d '{"model":"deepseek-chat","messages":[{"role":"user","content":"ping"}]}'
# 2. Ensure local Ollama on Core is running:
curl http://127.0.0.1:11434/api/tags
# 3. Notify all Hermes users (Germaine, Anita, Tony)

Dependencies

  • ALL Hermes instances depend on this server's LiteLLM proxy
  • If this goes down, Hermes falls back to local Ollama (llama3.2:3b on Core)
  • Tony's Hermes has no fallback — would be offline

Server 4: unms.forefrontwireless.com (Hetzner CPX21)

Hostname: unms IP: 5.161.225.131 Provider: Hetzner (CPX21, 3C/4G/80GB) OS: Debian 12 Status: 🟢 LIVE — 4d 11h uptime

Purpose

UISP/UNMS (WISP management) + UCRM (customer management). Manages tower routers and customer billing for Forefront Wireless.

Docker Containers (9)

unms-api, unms-device-ws-1, unms-device-ws-2, unms-nginx, unms-rabbitmq, unms-postgres, unms-siridb, unms-fluentd, ucrm

Backup

  • Docker volumes: postgres data, UCRM data
  • UNMS config: Exportable from UNMS UI

Restore

# 1. Provision CPX21 → Reinstall Debian 12 + Docker
# 2. Restore docker-compose stacks from backup
# 3. Restore Postgres volumes
# 4. Update DNS for unms.forefrontwireless.com
# 5. Re-register tower routers in UNMS

Server 5: unifi (Hetzner CPX21)

Hostname: unifi IP: 178.156.131.57 Provider: Hetzner (CPX21, 3C/4G/80GB) OS: Debian 12 Status: 🟢 LIVE — Recently rebuilt (6h uptime)

Purpose

UniFi Network Controller — manages Ubiquiti network equipment.

Services

  • MariaDB
  • UniFi Controller software (native, not Docker)

Backup

  • UniFi backup via controller UI (automatic backups)
  • MariaDB database backup

Restore

# 1. Provision CPX21 → Install UniFi controller
# 2. Restore UniFi backup from last export
# 3. Update DNS for unifi.itpropartner.com
# 4. Adopt APs/switches back

Server 6: hudu.itpropartner.com (Hetzner CPX21)

Hostname: hudu IP: 178.156.130.130 Provider: Hetzner (CPX21, 3C/4G/80GB) OS: Debian 12 Status: 🟢 LIVE

Purpose

Hudu IT documentation platform — internal knowledge base.

Docker Containers (5)

hudu2-app-1, hudu2-worker-1, hudu2-db-1, hudu2-redis-1, letsencrypt

Backup

  • Hudu automatic: Built-in backup to S3-compatible storage
  • Postgres DB: Daily dump

Restore

# 1. Provision CPX21 → Install Docker
# 2. Deploy Hudu Docker stack
# 3. Restore Postgres from backup
# 4. Update DNS

Server 7: fleettracker360 (Hetzner CPX11)

Hostname: fleettrack360 IP: 178.156.149.32 Provider: Hetzner (CPX11, 2C/2G/40GB) OS: Debian 12 Status: 🟢 LIVE

Purpose

Fleet tracking application (BoxPilot Logistics?).

Services

  • Apache2 (80/443)
  • MariaDB (3306)

Backup

  • Apache config + web root
  • MariaDB database dump

Server 8: docker (Hetzner CPX11)

Hostname: docker IP: 178.156.168.35 Provider: Hetzner (CPX11, 2C/2G/40GB) OS: Debian 12 Status: 🟢 LIVE — 🔴 Disk 73% used (9.9G free on 38G)

Purpose

RunCloud staging + utility containers:

  • Nginx Proxy Manager
  • RustDesk server (hbbr, hbbs)
  • Uptime Kuma
  • StrongSwan

Docker Containers (8)

runcloud_php56, runcloud_php81, runcloud_mariadb, nginx-proxy-manager, hbbr, hbbs, strongswan, uptime-kuma


Server 9: app1 / n8n (Hetzner CPX11)

Hostname: n8n IP: 87.99.144.163 Provider: Hetzner (CPX11, 2C/2G/40GB) OS: Debian 12 Status: 🟢 LIVE

Purpose

n8n workflow automation.

Docker Containers (2)

n8n, n8n-postgres


Server 10: tony-vps (Hetzner CPX21)

Hostname: tony IP: 87.99.159.142 Provider: Hetzner (CPX21, 3C/4G/80GB) OS: Debian 12 Status: 🟢 LIVE

Purpose

Tony's standalone Hermes agent. Separate from main infrastructure.

Services

  • llama-server (systemd) — Llama 3.2 1B local fallback
  • hermes-heartbeat.sh (cron — every minute)

Notes

  • Tony's independent instance — not managed from Core
  • Uses admin-ai for primary model, local Llama 1B for fallback
  • No Docker containers

Server 11: app1-bu (Hetzner CPX11 — Warm Standby)

Hostname: app1-bu.itpropartner.com IP: 5.161.114.8 Provider: Hetzner (CPX11, 2C/2G/40GB) OS: Debian 12 Status: 🟢 STANDBY — Warm, gateway dormant

Purpose

Hermes warm standby. Clones Core's state via S3 sync.

Services

  • SSH (22)
  • Tailscale
  • node_exporter (9100)
  • WireGuard (wg0 — tunnel to home router at 10.77.0.3)

Failover Procedure

# Automatic (watchdog on app1-bu):
# 1. Checks Core every 5 min (ping + Hermes health)
# 2. If Core down for 2 min → sync latest S3 state
# 3. Integrity check on state.db (PRAGMA quick_check)
# 4. Start Hermes gateway → Telegram accessible
# 5. Write ACTIVE_OWNER lock to S3

# Manual activation:
ssh -i /root/.ssh/itpp-infra root@5.161.114.8
hermes gateway run --replace
# Or if Core is fenceable:
ssh root@152.53.192.33 "systemctl stop hermes && systemctl mask hermes"

Restore

# 1. Power on via Hetzner API or console
# 2. Ensure S3 sync runs:
#    /root/.hermes/scripts/hermes-standby-sync.sh
# 3. Check integrity:
#    sqlite3 /root/.hermes/state.db "PRAGMA integrity_check;"
# 4. If good → start gateway:
#    hermes gateway run
# 5. If corrupt → restore from snapshot:
#    aws s3 cp s3://hermes-vps-backups/snapshots/<latest> /root/

DR Classification Matrix

Server Tier RTO Target RPO Target Restore Complexity
Core 🔴 Critical 5 min (failover) 15 min Medium (Docker + Hermes)
ai (admin-ai) 🔴 Critical 2 hours 24 hours High (migration)
wphost02 🟡 Important 4 hours 24 hours Low (RunCloud restore)
unms 🟡 Important 4 hours 24 hours Medium (Docker stack)
hudu 🟡 Important 4 hours 24 hours Medium (Docker stack)
unifi 🟡 Important 4 hours 24 hours Low (native install)
n8n 🟢 Standard 8 hours 24 hours Low (2 containers)
docker 🟢 Standard 8 hours 24 hours Medium (8 containers)
fleettracker360 🟢 Standard 8 hours 24 hours Low (LAMP stack)
tony-vps 🟢 Standard Coordinate 24 hours Low (minimal)
app1-bu 🔴 Standby 2 min 15 min Low (S3 sync)

Recovery Bundle Location

Each server's recovery configs are bundled at:

  • /root/.hermes/recovery-bundle-2026-07-05.md (Core — needs refresh)
  • /root/.hermes/references/server-dr-plans.md (this document)
  • /root/.hermes/references/server-provisioning-standard-v1.md (base install)

S3 backup of this document: s3://hermes-vps-backups/live/config/server-dr-plans.md