Initial resurrection kit — 81 scripts, 62 references, configs, systemd units, crons, Docker compose files, Caddy config, master README

This commit is contained in:
root
2026-07-15 17:45:36 -04:00
commit ae056eaf83
197 changed files with 26127 additions and 0 deletions
+229
View File
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
"""Build the full Hermes recovery bundle markdown file."""
import sqlite3, json, datetime, os, subprocess, sys
db = sqlite3.connect('/root/.hermes/state.db')
c = db.cursor()
# ===== 1. Get today's user conversations =====
sessions_data = []
c.execute("""
SELECT id, title, started_at, ended_at, end_reason, message_count
FROM sessions
WHERE started_at >= 1783180800 AND id LIKE '2026%'
ORDER BY started_at
""")
for row in c.fetchall():
sessions_data.append({
'id': row[0],
'title': row[1] or '(no title)',
'started': datetime.datetime.fromtimestamp(row[2]).strftime('%H:%M:%S'),
'ended': datetime.datetime.fromtimestamp(row[3]).strftime('%H:%M:%S') if row[3] else 'active',
'end_reason': row[4] or 'running',
'msg_count': row[5]
})
conversation_text = ""
for sd in sessions_data:
conversation_text += f"\n\n{'='*70}\n"
conversation_text += f"SESSION: {sd['id']} | {sd['title']}\n"
conversation_text += f"Started: {sd['started']} | Ended: {sd['ended']} | Status: {sd['end_reason']}\n"
conversation_text += f"{'='*70}\n\n"
c.execute("SELECT role, content, timestamp FROM messages WHERE session_id = ? ORDER BY id", (sd['id'],))
for role, content, ts in c.fetchall():
ts_dt = datetime.datetime.fromtimestamp(ts).strftime('%H:%M:%S')
text = (content or '(empty)').strip()
# Truncate very long messages
if len(text) > 5000:
text = text[:5000] + f"\n... [truncated, was {len(content)} chars]"
conversation_text += f"[{ts_dt}] {role.upper()}:\n{text}\n\n"
db.close()
# ===== 2. Read key files =====
def readf(path):
try:
with open(path) as f:
return f.read()
except Exception as e:
return f"[ERROR: {e}]"
soul = readf('/root/.hermes/SOUL.md')
config_yaml = readf('/root/.hermes/config.yaml')
dotenv = readf('/root/.hermes/.env')
aws_creds = readf('/root/.aws/credentials')
service_file = readf('/etc/systemd/system/hermes.service')
wisp_pub = readf('/root/.ssh/wisp_rsa.pub')
wisp_priv = readf('/root/.ssh/wisp_rsa')
imap_pass = readf('/root/.config/himalaya/g-germainebrown.pass')
hetzner_token = readf('/root/.hermes/scripts/.hetzner_token')
netcup_key = readf('/root/.hermes/scripts/.netcup_api_key')
wisp_config = readf('/root/.hermes/scripts/wisp-backup/config.yaml')
# ===== 3. Get cron jobs =====
result = subprocess.run(['hermes', 'cron', 'list', '--json'], capture_output=True, text=True, timeout=15)
cron_text = ""
try:
cron_data = json.loads(result.stdout)
cron_jobs = cron_data if isinstance(cron_data, list) else cron_data.get('jobs', cron_data.get('data', []))
if not cron_jobs:
cron_text = "(no JSON output — fallback to text list)\n"
# Fallback: run text mode
result2 = subprocess.run(['hermes', 'cron', 'list'], capture_output=True, text=True, timeout=15)
cron_text += result2.stdout
else:
for job in cron_jobs:
cron_text += f"\n### {job.get('name', 'unnamed')}\n"
cron_text += f"- ID: {job.get('id', '?')}\n"
cron_text += f"- Schedule: {job.get('schedule', '?')}\n"
cron_text += f"- Repeat: {job.get('repeat', '')}\n"
cron_text += f"- Deliver: {job.get('deliver', '?')}\n"
cron_text += f"- Script: {job.get('script', 'none')}\n"
cron_text += f"- Skills: {job.get('skills', 'none')}\n"
cron_text += f"- Mode: {'no-agent' if job.get('no_agent') else 'agent-driven'}\n"
cron_text += f"- Next run: {job.get('next_run', '?')}\n"
except Exception as e:
cron_text = f"[Error getting cron jobs: {e}]\n"
result2 = subprocess.run(['hermes', 'cron', 'list'], capture_output=True, text=True, timeout=15)
cron_text += result2.stdout
# ===== 4. Build the recovery document =====
doc = f"""# Hermes Full Recovery Bundle — Jul 5, 2026
> Save this file. If the server dies, paste the contents of the **BOOTSTRAP** section
> below into a new Hermes agent to restore me.
---
## BOOTSTRAP INSTRUCTIONS
### Step 1 — Prerequisites
1. Install Hermes Agent v0.18.0+ on a Linux server (Debian/Ubuntu)
2. Register a Telegram bot with BotFather, get a TELEGRAM_BOT_TOKEN
3. Make sure python3, git, and systemd are available
### Step 2 — Create files
Create these files with the exact contents shown in their sections below:
- `/root/.hermes/config.yaml`
- `/root/.hermes/.env`
- `/root/.aws/credentials`
- `/root/.ssh/wisp_rsa` (chmod 600)
- `/root/.hermes/scripts/.hetzner_token` (chmod 600)
- `/root/.hermes/scripts/.netcup_api_key` (chmod 600)
- `/root/.hermes/SOUL.md`
- All scripts in the Scripts section
### Step 3 — Start Hermes
```bash
hermes gateway start
```
### Step 4 — Recreate cron jobs
```bash
# Run these commands after Hermes is online
# (cron job definitions below)
```
### Step 5 — Verify
```bash
hermes gateway status
hermes cron list
source /opt/awscli-venv/bin/activate && aws s3 ls s3://hermes-vps-backups/ --endpoint-url https://s3.us-east-1.wasabisys.com/
```
---
## CREDENTIALS
**SMTP Password (g@germainebrown.com):** `{imap_pass.strip()}`
**Wasabi S3:** endpoint=https://s3.us-east-1.wasabisys.com | Access Key: GYH83FP0KL0K85N60JKQ
**Hetzner API Token:** `{hetzner_token.strip()}`
**netcup API Key:** `{netcup_key.strip()}`
**admin-ai API Key:** In config.yaml (sk-lbhhxIk...bWPA)
**Telegram Bot Token:** In .env file below
---
## CONFIG FILES
### /root/.hermes/SOUL.md
```
{soul}
```
### /root/.hermes/config.yaml
```yaml
{config_yaml}
```
### /root/.hermes/.env
```
{dotenv}
```
### /root/.aws/credentials
```
{aws_creds}
```
### /etc/systemd/system/hermes.service
```
{service_file}
```
---
## SSH KEYS
### WISP Public Key
```
{wisp_pub}
```
### WISP Private Key
```
{wisp_priv}
```
---
## WISP BACKUP CONFIG
```yaml
{wisp_config}
```
---
## CRON JOBS
{cron_text}
---
## SCRIPT FILES
### imap_triage.py
"""
# Read scripts
script_dir = '/root/.hermes/scripts'
for fname in sorted(os.listdir(script_dir)):
fpath = os.path.join(script_dir, fname)
if os.path.isfile(fpath) and not fname.startswith('.'):
content = readf(fpath)
doc += f"\n### {fname}\n```\n{content}\n```\n"
# Also read wisp-backup subdirectory scripts
wisp_dir = os.path.join(script_dir, 'wisp-backup')
if os.path.isdir(wisp_dir):
for fname in sorted(os.listdir(wisp_dir)):
fpath = os.path.join(wisp_dir, fname)
if os.path.isfile(fpath) and not fname.endswith('.pyc'):
content = readf(fpath)
doc += f"\n### wisp-backup/{fname}\n```\n{content}\n```\n"
doc += "\n\n---\n\n## TODAY'S CONVERSATION HISTORY\n"
doc += conversation_text
# ===== 5. Write file =====
output_path = '/root/.hermes/recovery-bundle-2026-07-05.md'
with open(output_path, 'w') as f:
f.write(doc)
file_size = os.path.getsize(output_path)
print(f"RECOVERY FILE: {output_path}")
print(f"SIZE: {file_size} bytes ({file_size/1024:.1f} KB)")
print(f"TODAY SESSIONS: {len(sessions_data)}")