GitPreserver is a self-hosted, Docker-based git repository backup tool.
1.9K
![]()
A life preserver for your git repositories. Mirror your code, preserve your history, survive the flood.
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.
repo + read:user scopesgit clone https://github.com/RealDougEubanks/gitpreserver.git
cd gitpreserver
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
./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
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 | Status |
|---|---|
| Linux / macOS (Docker) | Ready |
| Synology DSM 7+ | Scaffolded |
| unRAID | Scaffolded |
All settings use environment variables prefixed GITPRESERVER_. Copy config/.env.example to .env — the file is fully commented.
| Variable | Default | Description |
|---|---|---|
GITPRESERVER_TOKEN | — | Personal Access Token (required) |
GITPRESERVER_USERNAME | — | Username or org to back up (required) |
GITPRESERVER_HOST_TYPE | github | github | bitbucket | gitlab | gitea |
GITPRESERVER_BACKUP_DIR | /backups | Local backup staging path |
GITPRESERVER_RETENTION_DAYS | 30 | Days to keep local snapshots (0 = keep forever) |
GITPRESERVER_RCLONE_REMOTE | — | rclone remote name (blank = local only) |
GITPRESERVER_ENCRYPT | false | Enable rclone crypt encryption |
GITPRESERVER_SCHEDULE | 0 2 * * 0 | Cron expression |
GITPRESERVER_DRY_RUN | false | No writes, no sync |
Full reference: docs/configuration.md
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.
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.
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
| Phase | Scope | Status |
|---|---|---|
| 1 | GitHub (user + org accounts) | In progress |
| 2 | Bitbucket and GitLab | Planned |
| 3 | Gitea, Forgejo, generic git hosts | Planned |
| — | Synology SPK | Scaffolded |
| — | unRAID Community Applications | Scaffolded |
| — | Multiple simultaneous destinations | Planned |
| — | Webhook notifications | Planned |
Bundles ghorg, gh, rclone, tini, jq, and git on a Debian base image. See CREDITS.md for full attribution.
Content type
Image
Digest
sha256:e97c6954c…
Size
127.4 MB
Last updated
3 months ago
docker pull dougeubanks/gitpreserver