Backup GitHub Repositories with Gitea Mirror

Why homelabbers care

GitHub is great—right up until an outage, SSO change, or account lockout strands your projects. Gitea Mirror keeps a self-hosted copy of everything (history, metadata, LFS) so you can keep working locally. This playbook walks through the minimal Docker setup the project ships with and shows how to prove your backups actually work.

Requirements

Step-by-step

1. Clone the repo and start the stack

git clone https://github.com/RayLabsHQ/gitea-mirror.git
cd gitea-mirror
docker compose -f docker-compose.alt.yml up -d

The alt compose file ships with sane defaults for a single-node backup mirror. It stores data in ./data. To use a different path, edit the volume mapping (for example - /srv/gitea-mirror:/app/data).

Verify the containers:

docker compose -f docker-compose.alt.yml ps
docker compose -f docker-compose.alt.yml logs -f gitea-mirror

Wait for “Server started” before moving on.

2. Generate tokens and connect GitHub

  1. Create a GitHub personal access token (classic) with repo enabled and, inside the admin:org section, check read:org so the mirror can list organization repositories—leave write:org and admin:org unchecked.
  2. Log in to Gitea and create an access token for an admin/owner account with write:repository.
  3. Visit http://<host>:4321 and sign up—the first user becomes admin.
  4. Complete the setup wizard:
    • Paste the GitHub PAT and Gitea URL/token.
    • Choose which GitHub owners (user/org) to track.
    • Leave sync interval at the default 1 hour to start.

3. Stage your first backup job

On the dashboard:

  1. Click Mirror Repository for a small test project.
  2. Open Gitea and confirm the mirror appears with the right owner/org.
  3. In Configuration → Connections, open the Content & Data section to enable Mirror metadata and Git LFS if you rely on issues, wikis, or large assets.

For broader coverage, switch the organization strategy to Preserve structure so Gitea mirrors your GitHub org layout automatically.

4. Turn on automatic syncs and cleanup

Open Configuration → Automation in the web UI.

Automation tab in Gitea Mirror showing the automatic syncing controls for GitHub backups.

Configure the scheduler and cleanup policies from the Automation tab so GitHub mirrors stay fresh without manual cron jobs.

5. Prove the backup works

Treat the mirror like any other DR asset:

  1. Temporarily block outbound GitHub access on your machine.
  2. Clone from Gitea instead: git clone http://<gitea-host>/<owner>/<repo>.git.
  3. Confirm commit history, tags, releases, and issues exist.
  4. Remove the block and document the restore steps in your homelab wiki.

Health checks & monitoring

Hardening tips

Next steps

FAQ

Does Gitea Mirror copy issues, pull requests, releases, and LFS?

Yes. Enable Mirror metadata, Mirror releases, and Git LFS from Configuration → Connections → Content & Data. Pull requests are mirrored as enriched issues with linked branches and metadata.

How often should I sync GitHub backups?

Most homelabs pick 30–120 minutes. Faster schedules improve RPO but use more GitHub API quota; adjust by org/repo if only a few projects are critical.

Where are backups stored and how do I restore?

Repositories and the SQLite DB live under the data/ directory (or your configured volume). Restore by cloning from Gitea or by moving the volume to a fresh deployment and signing back in.