#!/usr/bin/env bash
set -u
REPO="/mnt/mybooklive-vps/RESTIC"
PASS="/etc/restic/nas-password"
BASE="/tmp/restic-verify"
REPORT="/root/restic-verification-2026-08-13.txt"
rm -rf "$BASE"
mkdir -p "$BASE"
: > "$REPORT"
exec > >(tee -a "$REPORT") 2>&1
echo "============================================================"
echo " RESTIC GESAMTPRÜFUNG"
echo " Start: $(date -Is)"
echo "============================================================"
echo
FAIL=0
WARN=0
ok() { echo "[OK] $*"; }
warn() { echo "[WARN] $*"; WARN=$((WARN+1)); }
fail() { echo "[FAIL] $*"; FAIL=$((FAIL+1)); }
echo "=== 1. SNAPSHOT-LISTE ==="
restic -r "$REPO" --password-file "$PASS" snapshots || fail "Snapshot-Liste fehlgeschlagen"
echo
echo "=== 2. RESTIC REPOSITORY CHECK --read-data ==="
if restic -r "$REPO" --password-file "$PASS" check --read-data; then
ok "Restic Repository inklusive gespeicherter Datenblöcke"
else
fail "Restic Repository-Check"
fi
echo
declare -A SNAPS=(
[obsidian]="cbca7e22"
[cron]="bba732f7"
[kanban]="34aaf8c8"
[sma]="13c7bb0e"
[n8n]="4d052153"
[graphiti]="8f1d4f17"
[mirofish]="95a57838"
[couchdb]="43070023"
[vento]="56ca305d"
[lead-engine]="aaea505e"
[hermes-skills]="11fb7f73"
[hermes-prompts-scripts]="4c2c3db3"
[hermes-workstates]="6f84f8e7"
[knowledge-databases]="e017a3f4"
[project-core]="dc37c090"
[courses]="eb5d2561"
[social-media]="e35f24e5"
[research-apps]="abb6bfb9"
[reports-reference]="3b95c8b7"
[worker-watcher]="a6ed70a1"
[solar-wirtschaftlichkeit]="42a2b280"
[telefon-agent]="b054da41"
[the-donna]="feff007a"
[vps-admin-reference]="45100dc8"
)
echo "=== 3. ALLE SNAPSHOTS RESTAURIEREN ==="
for name in "${!SNAPS[@]}"; do
snap="${SNAPS[$name]}"
target="$BASE/$name"
mkdir -p "$target"
echo
echo "--- $name / $snap ---"
if restic -r "$REPO" --password-file "$PASS" \
restore "$snap" --target "$target"; then
files=$(find "$target" -type f | wc -l)
bytes=$(du -sb "$target" 2>/dev/null | awk '{print $1}')
if [ "$files" -gt 0 ]; then
ok "$name restauriert: $files Dateien, $bytes Bytes"
else
fail "$name restauriert, aber keine Dateien gefunden"
fi
else
fail "$name Restore fehlgeschlagen"
fi
done
echo
echo "=== 4. SQLITE-INTEGRITÄT ==="
SQLITE_COUNT=0
SQLITE_FAIL=0
while IFS= read -r -d '' f; do
if head -c 16 "$f" 2>/dev/null | grep -aq "SQLite format 3"; then
SQLITE_COUNT=$((SQLITE_COUNT+1))
result=$(sqlite3 "$f" "PRAGMA integrity_check;" 2>&1)
if [ "$result" = "ok" ]; then
ok "SQLite: $f"
else
fail "SQLite: $f -> $result"
SQLITE_FAIL=$((SQLITE_FAIL+1))
fi
fi
done < <(
find "$BASE" -type f \
\( -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' \) \
-print0
)
echo
echo "SQLite-Datenbanken erkannt: $SQLITE_COUNT"
echo "SQLite-Fehler: $SQLITE_FAIL"
echo
echo "=== 5. JSON-EXPORTS / REFERENZDATEIEN ==="
JSON_COUNT=0
JSON_FAIL=0
while IFS= read -r -d '' f; do
JSON_COUNT=$((JSON_COUNT+1))
if python3 -m json.tool "$f" >/dev/null 2>&1; then
:
else
# JSONL ist absichtlich kein einzelnes JSON-Dokument.
case "$f" in
*.jsonl)
;;
*)
warn "JSON nicht parsebar: $f"
JSON_FAIL=$((JSON_FAIL+1))
;;
esac
fi
done < <(find "$BASE" -type f \( -name '*.json' -o -name '*.jsonl' \) -print0)
echo "JSON/JSONL-Dateien geprüft: $JSON_COUNT"
echo "JSON-Warnungen: $JSON_FAIL"
echo
echo "=== 6. NEO4J-DUMPS ==="
GRAPH_DUMP=$(find "$BASE/graphiti" -type f -name 'neo4j.dump' -print -quit 2>/dev/null || true)
MIRO_DUMP=$(find "$BASE/mirofish" -type f -name 'neo4j.dump' -print -quit 2>/dev/null || true)
check_dump() {
local label="$1"
local image="$2"
local dump="$3"
if [ -z "$dump" ] || [ ! -s "$dump" ]; then
fail "$label Neo4j-Dump fehlt oder ist leer"
return
fi
local dir
dir=$(dirname "$dump")
echo "--- $label ---"
ls -lh "$dump"
if docker run --rm \
-v "$dir:/backup:ro" \
"$image" \
neo4j-admin database load neo4j \
--from-path=/backup \
--info; then
ok "$label Neo4j-Dump wird von neo4j-admin erkannt"
else
warn "$label Dump konnte mit load --info nicht validiert werden"
fi
}
check_dump "Graphiti" "neo4j:5.26-community" "$GRAPH_DUMP"
check_dump "MiroFish" "neo4j:5.18-community" "$MIRO_DUMP"
echo
echo "=== 7. SPEZIELLE PFLICHTDATEIEN ==="
require_pattern() {
local label="$1"
local root="$2"
local pattern="$3"
if find "$root" -type f -name "$pattern" -print -quit 2>/dev/null | grep -q .; then
ok "$label vorhanden"
else
fail "$label fehlt"
fi
}
require_pattern "Cron jobs.json" "$BASE/cron" "jobs.json"
require_pattern "Kanban kanban.db" "$BASE/kanban" "kanban.db"
require_pattern "SMA signals.db" "$BASE/sma" "signals.db"
require_pattern "n8n database.sqlite" "$BASE/n8n" "database.sqlite"
require_pattern "YouTube Knowledge DB" "$BASE/knowledge-databases" "youtube-research-knowledge.db"
require_pattern "Knowledge Pipeline DB" "$BASE/knowledge-databases" "knowledge-pipeline.db"
require_pattern "Worker Watcher DB" "$BASE/worker-watcher" "watcher.sqlite"
require_pattern "Solar DB" "$BASE/solar-wirtschaftlichkeit" "solar.sqlite"
echo
echo "=== 8. GESAMTERGEBNIS ==="
echo "Ende: $(date -Is)"
echo
echo "FEHLER: $FAIL"
echo "WARNUNGEN:$WARN"
if [ "$FAIL" -eq 0 ]; then
echo
echo "GESAMTSTATUS: OK"
else
echo
echo "GESAMTSTATUS: FEHLER"
fi
echo
echo "Bericht: $REPORT"
echo "Restore-Verzeichnis: $BASE"
echo "============================================================"
exit 0