Fix backups for JSON-file storage + healthcheck; drop handoff folder
- backup.sh: snapshot all of /data as timestamped tar.gz to local NAS path; push to B2 only when a real bucket/key is set (no more nonexistent app.db). - compose: working CMD-SHELL healthcheck; mount /mnt/user/Backup target. - remove the accidentally committed moon-household-budget-handoff/ scaffolding. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,34 +1,44 @@
|
||||
#!/bin/sh
|
||||
# Snapshot the app's data to Backblaze B2 via rclone.
|
||||
# - SQLite DB: a consistent .backup snapshot (safe while the app is running)
|
||||
# - uploads: mirrored to B2
|
||||
# rclone's B2 remote ("b2:") is configured entirely from RCLONE_CONFIG_B2_*
|
||||
# env vars (set in .env / compose). Runs once; the container loops it.
|
||||
# Back up the app's data under /data (the budget JSON files, imported PDFs/CSVs,
|
||||
# and uploaded images). This app stores everything as plain JSON files — there
|
||||
# is no SQLite database.
|
||||
#
|
||||
# Always writes a timestamped tar.gz to the local NAS path (/backups, mounted
|
||||
# from the host). ALSO pushes to Backblaze B2 — but only when a real bucket and
|
||||
# credentials are configured, so it's harmless before B2 is set up.
|
||||
#
|
||||
# rclone's B2 remote ("b2:") is configured from the RCLONE_CONFIG_B2_* env vars.
|
||||
# Runs once; the container loops it on BACKUP_INTERVAL.
|
||||
set -eu
|
||||
|
||||
STAMP=$(date +%Y%m%d-%H%M%S)
|
||||
DEST="b2:${B2_BUCKET}/moon-household-budget"
|
||||
KEEP_DAYS="${BACKUP_KEEP_DAYS:-30}"
|
||||
LOCAL_DIR="/backups"
|
||||
|
||||
echo "[backup ${STAMP}] starting"
|
||||
|
||||
# 1. SQLite snapshot (only if a db file is present)
|
||||
if [ -f /data/app.db ]; then
|
||||
sqlite3 /data/app.db ".backup '/tmp/app-${STAMP}.db'"
|
||||
rclone copyto "/tmp/app-${STAMP}.db" "${DEST}/db/app-${STAMP}.db"
|
||||
rm -f "/tmp/app-${STAMP}.db"
|
||||
echo "[backup ${STAMP}] db snapshot uploaded"
|
||||
# 1. Local timestamped snapshot of everything under /data ---------------------
|
||||
mkdir -p "${LOCAL_DIR}"
|
||||
ARCHIVE="${LOCAL_DIR}/moon-data-${STAMP}.tar.gz"
|
||||
tar -czf "${ARCHIVE}" -C /data .
|
||||
echo "[backup ${STAMP}] local snapshot: ${ARCHIVE} ($(du -h "${ARCHIVE}" | cut -f1))"
|
||||
|
||||
# prune old local snapshots
|
||||
find "${LOCAL_DIR}" -name 'moon-data-*.tar.gz' -type f -mtime +"${KEEP_DAYS}" -delete 2>/dev/null || true
|
||||
|
||||
# 2. Optional Backblaze B2 push (only when a real bucket + key are set) --------
|
||||
if [ -n "${B2_BUCKET:-}" ] && [ "${B2_BUCKET#__}" = "${B2_BUCKET}" ] \
|
||||
&& [ -n "${RCLONE_CONFIG_B2_ACCOUNT:-}" ] && [ "${RCLONE_CONFIG_B2_ACCOUNT#__}" = "${RCLONE_CONFIG_B2_ACCOUNT}" ]; then
|
||||
DEST="b2:${B2_BUCKET}/moon-household-budget"
|
||||
if rclone copyto "${ARCHIVE}" "${DEST}/snapshots/moon-data-${STAMP}.tar.gz" 2>/tmp/rclone.err; then
|
||||
rclone sync /data "${DEST}/current" 2>>/tmp/rclone.err || true
|
||||
rclone delete --min-age "${KEEP_DAYS}d" "${DEST}/snapshots" 2>/dev/null || true
|
||||
echo "[backup ${STAMP}] pushed to B2 (${B2_BUCKET})"
|
||||
else
|
||||
echo "[backup ${STAMP}] B2 push FAILED: $(head -1 /tmp/rclone.err 2>/dev/null)"
|
||||
fi
|
||||
else
|
||||
echo "[backup ${STAMP}] no /data/app.db — skipping db snapshot"
|
||||
echo "[backup ${STAMP}] B2 not configured — local snapshot only"
|
||||
fi
|
||||
|
||||
# 2. Uploaded images (and anything else under /data except the live db)
|
||||
if [ -d /data/uploads ]; then
|
||||
rclone sync /data/uploads "${DEST}/uploads"
|
||||
echo "[backup ${STAMP}] uploads synced"
|
||||
fi
|
||||
|
||||
# 3. Prune old db snapshots
|
||||
rclone delete --min-age "${KEEP_DAYS}d" "${DEST}/db" 2>/dev/null || true
|
||||
|
||||
echo "[backup ${STAMP}] done"
|
||||
|
||||
Reference in New Issue
Block a user