Sign inSign up

dougeubanks/gitpreserver

By dougeubanks

•Updated 4 months ago

GitPreserver is a self-hosted, Docker-based git repository backup tool.

Image
Developer tools
1

2.4K

dougeubanks/gitpreserver repository overview

⁠GitPreserver

GitPreserver

A life preserver for your git repositories. Mirror your code, preserve your history, survive the flood.

License: MIT Docker Pulls GitHub release shellcheck


GitPreserver mirror-clones every repository in your git account — all branches, all tags, full history — and syncs encrypted backups to any rclone-supported destination on a schedule you control. It runs on any Linux/Docker host, Synology NAS, or unRAID server, and requires no persistent service.

GitHub suffered over 257 incidents between May 2025 and April 2026. If you've invested weeks building CI/CD pipelines, unit tests, and deployment configs across dozens of repositories, you need a safety net that doesn't depend on any single platform staying available.


⁠What it does

  • Mirror-clones all repos for a configured account (all branches, all tags, full ref history) using ghorg⁠
  • Exports metadata — issues, pull requests, and releases — as JSON sidecar files alongside the clones
  • Syncs everything to any rclone-supported destination⁠: Backblaze B2, AWS S3, Cloudflare R2, Google Drive, OneDrive, MEGA, SMB, NFS, local filesystem, and 70+ others
  • Encrypts backups at rest via rclone crypt⁠ (AES-256-CTR, optional)
  • Runs on a schedule via cron — no persistent daemon required
  • Supports GitHub (Phase 1), with Bitbucket, GitLab, Gitea, and generic git hosts on the roadmap

⁠What it doesn't do

  • Back up GitHub Actions secrets (not API-exportable — document them in a password manager)
  • Run a local git server
  • Replace your git host

⁠Quick start

⁠Prerequisites
  • Docker and Docker Compose
  • A GitHub Personal Access Token — fine-grained (recommended) with Contents, Metadata, Issues, and Pull requests set to Read, or classic with repo + read:user scopes
  • An rclone-supported storage destination (or use local-only mode)
⁠1. Clone the repo
git clone https://github.com/RealDougEubanks/gitpreserver.git
cd gitpreserver
⁠2. Configure
cp config/.env.example .env

Edit .env and set at minimum:

GITPRESERVER_TOKEN=github_pat_your_token_here
GITPRESERVER_USERNAME=your_github_username

To sync offsite, set GITPRESERVER_RCLONE_REMOTE to a remote configured in rclone/rclone.conf.

The container runs as a non-root user (UID/GID 1000 by default). If your host user differs, set PUID and PGID in .env:

echo "PUID=$(id -u)" >> .env
echo "PGID=$(id -g)" >> .env
⁠3. Run a backup
./run-backup.sh                                  # full run using .env
./run-backup.sh /mnt/backup/github --no-sync     # local-only, no rclone
./run-backup.sh --dry-run                        # validate config, write nothing
⁠4. Schedule it
crontab -e

Add a line — by default, Sundays at 2 AM:

0 2 * * 0  cd /opt/gitpreserver && ./run-backup.sh >> /var/log/gitpreserver.log 2>&1

⁠Platform support

PlatformStatus
Linux / macOS (Docker)Ready
Synology DSM 7+Scaffolded
unRAIDScaffolded

⁠Configuration

All settings use environment variables prefixed GITPRESERVER_. Copy config/.env.example to .env — the file is fully commented.

VariableDefaultDescription
GITPRESERVER_TOKEN—Personal Access Token (required)
GITPRESERVER_USERNAME—Username or org to back up (required)
GITPRESERVER_HOST_TYPEgithubgithub | bitbucket | gitlab | gitea
GITPRESERVER_BACKUP_DIR/backupsLocal backup staging path
GITPRESERVER_RETENTION_DAYS30Days to keep local snapshots (0 = keep forever)
GITPRESERVER_RCLONE_REMOTE—rclone remote name (blank = local only)
GITPRESERVER_ENCRYPTfalseEnable rclone crypt encryption
GITPRESERVER_SCHEDULE0 2 * * 0Cron expression
GITPRESERVER_DRY_RUNfalseNo writes, no sync

Full reference: docs/configuration.md⁠


⁠Storage backends

Any rclone remote works — configure it in rclone/rclone.conf and point GITPRESERVER_RCLONE_REMOTE at its name.

Recommended default: Backblaze B2 (~$0.006/GB/month, no egress fees to rclone).

See docs/storage-backends.md⁠ for setup guides covering B2, S3, MEGA, Google Drive, SMB/NFS, and more.


⁠Encryption

Set GITPRESERVER_ENCRYPT=true and configure a crypt remote in rclone.conf. Backups are encrypted with AES-256-CTR via rclone crypt. Store your passphrase in a password manager — there is no key escrow.

See docs/encryption.md⁠.


⁠Restoring

Mirrors are standard bare git repos. To push one to a new remote:

cd backups/2026-05-21/repos/your-repo.git
git remote add new-origin https://gitlab.com/YOUR_USERNAME/your-repo.git
git push --mirror new-origin

Issues, PRs, and releases are JSON files in backups/YYYY-MM-DD/metadata/.

Full restore guide: docs/restoring.md⁠


⁠Roadmap

PhaseScopeStatus
1GitHub (user + org accounts)In progress
2Bitbucket and GitLabPlanned
3Gitea, Forgejo, generic git hostsPlanned
—Synology SPKScaffolded
—unRAID Community ApplicationsScaffolded
—Multiple simultaneous destinationsPlanned
—Webhook notificationsPlanned

⁠Credits

Bundles ghorg⁠, gh⁠, rclone⁠, tini⁠, jq⁠, and git⁠ on a Debian base image. See CREDITS.md⁠ for full attribution.


⁠License

MIT⁠

Tag summary

Content type

Image

Digest

sha256:e97c6954c…

Size

127.4 MB

Last updated

4 months ago

docker pull dougeubanks/gitpreserver