fix: backup and restore data/ dir on update and rollback

The data/ directory (services.json, config.json, credentials,
TOTP config, notifications) was never included in the update
backup. Every update wiped user data — services, licenses,
credentials — requiring manual restore.

Now the host-side updater:
- Backs up data/ alongside code files before any update
- Restores data/ on rollback (build failure, restart failure,
  or health-check failure)
This commit is contained in:
Hermes
2026-05-28 02:08:33 -07:00
parent 588188edb5
commit c52016d727
+27 -4
View File
@@ -115,7 +115,7 @@ main() {
exit 1 exit 1
fi fi
# 3. Backup current API files # 3. Backup current API files AND data directory
local backup_dir="${BACKUPS_DIR}/${from_version}" local backup_dir="${BACKUPS_DIR}/${from_version}"
mkdir -p "$backup_dir" mkdir -p "$backup_dir"
log "Backing up current API files to ${backup_dir}" log "Backing up current API files to ${backup_dir}"
@@ -126,9 +126,14 @@ main() {
done done
[[ -d "$api_source_dir/routes" ]] && cp -rf "$api_source_dir/routes" "$backup_dir/" [[ -d "$api_source_dir/routes" ]] && cp -rf "$api_source_dir/routes" "$backup_dir/"
[[ -d "$api_source_dir/src" ]] && cp -rf "$api_source_dir/src" "$backup_dir/" [[ -d "$api_source_dir/src" ]] && cp -rf "$api_source_dir/src" "$backup_dir/"
# VERSION (commit hash) was copied from api_source_dir above; preserve as-is
# so a rollback restores the original commit marker. The version *string* is # Backup data directory (services.json, config.json, credentials, TOTP, etc.)
# already encoded in the backup dir name (${from_version}). # This is the critical gap — without this, user data is lost on every update.
if [[ -d "$api_source_dir/data" ]]; then
log "Backing up data directory: ${api_source_dir}/data/"
rm -rf "$backup_dir/data"
cp -rf "$api_source_dir/data" "$backup_dir/data"
fi
cleanup_old_backups cleanup_old_backups
@@ -212,6 +217,12 @@ main() {
rm -rf "$api_source_dir/src" rm -rf "$api_source_dir/src"
cp -rf "$backup_dir/src" "$api_source_dir/src" cp -rf "$backup_dir/src" "$api_source_dir/src"
fi fi
# Restore data directory (services.json, config.json, credentials, TOTP, etc.)
if [[ -d "$backup_dir/data" ]]; then
log "Restoring data directory from backup"
rm -rf "$api_source_dir/data"
cp -rf "$backup_dir/data" "$api_source_dir/data"
fi
write_result "false" "$version" "$(( $(date +%s) - start_time ))" "Docker build failed" write_result "false" "$version" "$(( $(date +%s) - start_time ))" "Docker build failed"
rm -f "${TRIGGER_FILE}.processing" rm -f "${TRIGGER_FILE}.processing"
@@ -237,6 +248,12 @@ main() {
rm -rf "$api_source_dir/src" rm -rf "$api_source_dir/src"
cp -rf "$backup_dir/src" "$api_source_dir/src" cp -rf "$backup_dir/src" "$api_source_dir/src"
fi fi
# Restore data directory
if [[ -d "$backup_dir/data" ]]; then
log "Restoring data directory from backup"
rm -rf "$api_source_dir/data"
cp -rf "$backup_dir/data" "$api_source_dir/data"
fi
docker compose build --quiet 2>&1 || docker-compose build --quiet 2>&1 || true docker compose build --quiet 2>&1 || docker-compose build --quiet 2>&1 || true
docker compose up -d 2>&1 || docker-compose up -d 2>&1 || true docker compose up -d 2>&1 || docker-compose up -d 2>&1 || true
@@ -267,6 +284,12 @@ main() {
rm -rf "$api_source_dir/src" rm -rf "$api_source_dir/src"
cp -rf "$backup_dir/src" "$api_source_dir/src" cp -rf "$backup_dir/src" "$api_source_dir/src"
fi fi
# Restore data directory
if [[ -d "$backup_dir/data" ]]; then
log "Restoring data directory from backup"
rm -rf "$api_source_dir/data"
cp -rf "$backup_dir/data" "$api_source_dir/data"
fi
docker compose build --quiet 2>&1 || docker-compose build --quiet 2>&1 || true docker compose build --quiet 2>&1 || docker-compose build --quiet 2>&1 || true
docker compose up -d 2>&1 || docker-compose up -d 2>&1 || true docker compose up -d 2>&1 || docker-compose up -d 2>&1 || true