Configure GitHub Mirror
JJHub can mirror a repository to GitHub using a standalone worker modeled after Gitea push mirrors. The worker keeps a local bare cache, fetches refs from JJHub, and pushes them to GitHub withgit push --mirror.
This integration is intentionally mirror-only:
- It mirrors git refs and tags from JJHub to GitHub.
- It does not translate pull requests into landing requests.
- It does not sync issues, comments, or labels.
- It does not mirror wiki or documents sidecar repositories.
Before You Start
- Create the destination GitHub repository first.
- Make sure the configured GitHub token can read repository metadata and push to that repository.
- Generate a JJHub token that can fetch the source repository.
- Configure a JJHub webhook that sends
push,create, anddeleteevents to the mirror worker.
Required Configuration
JJHUB_SYNC_GITHUB_API_URL is used to verify that the destination repository exists before the worker starts mirroring. If you use GitHub Enterprise Server, set both JJHUB_SYNC_GITHUB_API_URL and JJHUB_SYNC_GITHUB_GIT_BASE_URL to the Enterprise host.
JJHUB_SYNC_CREDENTIAL_ENCRYPTION_KEY must remain stable across restarts. On first boot, the worker encrypts JJHUB_SYNC_GITHUB_TOKEN into the SQLite database under the github-mirror-write-token credential purpose. Keep JJHUB_SYNC_GITHUB_TOKEN set when bootstrapping the worker or rotating the mirror PAT.
Start the Worker
From the repository root, run an initial reconciliation when you start the service:Configure JJHub Webhooks
Send JJHub repository webhooks to the mirror worker:- URL:
https://your-worker.example/webhooks/jjhub - Secret:
JJHUB_SYNC_JJHUB_WEBHOOK_SECRET - Events:
push,create,delete
push covers new commits, create covers new bookmarks or tags, and delete removes refs from the destination on the next mirror pass.
Operational Behavior
The mirror worker uses this loop for each configured mapping:- Verify that the destination GitHub repository exists and is accessible.
- Load the GitHub mirror PAT from the encrypted SQLite credential store.
- Keep a local bare cache under
JJHUB_SYNC_MIRROR_CACHE_DIR. - Run
git fetch --prune --tagsfrom the JJHub remote. - Run
git push --mirrorto the GitHub remote. - Record the result in SQLite and retry on the next webhook or reconciliation interval if the push fails.
Troubleshooting
If the destination repository is missing, the worker fails with:git push --mirror failures are also rewritten to the same provisioning guidance so operators get a clear action instead of raw git transport noise.