fuzzyworld-tools / files / server / truenas / mirror-all.sh
mirror-all.sh
| 1 | #!/bin/sh |
| 2 | # Backup mirror of every DreamHost repo, run on TrueNAS from a cron job (System → Advanced → Cron Jobs). |
| 3 | # |
| 4 | # mirror-all.sh /mnt/<pool>/git-mirrors |
| 5 | # |
| 6 | # DEST is a ZFS dataset (snapshotted by a periodic snapshot task). DEST/.ssh/id_ed25519 is a key that |
| 7 | # DreamHost only lets run server/mirror-only (fetch + list), so this box can read repos but never write. |
| 8 | # New repos are cloned with --mirror; existing ones get `remote update --prune`. Repos that disappear |
| 9 | # from DreamHost are kept here (this is a backup) and listed in the summary. Each mirror's config |
| 10 | # carries fuzzyworld.visibility, so a restore keeps the private/public marking. |
| 11 | set -u |
| 12 | DEST=${1:?usage: mirror-all.sh /mnt/<pool>/git-mirrors} |
| 13 | HOST=${FW_MIRROR_HOST:-fuzzygamer@iad1-shared-b7-30.dreamhost.com} |
| 14 | SSH="ssh -i $DEST/.ssh/id_ed25519 -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=$DEST/.ssh/known_hosts" |
| 15 | export GIT_SSH_COMMAND="$SSH" |
| 16 | LOG=$DEST/.logs/mirror-$(date -u +%Y%m%d).log |
| 17 | mkdir -p "$DEST/.logs" |
| 18 | exec 3>&2 # keep the cron job's stderr: failures are reported there too |
| 19 | exec >> "$LOG" 2>&1 |
| 20 | echo "== $(date -u '+%F %T UTC') mirror from $HOST" |
| 21 | |
| 22 | names=$($SSH "$HOST" list) || { echo "FAIL: cannot list repos on $HOST"; echo "git mirror: cannot list repos on $HOST (log: $LOG)" >&3; exit 1; } |
| 23 | ok=0; failed=0 |
| 24 | for name in $names; do |
| 25 | m="$DEST/$name.git" |
| 26 | if [ -d "$m" ]; then |
| 27 | git -C "$m" remote update --prune >/dev/null 2>&1 && r=0 || r=1 |
| 28 | else |
| 29 | git clone --quiet --mirror "$HOST:git/$name.git" "$m" && r=0 || r=1 |
| 30 | fi |
| 31 | if [ $r = 0 ]; then |
| 32 | v=$($SSH "$HOST" "visibility $name") && git -C "$m" config fuzzyworld.visibility "$v" |
| 33 | ok=$((ok + 1)) |
| 34 | else |
| 35 | echo "FAIL: $name"; failed=$((failed + 1)) |
| 36 | fi |
| 37 | done |
| 38 | gone="" |
| 39 | for m in "$DEST"/*.git; do |
| 40 | [ -d "$m" ] || continue |
| 41 | n=$(basename "$m" .git) |
| 42 | echo "$names" | tr ' ' '\n' | grep -qxF "$n" || gone="$gone $n" |
| 43 | done |
| 44 | echo "mirrored $ok, failed $failed${gone:+, kept but no longer on DreamHost:$gone}" |
| 45 | echo "== done $(date -u '+%F %T UTC')" |
| 46 | [ $failed = 0 ] || { echo "git mirror: $failed repo(s) failed (log: $LOG)" >&3; exit 1; } |