Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

11 Commits

Folders and files

Repository files navigation

github-backup

English | Русский

Painless + fast + simple (that's the whole point) regular backup of all your GitHub repos to any VPS.

Requires github.com/gabrie30/ghorg in /usr/local/bin, plus git, jq and curl.

Each account needs a classic personal access token with the repo and read:org scopes: repo for private repos, read:org to list organizations.

Installation

cp accounts.env.example accounts.env
chmod 600 /root/github-backup/accounts.env
chmod 700 /root/github-backup/github-backup.sh

/etc/systemd/system/github-backup.service:

[Unit]
Description=Mirror GitHub accounts and their organizations
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/root/github-backup/github-backup.sh

/etc/systemd/system/github-backup.timer:

[Unit]
Description=Run github-backup daily

[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1h

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now github-backup.timer
journalctl -u github-backup.service -f

Deleted repositories (trash)

Repos deleted on GitHub are moved to /data/_trash/... with a timestamp:

  • user: /data/<account>/repos/<repo> → /data/_trash/<account>/repos/<repo>__<UTC>
  • org: /data/<account>/orgs/<org>/<repo> → /data/_trash/<account>/orgs/<org>/<repo>__<UTC>

Deletion is detected through the GitHub API (the source of truth), not through ghorg --prune.

If the API request fails or returns an empty list, the move is skipped (protection against false removal when a token or the network fails) – look for trash skipped lines in the logs.

Checking backups

Contents – what was last backed up and when (sorted by freshness):

./backup-status.sh            # or: ./backup-status.sh /data

Columns: LAST FETCH (when the mirror was last synced), LAST COMMIT (date of the newest commit in the mirror), REPO. The top rows are the most recent. At the bottom: the number of mirrors in trash and the total size.

Runs – whether the timer fired and with what result (systemd):

systemctl list-timers github-backup.timer --no-pager   # next / last run
systemctl status github-backup.service --no-pager      # result of the last run
journalctl -u github-backup.service -n 100 --no-pager  # full log of the last run
journalctl -u github-backup.service -f                 # follow live

Alerts

A failed ghorg run or a failed GitHub API request is logged as FAIL:. The run still processes everything else, then exits non-zero, so systemctl status shows the service as failed. An empty remote list only logs trash skipped and is not a failure.

Optionally, report each run to an Uptime Kuma push monitor:

  1. Create a monitor of type Push with a heartbeat interval of 93600 seconds (26 hours: the daily timer can drift by up to an hour).
  2. Add its URL to accounts.env:
KUMA_PUSH_URL="https://kuma.example.com/api/push/<token>"

A clean run sends up, a run with failures sends down. A missing heartbeat also turns the monitor down, which covers a dead timer or host.


banochkin.com DAO 🏴‍☠️

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages