Forgejo Repository Mirroring: Setup, Trade‑offs, and a Quick Verification Walk‑through
Learn how to set up Forgejo’s native repository mirroring, trigger syncs manually, understand its limits with large repos and divergent histories, and verify the mirror with a quick clone‑and‑compare.
11 Mar 2026, 09:36 UTC

Why mirroring matters
Teams often keep a canonical Git repository on one Forgejo instance and need a read‑only copy on another server for CI, backup, or geographic latency reasons. Forgejo’s native mirroring feature handles the push/pull cycle automatically, preserving branch protection rules and full commit history without requiring external tooling.
Configuring a mirror in the UI
- Open the repository settings and select Mirroring.
- Click Add Mirror and fill in the target URL (e.g.
https://mirror.example.com/org/project.git). - Choose authentication: personal access token, SSH key, or basic auth. The UI stores the credential in plain text in the repository config file.
- Set the sync interval (default 8 h) or disable automatic runs if you prefer manual triggers.
- Enable Read‑only to prevent accidental pushes to the mirror.
The resulting snippet in repo.git/config looks like:
[remote "mirror"]
url = https://token:@mirror.example.com/org/project.git
fetch = +refs/heads/*:refs/heads/*
mirror = true
interval = 8h
readonly = true
Triggering a sync from the command line
For immediate verification or to recover from a missed schedule, run the admin CLI on the Forgejo host (typically as the forgejo system user or root):
# forgejo-admin mirror sync <repo-id>
Where to run: the server that hosts Forgejo.
Permissions: the executing user must have read/write access to Forgejo’s data directory and the admin binary.
Placeholders: replace <repo-id> with the numeric repository identifier (visible in the URL of the repo settings page).
Expected check: the command prints a job ID; tail the log file /var/log/forgejo/mirror.log (or the configured log path) for a line containing sync succeeded.
Risks: a full git fetch --all && git push --mirror runs for each mirror; on large repos this can spike CPU, memory, and network I/O.
Limitation: conflict handling and large repos
Forgejo does not attempt automatic merge conflict resolution. If the source and mirror diverge (e.g., force‑pushed history on the source), the next sync will fail and the job log will show a non‑fast‑forward error. Manual intervention—typically a forced push from the source or a re‑initialisation of the mirror—is required. Additionally, repositories larger than a few gigabytes may hit the default Git HTTP buffer limits; consider raising http.postBuffer on the mirror side or using SSH with a larger git config --global core.compression setting.
Verify the mirror
- Clone the mirrored repository on a separate machine:
git clone https://mirror.example.com/org/project.git. - Run
git log --graph --all --oneline -20and compare the latest commit hashes with the source repo. - Check that protected branches (e.g.,
main) still show the same protection status in the Forgejo UI of the mirror.
If the histories match and branch protections are intact, the mirror is healthy. Schedule periodic checks (e.g., a cron job that runs the CLI sync and alerts on non‑zero exit codes) to catch drift early.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.