teleo-infrastructure/ops/backup_vps_sqlite_kb.sh
twentyOne2x ce261a8ee6
Some checks are pending
CI / lint-and-test (push) Waiting to run
Add VPS SQLite KB backup canary (#42)
2026-07-07 12:05:46 +02:00

99 lines
4.2 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# Creates a consistent SQLite backup and a secrets-excluded Leo/KB file archive
# from the Teleo VPS. It writes local proof files but does not upload to GCP.
TELEO_VPS_HOST="${TELEO_VPS_HOST:-root@77.42.65.182}"
TELEO_SSH_KEY="${TELEO_SSH_KEY:-$HOME/.ssh/livingip_hetzner_20260604_ed25519}"
TELEO_REMOTE_ROOT="${TELEO_REMOTE_ROOT:-/opt/teleo-eval}"
REMOTE_BACKUP_ROOT="${REMOTE_BACKUP_ROOT:-/opt/teleo-eval/backups}"
LOCAL_BACKUP_DIR="${LOCAL_BACKUP_DIR:-./outputs/gcp-infra-hardening-20260707/private-backups}"
PROOF_DIR="${PROOF_DIR:-./outputs/gcp-infra-hardening-20260707/proofs}"
TS="${TS:-$(date -u +%Y%m%dT%H%M%SZ)}"
SQLITE_REMOTE_DIR="${REMOTE_BACKUP_ROOT}/pipeline"
SQLITE_BASE="teleo-pipeline-sqlite-${TS}"
KB_REMOTE_DIR="${REMOTE_BACKUP_ROOT}/kb"
KB_BASE="teleo-leo-kb-files-${TS}"
ssh_base=(
ssh
-i "$TELEO_SSH_KEY"
-o BatchMode=yes
-o StrictHostKeyChecking=accept-new
)
scp_base=(
scp
-i "$TELEO_SSH_KEY"
-o BatchMode=yes
-o StrictHostKeyChecking=accept-new
)
sha256_file() {
if command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$1" | awk '{print $1}'
else
sha256sum "$1" | awk '{print $1}'
fi
}
mkdir -p "$LOCAL_BACKUP_DIR" "$PROOF_DIR"
chmod 700 "$LOCAL_BACKUP_DIR"
"${ssh_base[@]}" "$TELEO_VPS_HOST" "set -euo pipefail
mkdir -p '$SQLITE_REMOTE_DIR' '$KB_REMOTE_DIR'
chmod 700 '$SQLITE_REMOTE_DIR' '$KB_REMOTE_DIR'
sqlite3 '$TELEO_REMOTE_ROOT/pipeline/pipeline.db' \".backup '$SQLITE_REMOTE_DIR/${SQLITE_BASE}.db'\"
gzip -f -9 '$SQLITE_REMOTE_DIR/${SQLITE_BASE}.db'
sha256sum '$SQLITE_REMOTE_DIR/${SQLITE_BASE}.db.gz' > '$SQLITE_REMOTE_DIR/${SQLITE_BASE}.db.gz.sha256'
cd '$TELEO_REMOTE_ROOT'
tar --warning=no-file-changed --exclude='secrets' --exclude='*.log' --exclude='logs' -czf '$KB_REMOTE_DIR/${KB_BASE}.tar.gz' \\
workspaces/main/agents/leo \\
workspaces/research-leo/agents/leo \\
agent-state
sha256sum '$KB_REMOTE_DIR/${KB_BASE}.tar.gz' > '$KB_REMOTE_DIR/${KB_BASE}.tar.gz.sha256'
ls -lh '$SQLITE_REMOTE_DIR/${SQLITE_BASE}.db.gz' '$KB_REMOTE_DIR/${KB_BASE}.tar.gz'
" > "$PROOF_DIR/vps-backup-create-${TS}.txt"
"${scp_base[@]}" "$TELEO_VPS_HOST:${SQLITE_REMOTE_DIR}/${SQLITE_BASE}.db.gz" "$LOCAL_BACKUP_DIR/"
"${scp_base[@]}" "$TELEO_VPS_HOST:${SQLITE_REMOTE_DIR}/${SQLITE_BASE}.db.gz.sha256" "$LOCAL_BACKUP_DIR/"
"${scp_base[@]}" "$TELEO_VPS_HOST:${KB_REMOTE_DIR}/${KB_BASE}.tar.gz" "$LOCAL_BACKUP_DIR/"
"${scp_base[@]}" "$TELEO_VPS_HOST:${KB_REMOTE_DIR}/${KB_BASE}.tar.gz.sha256" "$LOCAL_BACKUP_DIR/"
chmod 600 \
"$LOCAL_BACKUP_DIR/${SQLITE_BASE}.db.gz" \
"$LOCAL_BACKUP_DIR/${SQLITE_BASE}.db.gz.sha256" \
"$LOCAL_BACKUP_DIR/${KB_BASE}.tar.gz" \
"$LOCAL_BACKUP_DIR/${KB_BASE}.tar.gz.sha256"
sqlite_expected="$(awk '{print $1}' "$LOCAL_BACKUP_DIR/${SQLITE_BASE}.db.gz.sha256")"
sqlite_actual="$(sha256_file "$LOCAL_BACKUP_DIR/${SQLITE_BASE}.db.gz")"
kb_expected="$(awk '{print $1}' "$LOCAL_BACKUP_DIR/${KB_BASE}.tar.gz.sha256")"
kb_actual="$(sha256_file "$LOCAL_BACKUP_DIR/${KB_BASE}.tar.gz")"
test "$sqlite_expected" = "$sqlite_actual"
test "$kb_expected" = "$kb_actual"
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
gunzip -c "$LOCAL_BACKUP_DIR/${SQLITE_BASE}.db.gz" > "$tmpdir/pipeline.db"
{
echo "sqlite_backup=$LOCAL_BACKUP_DIR/${SQLITE_BASE}.db.gz"
echo "sqlite_remote=$SQLITE_REMOTE_DIR/${SQLITE_BASE}.db.gz"
echo "sqlite_backup_size_bytes=$(wc -c < "$LOCAL_BACKUP_DIR/${SQLITE_BASE}.db.gz" | tr -d ' ')"
echo "sqlite_db_size_bytes=$(wc -c < "$tmpdir/pipeline.db" | tr -d ' ')"
echo "sqlite_sha256=$sqlite_actual"
echo "sqlite_sha256_matches_vps=true"
echo "sqlite_integrity_check=$(sqlite3 "$tmpdir/pipeline.db" 'PRAGMA integrity_check;')"
echo "sqlite_user_table_count=$(sqlite3 "$tmpdir/pipeline.db" "select count(*) from sqlite_master where type='table' and name not like 'sqlite_%';")"
echo "kb_backup=$LOCAL_BACKUP_DIR/${KB_BASE}.tar.gz"
echo "kb_remote=$KB_REMOTE_DIR/${KB_BASE}.tar.gz"
echo "kb_backup_size_bytes=$(wc -c < "$LOCAL_BACKUP_DIR/${KB_BASE}.tar.gz" | tr -d ' ')"
echo "kb_sha256=$kb_actual"
echo "kb_sha256_matches_vps=true"
echo "kb_file_count=$(tar -tzf "$LOCAL_BACKUP_DIR/${KB_BASE}.tar.gz" | wc -l | tr -d ' ')"
} > "$PROOF_DIR/vps-sqlite-kb-backup-proof-${TS}.txt"
cat "$PROOF_DIR/vps-sqlite-kb-backup-proof-${TS}.txt"