#!/usr/bin/env python3 """Send DR plan + consolidation proposal email to Germaine.""" import smtplib, random, importlib.util from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders SMTP = "mail.germainebrown.com" PORT = 2525 PASS = "Catches.bullets1985" FROM = "shonuff@germainebrown.com" TO = "g@germainebrown.com" def load_list(path, attr="ITEMS"): spec = importlib.util.spec_from_file_location("mod", path) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return getattr(mod, attr, []) CLOSINGS = load_list("/root/.hermes/references/shonuff-closings.py", "SHONUFF_CLOSINGS") TITLES = load_list("/root/.hermes/references/shonuff-titles.py", "SHONUFF_TITLES") # Create message msg = MIMEMultipart("mixed") msg["From"] = FROM msg["To"] = TO msg["Bcc"] = TO msg["Subject"] = "DR Plans + Consolidation Proposal — Full & Redacted" # Full version text part full_body = """\

DR Plans + Memory Consolidation Proposal


What's Attached

1. Per-Server DR Plans (full)
Covers all 11 servers: Core, ai (admin-ai), wphost02, unms, unifi, hudu, fleettracker360, docker box, n8n, tony-vps, app1-bu (standby). Each with services, backup strategy, restore procedure, and dependency map.

2. Per-Server DR Plans (redacted)
IPs removed, credentials stripped, internal details generalized. Suitable for 3rd party review or compliance audit.

3. Server Provisioning Standard v1
Base OS config, SSH key deployment, standard users, Docker setup, firewall baseline. Every new server follows this pattern.

4. Memory Consolidation Proposal
Three options for improving the memory auto-pruning system — priority tagging, dual-store architecture, or template-based structuring. Recommendation in the document.

Key Findings

Item Status
AI server disk usage 🔴 92% full — clean up before migration
Docker volume backups 🟡 Not automated — needs attention
Database dumps 🟡 Not automated for most servers
Hermes warm standby ✅ Functional via app1-bu
WireGuard tunnel to home ✅ Active (Core + app1-bu)
Router SMTP ✅ Sending via port 2525

No Servers Left Behind

Every Hetzner box is inventoried and documented in the DR plan. Migration targets identified per the RS 4000 standard the Network Services Team defined. The redacted version is clean for external review — no IPs, no credentials, minimal internal topology.

Next Steps

  1. Network Services Team reviews the consolidation proposal
  2. AI server disk cleanup (highest priority)
  3. Docker volume backup automation
  4. Database dump scheduling
  5. Begin netcup migration when ready

Files are saved locally at:
/root/.hermes/references/server-dr-plans.md (full)
/root/.hermes/references/server-dr-plans-redacted.md (redacted)
/root/.hermes/references/server-provisioning-standard-v1.md
/root/.hermes/references/memory-consolidation-proposal.md

""" # Create the alternative parts (plain text + HTML) text_alt = MIMEMultipart("alternative") # Plain text fallback text_part = MIMEText("""DR Plans + Consolidation Proposal Attachments: 1. Per-Server DR Plans (full) - ALL 11 servers 2. Per-Server DR Plans (redacted) - for 3rd party review 3. Server Provisioning Standard v1 4. Memory Consolidation Proposal Key Findings: - AI server disk 92% full - NEEDS CLEANUP - Docker volume backups not automated - Database dumps not automated - Hermes standby functional - WireGuard active on Core + app1-bu Full files at: /root/.hermes/references/server-dr-plans.md /root/.hermes/references/server-dr-plans-redacted.md /root/.hermes/references/server-provisioning-standard-v1.md /root/.hermes/references/memory-consolidation-proposal.md """, "plain") # HTML version sig = open("/root/.hermes/references/shonuff-email-signature.html").read() b64 = open("/root/.hermes/references/shonuff-image-b64.txt").read().strip() title = random.choice(TITLES) closing = random.choice(CLOSINGS) sig = sig.replace("%SHONUFF_IMAGE%", b64).replace("%SHONUFF_TITLE%", title) html_full = f"

{full_body.replace(chr(10), '
')}

{closing}

{sig}" html_part = MIMEText(html_full, "html") text_alt.attach(text_part) text_alt.attach(html_part) msg.attach(text_alt) # Attach the files for fname, display_name in [ ("/root/.hermes/references/server-dr-plans.md", "server-dr-plans-full.md"), ("/root/.hermes/references/server-dr-plans-redacted.md", "server-dr-plans-redacted.md"), ("/root/.hermes/references/server-provisioning-standard-v1.md", "server-provisioning-standard-v1.md"), ("/root/.hermes/references/memory-consolidation-proposal.md", "memory-consolidation-proposal.md"), ]: with open(fname, "rb") as f: attachment = MIMEBase("application", "octet-stream") attachment.set_payload(f.read()) encoders.encode_base64(attachment) attachment.add_header("Content-Disposition", f"attachment; filename={display_name}") msg.attach(attachment) # Send with smtplib.SMTP(SMTP, PORT) as s: s.starttls() s.login(FROM, PASS) s.send_message(msg) print(f"Sent to {TO} — BCC'd g@germainebrown.com")