Overview
Rousseau's entire operational state fits in two SQLite files:
sessions.db— conversations, cron jobs, JID map, FTS5 index, claude cache.whatsapp.db— whatsmeow device credentials (WhatsApp only).
Every DR strategy here revolves around backing those files up and restoring them cleanly.
Backup
Before any upgrade, migration, or destructive command:
D=$(date -u +%Y%m%d-%H%M%SZ)
mkdir -p ~/backup/rousseau/$D
sqlite3 ~/.local/share/rousseau/sessions.db ".backup ~/backup/rousseau/$D/sessions.db"
cp ~/.local/share/rousseau/whatsapp.db ~/backup/rousseau/$D/whatsapp.db 2>/dev/null || true
# ~/.config/systemd/user/rousseau-backup.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/rousseau-backup.sh
# ~/.config/systemd/user/rousseau-backup.timer
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
# /usr/local/bin/rousseau-backup.sh
#!/usr/bin/env bash
set -euo pipefail
D=$(date -u +%Y%m%d-%H%M%SZ)
DEST="$HOME/backup/rousseau/$D"
mkdir -p "$DEST"
sqlite3 "$HOME/.local/share/rousseau/sessions.db" ".backup $DEST/sessions.db"
cp "$HOME/.local/share/rousseau/whatsapp.db" "$DEST/" 2>/dev/null || true
find "$HOME/backup/rousseau" -mindepth 1 -maxdepth 1 -mtime +30 -print0 | xargs -0 rm -rf --
export RESTIC_REPOSITORY=b2:rousseau-bucket:backups
export RESTIC_PASSWORD_FILE=/etc/rousseau/restic.pw
restic backup \
~/.local/share/rousseau/sessions.db \
~/.local/share/rousseau/whatsapp.db \
--tag rousseau
Restore
# Stop any running rousseau processes first
systemctl --user stop 'rousseau-*.service'
pkill -TERM rousseau 2>/dev/null || true
# Restore
cp ~/backup/rousseau/<D>/sessions.db ~/.local/share/rousseau/
cp ~/backup/rousseau/<D>/whatsapp.db ~/.local/share/rousseau/ 2>/dev/null || true
# Verify
sqlite3 ~/.local/share/rousseau/sessions.db "PRAGMA integrity_check;"
# expect: ok
# Start
systemctl --user start 'rousseau-*.service'
Integrity checks
Run monthly:
sqlite3 ~/.local/share/rousseau/sessions.db "PRAGMA integrity_check;"
sqlite3 ~/.local/share/rousseau/sessions.db "PRAGMA quick_check;"
sqlite3 ~/.local/share/rousseau/sessions.db "SELECT COUNT(*) FROM sessions;"
If integrity_check returns anything other than ok, restore from the latest good backup.
What survives
| Backup | Restores | Notes |
|---|---|---|
sessions.db |
Conversations, cron jobs, JID map, FTS5, claude cache | Enough for full recovery of history + scheduled prompts |
whatsapp.db |
WhatsApp pairing | Without this, a QR re-pair is required |
~/.claude/ (for claudecli) |
Claude Code OAuth | Not owned by rousseau; back up separately |
~/.config/rousseau/config.yaml |
Config | Also worth versioning |
Failure modes
- Backup taken during a heavy write — WAL means readers see a consistent snapshot, but a plain
cpmight catch the WAL mid-checkpoint. Use.backupor stop the daemon. - Restore into a running daemon — silent corruption. Always stop the process first.
- Restore with mismatched user — the file will be owned by the wrong user after container/host role changes.
chownback torousseau:rousseau(or your uid).