← Back to archive

Repo of the Day

RayLabsHQ/gitea-mirror: Gitea Mirror auto-syncs GitHub repos to your self-hosted Gitea/Forgejo, with a sleek Web UI and easy Docker deployment.

Published: Sep 4, 2026

Open repository ↗

Gitea Mirror auto-syncs GitHub repos to your self-hosted Gitea/Forgejo, with a sleek Web UI and easy Docker deployment. - RayLabsHQ/gitea-mirror

Summary

Gitea Mirror is a TypeScript application that automatically mirrors GitHub repositories (public, private, and starred) into a self-hosted Gitea or Forgejo instance. It provides a web UI for configuration, scheduled syncing, Git LFS handling, and metadata mirroring (issues, labels, releases, wiki). It is distributed under AGPL-3.0 and runs on Docker, Proxmox LXC, Nix, or manually with Bun.

What it is useful for

  • Backing up GitHub work on your own infrastructure so data survives account deletion or bans. The cleanup step defaults to archive rather than deletion and is skipped if GitHub is unreachable.
  • Mirroring whole GitHub organizations with strategies like "Preserve Structure", "Single Organization", "Flat User", or "Mixed Mode".
  • GitHub Enterprise (GHES and GHEC with data residency) via GH_API_URL (for example https://api.TENANT.ghe.com) and a token issued by that instance.
  • Aggregating from additional sources (beta): GitLab and Gitea/Forgejo. GitHub to Gitea is the documented default; Forgejo behaves like Gitea, and using GitHub or GitLab as a destination uses push targets that are code-only.
  • Triggering syncs from CI using personal API keys sent in the x-api-key header against endpoints such as /api/sync/repository.
  • Single sign-on via OIDC (Google, Azure AD, Okta, Authentik) or reverse-proxy header auth (Authentik, Authelia, Traefik Forward Auth).

How engineers can use it

The documented quick start is:

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

The first signup becomes admin, and the GitHub token plus Gitea/Forgejo URL are entered through the web UI.

For unattended operation, set SCHEDULE_ENABLED=true with SCHEDULE_INTERVAL=3600 (or a cron expression like "0 2 * * *"), and GITEA_MIRROR_INTERVAL=8h (also accepts 5m, 30m, 1h, 24h, 1d, 7d). AUTO_IMPORT_REPOS=true imports new repos on startup, and CLEANUP_ORPHANED_REPO_ACTION=archive is the recommended default for orphaned mirrors.

For production, use docker-compose.yml, which supports custom CA certificates, multi-arch images from ghcr.io/raylabshq/gitea-mirror (AMD64/ARM64), and ENCRYPTION_SECRET for AES-256-GCM token encryption at rest. Proxmox LXC and NixOS module installations are also documented.

Documented limitations and caveats:

  • Pull requests are mirrored as enriched issues, not real PRs, because the Gitea/Forgejo API does not expose PR creation.
  • Destinations are pull mirrors and therefore read-only; commit on the source instead.
  • The configured interval must be greater than or equal to the destination's mirror.MIN_INTERVAL, or syncs can fail.
  • For first-time mirrors of large repositories with LFS or metadata, avoid short intervals; start at 1h–8h.
  • LFS requires LFS_START_SERVER = true and Git v2.1.2+ on the destination server.
  • Rotating the GitHub token does not always update stored mirror credentials on existing repos; the README recommends editing the repository's Mirror Settings in Gitea/Forgejo, or recreating the mirror.

See the README and docs/ENVIRONMENT_VARIABLES.md for the full configuration reference.