Files
kvitt/infra/RESTORE.md
T
jacobh2 2476667510 M2c-pi: Pi bundle (infra/pi), cert-sync, Drive backup upload, Gitea workflow
The owner copies infra/pi/ to the Kvitt Pi and runs it there (D-100); nothing
on the Mac connects to the Pis. compose stack of SPEC §10.2 with images
${KVITT_REGISTRY}/kvitt-{server,cert-sync,backup}, Caddyfile §10.5.2 verbatim,
.env.example with the OQ-3 values as CHANGE_ME placeholders, install.sh,
deploy.sh (backup before every deploy), bootstrap.sh, backup-now.sh,
install-apk.sh. cert-sync image and sync.sh (§10.5.1, tar stream for both
authorized_keys variants); backup.sh uploads with rclone copy --immutable and
deletes local files once both are confirmed on Drive (D-002); both sidecars
schedule with supercronic because busybox crond runs no jobs as non-root;
backup runs as uid 10001. .gitea/workflows/build-images.yaml from the owner's
example (not yet run); infra/build-images.sh and infra/publish-apk.sh (R8
mapping kept, version per §10.6) on the Mac; README checklist and RESTORE.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
2026-10-18 21:48:35 +02:00

89 lines
3.2 KiB
Markdown

# Restore Kvitt from a Drive backup (SPEC §10.9)
Run on the Kvitt Pi, in `/opt/kvitt`, as the owner's user. Every command uses the running `backup` container,
which has `sqlite3`, `rclone`, the Drive credentials and the `data` and `backups` volumes, and runs as uid 10001,
the owner of the server's files. Nothing is deleted: the current database and pictures are moved aside.
Do not run it around 03:30, when the nightly backup runs.
```bash
cd /opt/kvitt
B="docker compose exec -T backup sh -c"
FOLDER=$(sed -n 's/^RCLONE_FOLDER_ID=//p' .env); REMOTE=$(sed -n 's/^RCLONE_REMOTE=//p' .env)
```
## 1. Stop the server
```bash
docker compose stop server
```
## 2. Download the chosen backup from Drive to the Pi
List what is on Drive (newest last) and pick a stamp:
```bash
$B 'c=$(mktemp); cp /config/rclone/rclone.conf "$c"; RCLONE_CONFIG=$c rclone lsf "$1" --drive-root-folder-id "$2" --files-only; rm -f "$c"' sh "$REMOTE" "$FOLDER" | sort
STAMP=20261102T013000Z # the stamp of the pair you chose
```
Download both files into the `backups` volume:
```bash
$B 'set -e; mkdir -p /backups/restore; c=$(mktemp); cp /config/rclone/rclone.conf "$c"
for f in "kvitt-$3.sqlite.gz" "pictures-$3.tar.gz"; do
RCLONE_CONFIG=$c rclone copy "$1$f" /backups/restore/ --drive-root-folder-id "$2"
done; rm -f "$c"; ls -l /backups/restore' sh "$REMOTE" "$FOLDER" "$STAMP"
```
(A file downloaded in the browser instead: copy it to the Pi with `scp`, then
`docker compose cp <file> backup:/backups/restore/`.)
## 3. Unpack and check
```bash
$B 'set -e; cd /backups/restore; gunzip -f "kvitt-$1.sqlite.gz"; sqlite3 "kvitt-$1.sqlite" "PRAGMA integrity_check"' sh "$STAMP"
```
It must print `ok`. Anything else: stop here and pick another backup.
## 4. Move the current data aside and put the backup in place
```bash
$B 'set -e; aside="/data/pre-restore-$(date -u +%Y%m%dT%H%M%SZ)"; mkdir "$aside"
for f in /data/kvitt.sqlite /data/kvitt.sqlite-wal /data/kvitt.sqlite-shm /data/pictures; do
[ -e "$f" ] && mv "$f" "$aside/"
done
cp "/backups/restore/kvitt-$1.sqlite" /data/kvitt.sqlite
tar -xzf "/backups/restore/pictures-$1.tar.gz" -C /data
echo "previous data kept in $aside"; ls -l /data' sh "$STAMP"
```
## 5. New sync epoch
```bash
docker compose run --rm server rotate-epoch
```
It prints the new epoch. The phones see it and re-push their data (§14.4.8).
## 6. Start the server and check health
```bash
docker compose start server
docker compose ps server # healthy within a minute
curl -fsS --resolve icehack.asuscomm.com:8443:127.0.0.1 https://icehack.asuscomm.com:8443/health
```
The last line prints `{"status":"ok",...}`.
## 7. The phones
Open Kvitt on both phones (owner's and partner's) and leave it open for a minute; the next sync detects the new
epoch and re-pushes the phone's data (if nothing seems to happen, close the app and open it again). Check that both phones show the same balances on Översikt (yes/no).
## Afterwards
When the phones agree, the downloaded files can go:
`$B 'rm -r /backups/restore'`. The `/data/pre-restore-<stamp>/` folder stays until you decide otherwise
(`$B 'ls /data'` shows it). Run `/opt/kvitt/backup-now.sh` once to put the restored state on Drive.