#!/bin/bash # ───────────────────────────────────────────── # SPB Git — Personal Git Platform # ───────────────────────────────────────────── # Author : Simon-Pierre Boucher # Contact : contact@spboucher.ai # File : deploy/backup.sh # Purpose : Nightly backup — tar.zst of bare repos + data, keep 14 # License : MIT © Simon-Pierre Boucher # ───────────────────────────────────────────── # # Cron (crontab -e on m3u96a): # 15 3 * * * /bin/bash /deploy/backup.sh >> /spbgit/logs/backup.log 2>&1 # set -euo pipefail if [ "$(uname)" = "Darwin" ]; then PREFIX="$HOME/srv"; else PREFIX="/srv"; fi GIT_ROOT="${SPBGIT_GIT_ROOT:-$PREFIX/git}" DATA_DIR="${SPBGIT_DATA_DIR:-$PREFIX/spbgit/data}" BACKUP_DIR="${SPBGIT_BACKUP_DIR:-$PREFIX/spbgit/backups}" KEEP=14 mkdir -p "$BACKUP_DIR" STAMP="$(date +%Y%m%d-%H%M%S)" if tar --help 2>/dev/null | grep -q -- --zstd; then ARCHIVE="$BACKUP_DIR/spbgit-$STAMP.tar.zst" tar --zstd -cf "$ARCHIVE" -C "$(dirname "$GIT_ROOT")" "$(basename "$GIT_ROOT")" -C "$(dirname "$DATA_DIR")" "$(basename "$DATA_DIR")" else ARCHIVE="$BACKUP_DIR/spbgit-$STAMP.tar.gz" tar -czf "$ARCHIVE" -C "$(dirname "$GIT_ROOT")" "$(basename "$GIT_ROOT")" -C "$(dirname "$DATA_DIR")" "$(basename "$DATA_DIR")" fi # Rotate: keep the newest $KEEP archives. ls -1t "$BACKUP_DIR"/spbgit-*.tar.* 2>/dev/null | tail -n +$((KEEP + 1)) | while read -r old; do rm -f "$old" done SIZE="$(du -h "$ARCHIVE" | cut -f1 | tr -d ' ')" echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] backup ok: $ARCHIVE ($SIZE), $(ls -1 "$BACKUP_DIR"/spbgit-*.tar.* | wc -l | tr -d ' ') archives kept"