Skip to content

Instantly share code, notes, and snippets.

@olange
Created October 5, 2025 13:14
Show Gist options
  • Save olange/ba458c1ab7e8a993b0d435b9eacfd72c to your computer and use it in GitHub Desktop.
Save olange/ba458c1ab7e8a993b0d435b9eacfd72c to your computer and use it in GitHub Desktop.
GitHub to Synology DSM7 scheduled mirror backup script (aka scheduled sync)
#!/bin/bash
# GitHub repo + wiki mirror backup for Synology NAS
set -euo pipefail
# --- CONFIG ---
GITHUB_USER="${1:-${GITHUB_USER:-}}"
if [ -z "${GITHUB_USER}" ]; then
echo "Usage: $0 <github-user-or-org>"
echo " or: GITHUB_USER=‹github-user-or-org› $0"
echo
echo "Example:"
echo " $0 ‹your-orgname›"
echo " GITHUB_USER=‹your-username› $0"
exit 1
fi
BACKUP_ROOT="/volume1/synced/GitHub"
BACKUP_DIR="$BACKUP_ROOT/$GITHUB_USER"
TIMESTAMP=$(date "+%Y%m%d-%H%M%S")
LOG_FILE="$BACKUP_ROOT/gh-backup-${GITHUB_USER}-${TIMESTAMP}.log"
mkdir -p "$BACKUP_DIR"
log() {
local msg="$1"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $msg" | tee -a "$LOG_FILE"
}
log "Starting GitHub backup for user/org: $GITHUB_USER"
# --- BACKUP LOOP ---
gh repo list "$GITHUB_USER" --limit 500 --json name,sshUrl -q '.[] | [.name, .sshUrl] | @tsv' |
while IFS=$'\t' read -r NAME SSHURL; do
REPO_DIR="$BACKUP_DIR/$NAME.git"
# --- main repository ---
if [ -d "$REPO_DIR" ]; then
log "Updating $NAME..."
git -C "$REPO_DIR" remote update --prune >>"$LOG_FILE" 2>&1 || log "⚠️ Failed to update $NAME"
else
log "Cloning new repo $NAME..."
git clone --mirror "$SSHURL" "$REPO_DIR" >>"$LOG_FILE" 2>&1 || log "⚠️ Failed to clone $NAME"
fi
# --- wiki repository ---
WIKI_SSHURL="${SSHURL%.git}.wiki.git"
WIKI_REPO_DIR="$BACKUP_DIR/${NAME}.wiki.git"
if git ls-remote "$WIKI_SSHURL" &>/dev/null; then
if [ -d "$WIKI_REPO_DIR" ]; then
log "Updating wiki for $NAME..."
git -C "$WIKI_REPO_DIR" remote update --prune >>"$LOG_FILE" 2>&1 || log "⚠️ Failed to update wiki for $NAME"
else
log "Cloning wiki for $NAME..."
git clone --mirror "$WIKI_SSHURL" "$WIKI_REPO_DIR" >>"$LOG_FILE" 2>&1 || log "⚠️ Failed to clone wiki for $NAME"
fi
else
log "No wiki found for $NAME"
fi
done
log "GitHub backup finished successfully."
@olange
Copy link
Author

olange commented Oct 5, 2025

Setup instructions

  1. Prerequisites on your Synology
    • Install Git: Package Center → Git Server
    • Enable SSH access: Control Panel → Terminal & SNMP → Enable SSH service
    • Enable User Home Service: Control Panel → User & Group → Advanced (to have a /var/services/homes/‹username›)
    • SSH into your Synology NAS
    • Generate and register a deploy key or token: ssh-keygen -t ed25519 -C "synology-backup" (creates files ~/.ssh/id_ed25519[.pub])
    • Add that key as a deploy key or to your GitHub account: GitHub › Settings › SSH keys
    • Register the GitHub public key as known SSH host with ssh -T [email protected] and verify that the public key presented is among GitHub's SSH key fingerprints (will create the ~/.ssh/known_hosts file)
    • Install GitHub CLI (gh) to automate repository listing: wget gh_2.81.0_linux_amd64.tar.gz installed to /var/packages/gh_2.81.0_linux_amd64 and symlinked to /usr/local/bin (pick the correct architecture for your NAS, mine is x86_64/amd64)
    • Authenticate to GitHub from NAS: gh auth login
  2. Install the backup script
    • Create a synced volume for all things synced with the Cloud: Control Panel → Shared folders
    • Create a /volume1/synced/GitHub parent folder for syncing GitHub repos
    • Copy script into /volume1/synced/GitHub/gh-backup.sh and chmod ug+x gh-backup.sh
  3. Schedule the backup: Control Panel → Task Scheduler → Create → Scheduled Task → User-defined script
    • gh-backup.sh ‹org1› every day at 04h04, send e-mail notification if script fails
    • gh-backup.sh ‹org2› every day at 04h08, idem
    • gh-backup.sh ‹user› every day at 04h12, idem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment