Work produced by the /kb driver on 2026-07-30. Each change is recorded on its Kanboard task; all remain Done-unverified or parked pending alvis's decisions. #183 agap-mcp/src/gitea.js askpassScript() and giteaWikiWrite()'s wiki checkout both used /tmp/agap-mcp-wiki, so writing the askpass helper made the dir non-empty and git clone always failed. gitea_wiki_write had likely never succeeded in production. Askpass moved to its own dir. #181 agap-mcp/src/server.js Initialise registeredToolCount at module load so /health reports the real count immediately instead of 0 until the first MCP request. #189 kanboard/backup.sh, seafile/backup.sh, vaultwarden/backup.sh, users-backup.sh, openai/backup-{hindsight-adolf,llm-dbs}.sh Remove the dead *.ts Zabbix trapper pushes (never landed). users-backup.sh also pointed at localhost:81 instead of 192.168.1.4:81 and pushed a date string into a numeric item. Freshness monitoring now rides the .age items. #192 RESTORE-RUNBOOK.md, {kanboard,seafile,vaultwarden}/restore.sh Restore path for the three services, verified in throwaway containers. Note: this work found Seafile backups have carried an empty ccnet_db.sql since 2026-07-07 -- filed as kb#222, not fixed here. #164 openai/litellm-config.yaml Metered `judge` (anthropic/claude-haiku-4-5) entry removed per alvis's 2026-07-30 decision. ANTHROPIC_API_KEY was never wired, so it could not spend. #128 openai/agent_registry.py litellm_key_spec() now also grants the routing-mode aliases, gated by the same _reachable_tiers() check as raw grants, so a small-tier agent cannot acquire automatic routing that resolves to tier-large. #219 openai/migrate-adolf-state.sh Migration script only; inert until run. Copies (never moves) the openai_adolf-state volume to /mnt/ssd/dbs/adolf, verifying a full sha256 manifest before declaring success. Tested against a throwaway volume. Deliberately NOT included, both awaiting alvis: agap-mcp/docker-compose.yml -- kb#174's contested BW_EMAIL revert (parked). openai/docker-compose.yml -- kb#219's bind-mount switch; the target dirs under /mnt/ssd/dbs/adolf do not exist yet, so committing it would let a later `compose up` recreate Adolf against empty paths. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Y5QPagv4iun1ghpwM96Ff
73 lines
2.3 KiB
Bash
Executable File
73 lines
2.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# Vaultwarden restore — companion to backup.sh (kb#192).
|
|
#
|
|
# Restores a snapshot produced by backup.sh (db_*.sqlite3, config.json,
|
|
# rsa_key*, attachments/, sends/) into a Vaultwarden data directory.
|
|
# Defaults to the live container/data dir, but every target is overridable
|
|
# via env vars so the same script can be pointed at a throwaway
|
|
# container + scratch data dir for a dry-run restore test.
|
|
#
|
|
# Usage:
|
|
# ./restore.sh /mnt/backups/vaultwarden/<snapshot-dir>
|
|
#
|
|
# Env overrides (defaults = live service):
|
|
# CONTAINER=vaultwarden
|
|
# DATA_DIR=/mnt/ssd/dbs/vw-data
|
|
#
|
|
# WARNING: this overwrites the target's live vault database. Never run
|
|
# against the "vaultwarden" container / /mnt/ssd/dbs/vw-data unless you
|
|
# intend a real disaster recovery — for testing, point CONTAINER/DATA_DIR
|
|
# at a throwaway container and a scratch directory instead.
|
|
|
|
set -euo pipefail
|
|
|
|
CONTAINER="${CONTAINER:-vaultwarden}"
|
|
DATA_DIR="${DATA_DIR:-/mnt/ssd/dbs/vw-data}"
|
|
|
|
if [ $# -lt 1 ]; then
|
|
echo "Usage: $0 <path-to-backup-snapshot-dir>" >&2
|
|
echo " e.g. $0 /mnt/backups/vaultwarden/20260728-0200" >&2
|
|
exit 1
|
|
fi
|
|
|
|
SRC="$(realpath "$1")"
|
|
DB_FILE="$(find "$SRC" -maxdepth 1 -name 'db_*.sqlite3' | head -n1)"
|
|
|
|
if [ -z "$DB_FILE" ] || [ ! -f "$DB_FILE" ]; then
|
|
echo "Error: no db_*.sqlite3 file found in $SRC" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Restoring into '$CONTAINER' (data dir: $DATA_DIR) from $SRC"
|
|
|
|
docker stop "$CONTAINER" > /dev/null
|
|
|
|
mkdir -p "$DATA_DIR"
|
|
cp "$DB_FILE" "$DATA_DIR/db.sqlite3"
|
|
[ -f "$SRC/config.json" ] && cp "$SRC/config.json" "$DATA_DIR/"
|
|
[ -f "$SRC/rsa_key.pem" ] && cp "$SRC"/rsa_key* "$DATA_DIR/" 2>/dev/null || true
|
|
[ -d "$SRC/attachments" ] && rsync -a --delete "$SRC/attachments/" "$DATA_DIR/attachments/"
|
|
[ -d "$SRC/sends" ] && rsync -a --delete "$SRC/sends/" "$DATA_DIR/sends/"
|
|
|
|
docker start "$CONTAINER" > /dev/null
|
|
|
|
echo "Waiting for Vaultwarden to come up..."
|
|
for i in $(seq 1 30); do
|
|
if docker exec "$CONTAINER" test -f /data/db.sqlite3 > /dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
echo "Verifying restored database..."
|
|
docker exec "$CONTAINER" sh -c '
|
|
if command -v sqlite3 >/dev/null 2>&1; then
|
|
echo "users row count: $(sqlite3 /data/db.sqlite3 "SELECT COUNT(*) FROM users;")"
|
|
else
|
|
echo "(sqlite3 CLI not present in image; file size check only)"
|
|
ls -la /data/db.sqlite3
|
|
fi
|
|
'
|
|
|
|
echo "Restore complete: $CONTAINER"
|