#!/bin/bash # # Daily backup of Signet datadir and mining wallet to git (https://git.4nkweb.com/4nk/backup). # Runs save-signet-datadir-backup.sh and export-mining-wallet.sh, then pushes to the # backup repo. Keeps only 2 versions of the full chain (signet-datadir) and 2 of the # mining wallet export. # # Run via cron. Requires: docker (for backup scripts), git, passwordless push to backup repo. # Log: data/backup-to-git.log # # Author: 4NK Team # Date: 2026-02-04 set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" BACKUP_DIR="${PROJECT_DIR}/backups" LOG_FILE="${SCRIPT_DIR}/backup-to-git.log" BACKUP_REPO_URL="git@git.4nkweb.com:4nk/backup.git" BACKUP_GIT_WORKSPACE="${BACKUP_GIT_WORKSPACE:-$HOME/.4nk-backup-git}" KEEP_VERSIONS=2 SIGNET_SUBDIR="signet-datadir" WALLET_SUBDIR="mining-wallet" log() { echo "$(date -Iseconds) $*" | tee -a "$LOG_FILE"; } cd "$PROJECT_DIR" || exit 1 log "=== Backup to git cron ===" # 1. Run signet datadir backup if [ ! -x "${PROJECT_DIR}/save-signet-datadir-backup.sh" ]; then log "ERROR: save-signet-datadir-backup.sh not executable" exit 1 fi log "Running save-signet-datadir-backup.sh..." if ! ./save-signet-datadir-backup.sh >> "$LOG_FILE" 2>&1; then log "ERROR: save-signet-datadir-backup.sh failed" exit 1 fi log " signet datadir backup OK" # 2. Run mining wallet export if [ ! -x "${PROJECT_DIR}/export-mining-wallet.sh" ]; then log "ERROR: export-mining-wallet.sh not executable" exit 1 fi log "Running export-mining-wallet.sh..." if ! ./export-mining-wallet.sh >> "$LOG_FILE" 2>&1; then log "ERROR: export-mining-wallet.sh failed" exit 1 fi log " mining wallet export OK" # 3. Clone or pull backup repo if [ -d "$BACKUP_GIT_WORKSPACE/.git" ]; then log "Pulling backup repo..." (cd "$BACKUP_GIT_WORKSPACE" && git pull) >> "$LOG_FILE" 2>&1 || { log "WARN: git pull failed, continuing with local state" } else log "Cloning backup repo..." mkdir -p "$(dirname "$BACKUP_GIT_WORKSPACE")" if ! git clone "$BACKUP_REPO_URL" "$BACKUP_GIT_WORKSPACE" >> "$LOG_FILE" 2>&1; then log "ERROR: git clone failed. Create repo at $BACKUP_REPO_URL first." exit 1 fi fi mkdir -p "${BACKUP_GIT_WORKSPACE}/${SIGNET_SUBDIR}" mkdir -p "${BACKUP_GIT_WORKSPACE}/${WALLET_SUBDIR}" # 4. Copy latest signet-datadir backup (use real file, not symlink, for timestamped filename) LATEST_SIGNET=$(readlink -f "$BACKUP_DIR/signet-datadir-latest.tar.gz" 2>/dev/null) if [ -z "$LATEST_SIGNET" ] || [ ! -f "$LATEST_SIGNET" ]; then log "ERROR: no signet-datadir backup found in $BACKUP_DIR" exit 1 fi cp "$LATEST_SIGNET" "${BACKUP_GIT_WORKSPACE}/${SIGNET_SUBDIR}/$(basename "$LATEST_SIGNET")" log " Copied $(basename "$LATEST_SIGNET") to ${SIGNET_SUBDIR}/" # 5. Copy latest mining wallet export (use real file, not symlink, for timestamped filename) LATEST_WALLET=$(readlink -f "$BACKUP_DIR/mining-wallet-export-latest.json" 2>/dev/null) if [ -z "$LATEST_WALLET" ] || [ ! -f "$LATEST_WALLET" ]; then log "ERROR: no mining-wallet export found in $BACKUP_DIR" exit 1 fi cp "$LATEST_WALLET" "${BACKUP_GIT_WORKSPACE}/${WALLET_SUBDIR}/$(basename "$LATEST_WALLET")" log " Copied $(basename "$LATEST_WALLET") to ${WALLET_SUBDIR}/" # 6. Remove any *-latest* files from backup repo (only timestamped versions belong) rm -f "${BACKUP_GIT_WORKSPACE}/${SIGNET_SUBDIR}/signet-datadir-latest.tar.gz" rm -f "${BACKUP_GIT_WORKSPACE}/${WALLET_SUBDIR}/mining-wallet-export-latest.json" # 7. Prune signet-datadir: keep only KEEP_VERSIONS most recent (by filename timestamp) cd "${BACKUP_GIT_WORKSPACE}/${SIGNET_SUBDIR}" while [ "$(ls -1 signet-datadir-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-*.tar.gz 2>/dev/null | wc -l)" -gt "$KEEP_VERSIONS" ]; do OLDEST=$(ls signet-datadir-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-*.tar.gz 2>/dev/null | sort | head -1) rm -f "$OLDEST" log " Pruned signet: $OLDEST" done # 8. Prune mining-wallet: keep only KEEP_VERSIONS most recent (by filename timestamp) cd "${BACKUP_GIT_WORKSPACE}/${WALLET_SUBDIR}" while [ "$(ls -1 mining-wallet-export-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-*.json 2>/dev/null | wc -l)" -gt "$KEEP_VERSIONS" ]; do OLDEST=$(ls mining-wallet-export-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-*.json 2>/dev/null | sort | head -1) rm -f "$OLDEST" log " Pruned wallet: $OLDEST" done # 9. Commit and push cd "$BACKUP_GIT_WORKSPACE" if git status --porcelain | grep -q .; then git add "${SIGNET_SUBDIR}/" "${WALLET_SUBDIR}/" git commit -m "backup: signet datadir and mining wallet $(date -Iseconds)" >> "$LOG_FILE" 2>&1 log "Pushing to $BACKUP_REPO_URL..." if git push >> "$LOG_FILE" 2>&1; then log " Push OK" else log "ERROR: git push failed" exit 1 fi else log "No changes to commit (backups identical)" fi log "=== Done ===" tail -n 150 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"