Files
hermes-skills/skills/devops/server-recovery-bundle/SKILL.md
T

5.4 KiB

name, description, version, author, license, platforms, metadata
name description version author license platforms metadata
server-recovery-bundle Build self-contained recovery bundles containing all config, scripts, credentials, cron jobs, and conversation history needed to restore a Hermes instance onto a brand-new server. 1.1.0 Hermes Agent MIT
linux
hermes
tags related_skills
disaster-recovery
backup
migration
bootstrap
hermetic
email-workflows
hermes-agent
hermes-backup

Server Recovery Bundle

Build a single self-contained markdown file that can be pasted into a fresh Hermes agent to fully restore the instance. Think of it as a disaster recovery envelope — all the config, scripts, and secrets someone would need if this server died tomorrow.

When to use

  • User asks for a "recovery bundle", "restore kit", "bootstrap file", or "everything I need to rebuild you"
  • After a server migration (document the new state)
  • Before a destructive upgrade or decommission
  • As a periodic safety net alongside regular backups

What to include

1. Header section

  • Title, date, one-line purpose
  • "Paste this into a new Hermes to restore me" instruction

2. Bootstrap instructions

  • Step-by-step: install Hermes, create each file, start gateway, recreate cron jobs, verify

3. Credentials summary (one place, easy to find)

  • SMTP/IMAP password
  • S3 (Wasabi/AWS) keys
  • Cloud API tokens (Hetzner, netcup, etc.)
  • VPN keys or passwords
  • A clear note of what each credential is for
  • WARNING: The recovery bundle contains cleartext secrets. It must be treated as a credential file and stored securely (password manager, encrypted vault). If emailed, use encrypted email or delete after transfer.

4. Config files — verbatim

  • ~/.hermes/config.yaml
  • ~/.hermes/.env
  • ~/.aws/credentials
  • ~/.hermes/SOUL.md
  • /etc/systemd/system/hermes.service
  • Any other env/config files the instance depends on

5. SSH keys (public + private)

  • WISP keys, deploy keys, any SSH keys used by scripts

6. Cron jobs — full definition

Include for each job: name, schedule, script path, skills, mode (no_agent/agent), deliver target Use hermes cron list --json (and fallback to text if JSON fails)

7. Scripts — verbatim

Every file in ~/.hermes/scripts/ that isn't in __pycache__ or starts with . Also include subdirectory scripts (wisp-backup/, etc.)

8. Today's conversation history

  • Get today's user sessions (not cron sessions) from the state DB
  • Filter by started_at >= today_midnight AND id LIKE '20%' (excludes cron sessions which start with cron_)
  • Include full message text from both sessions
  • Truncate extremely long messages (>5000 chars) with a note

Key patterns and pitfalls

Session filtering

Cron sessions have IDs like cron_<hash>_<timestamp> — filter them out by requiring id LIKE '20%' (user session IDs start with a date). The SQL filter:

SELECT id, title, started_at, ended_at, end_reason, message_count
FROM sessions 
WHERE started_at >= <today_unix_ts> AND id LIKE '20%'
ORDER BY started_at

Handling SMTP delivery failure

The recovery bundle file can be large (200-500 KB). Common email pitfalls:

  • Your mail server and agent server are different machines — always verify port reachability before assuming SMTP works
  • Test each port separately: SMTP (587), IMAP (993). One can be open while the other is firewalled.
  • A CNAME or MX record can point to a totally different provider than your other infrastructure. DNS lookup: host mail.example.com or python3 -c "import socket; print(socket.gethostbyname('mail.example.com'))"
  • Test with: python3 -c "import socket; s=socket.socket(); s.settimeout(5); s.connect(('<host>', 587)); print('OK')"
  • A port that times out (not refuses) points to a firewall drop, not a server-side block — your ISP or cloud provider may be filtering outbound SMTP
  • If SMTP fails: try Wasabi S3 upload as fallback (aws s3 cp with --endpoint-url)
  • Or deliver directly in the current chat (Telegram/WhatsApp can take large files)

Don't fabricate

Do not include password/API-key values you "reconstruct" from memory. Only include credentials you actually read from files on this machine. If a credential file doesn't exist, say so rather than leaving a placeholder.

Message truncation

Very long messages (compacted context, large JSON tool outputs) should be truncated at ~5000 chars with a note: [truncated, was N chars]. This keeps the bundle readable and under email size limits.

Cron job retention from state.db

After a server migration, cron jobs survive in state.db but the scheduler needs ~30-60s to discover them after startup. If hermes cron list returns empty immediately after migration, wait and retry before assuming they were lost.

Build script pattern

Rather than assembling the bundle inline in the agent's tool loop, write a Python build script (scripts/build-recovery.py) that:

  1. Queries state.db for sessions/messages
  2. Reads all config/script/credential files
  3. Assembles the markdown document
  4. Writes the output file

This avoids context-window overflow on large state DBs and makes the bundle reproducible.

Verification

After building the recovery bundle:

  1. Verify the file was written: wc -c <path>
  2. Try to upload/send it (failures here are worth reporting to the user)
  3. List what's in it: session count, script count, cron count
  4. Report result to the user with the file location and any delivery issues