Gitea Mirror Review: Automated GitHub to Gitea and Forgejo Sync
Gitea Mirror auto-syncs GitHub repos to your self-hosted Gitea/Forgejo, with a sleek Web UI and easy Docker deployment.
At a glance
- What is it?
- Gitea Mirror is a self-hosted TypeScript service for copying GitHub repositories and related data into Gitea or Forgejo on a schedule. Its Docker-first setup is approachable, while its optional provider and destination combinations remain beta features.
- Who is it for?
- Adopt Gitea Mirror when an operator needs recurring GitHub to Gitea or Forgejo replication through a self-hosted web service, especially when Git LFS, repository discovery, cleanup, or force-push controls matter. Do not treat beta source and destination combinations as equally mature as the default workflow.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why Gitea Mirror Exists for GitHub-to-Gitea Operators
Gitea Mirror addresses the gap between an active GitHub repository and a separate copy maintained on infrastructure controlled by the operator. It is aimed at administrators and engineering teams that self-host Gitea or Forgejo and want public, private, or starred GitHub repositories copied there without treating every synchronization as a manual task. The documented default direction is GitHub to Gitea, and the project describes that path as supported.
The service goes beyond copying branches. The README lists Git LFS, wiki content, releases, labels, milestones, issues, and pull requests represented as issues. It can mirror organizations, discover new GitHub repositories automatically, ignore selected repositories, and remove destination repositories deleted from GitHub. Scheduled intervals and activity logs make the service more relevant to an ongoing repository administration process than to a one-time export.
That distinction matters. A one-time repository transfer and a recurring mirror answer different operational questions. Gitea Mirror is aimed at the second case, where the destination must repeatedly approach the source state. It is therefore closer to a synchronization service than to a repository creation wizard.
The default path is narrower than the headline provider support suggests. GitLab, Codeberg, self-hosted instances, Gitea, and Forgejo can act as sources in beta combinations. GitHub and GitLab push targets are also marked beta. Issues and pull requests require a GitHub source according to the README. Operators should map their actual provider pairing to the project documentation before adopting it.
Gitea Mirror's Synchronization Model and Repository Scope
The documented repository keeps each mirrored repository associated with its configured source. For the default GitHub-to-Gitea workflow, it manages the source selection, destination, scheduling, and repository-level exclusions through the application. Organization mirroring can apply without configuring a source account when the organization is public, according to the README.
Metadata coverage depends on the provider path. The README states that gitlab.com, Codeberg, and self-hosted instances mirror code, tags, wiki, and LFS. Gitea and Forgejo sources add releases and their assets. Issues and pull requests require a GitHub source. This is an important boundary: connecting another source does not mean every metadata object becomes portable.
GitHub and GitLab push targets work differently again. According to the feature description, the application keeps a bare clone of each repository and pushes branches and tags to the target. It copies code only, and the target is overwritten during every synchronization. That is a replacement model rather than the fuller mirror feature set offered for Gitea and Forgejo destinations.
Force pushes introduce another operational boundary. The project documents protection modes that can create a backup on demand or block and await approval. This matters because Git synchronization can rewrite destination history. The existence of these controls does not mean every mirror event is non-destructive. Source rewrites, deletions, and target push behavior remain separate policies that administrators must review.
Docker Compose Installation and the First Administrative Login
The documented starting path uses the simplified Docker Compose file and a pre-built image. Clone the repository, enter its directory, and start the service with the exact command below:
git clone https://github.com/RayLabsHQ/gitea-mirror.git
cd gitea-mirror
docker compose -f docker-compose.alt.yml up -dThe service is then available at `http://localhost:4321`. The README says the first user to sign up becomes the administrator. GitHub and Gitea or Forgejo are configured through the web interface after startup, so the first real use begins with creating that administrative account and entering the source and destination credentials.
The simplified deployment stores data in the `./data` directory and maps user and group IDs. Optional `.env` values shown in the README are:
PORT=4321
PUID=1000
PGID=1000
BETTER_AUTH_SECRET=your-secret-key-change-this-in-productionThe README states that sensible defaults are available and that `BETTER_AUTH_SECRET` is generated if it is not set. The sample value should not be retained for a production deployment, as its own text says to change it. No additional setup command is documented for this quick path.
The reader should see the application interface at port 4321 after the containers start. If it sits behind Nginx, Caddy, Traefik, or another reverse proxy, `.env.example` says the external URL must be reflected in `BETTER_AUTH_URL`, `PUBLIC_BETTER_AUTH_URL`, and `BETTER_AUTH_TRUSTED_ORIGINS`; otherwise sign-in can fail with `invalid origin` errors.
Full Compose Deployment versus the Simplified Web-Configured Setup
The repository also provides `docker-compose.yml` for a fuller deployment. The README associates it with environment-based configuration, custom CA certificates, advanced mirror settings, forks, wiki, issues, and multi-registry support. Its documented start command is:
docker compose up -dThe complete Compose file maps host port 4321 to container port 4321, stores the application database in a named volume at `/app/data`, and sets production mode. It can pull an image from the project registry or build from the repository. The image expression defaults to `ghcr.io/raylabshq/gitea-mirror:latest`, although operators can select a tag through `DOCKER_TAG`.
The database configuration differs slightly by source. The full Compose file uses `DATABASE_URL=file:data/gitea-mirror.db`, while `.env.example` documents `DATABASE_URL=sqlite://data/gitea-mirror.db`. The repository points operators to `.env.example` and `docs/ENVIRONMENT_VARIABLES.md` for the complete set rather than claiming that the abbreviated Compose excerpt covers every option.
The pre-built image can also be pulled directly:
docker pull ghcr.io/raylabshq/gitea-mirror:latestFor evaluation, `docker-compose.alt.yml` is the clearer choice because the README presents it as web-configured and minimal. A production operator may instead choose the full Compose file when environment-driven provisioning, certificate mounting, or the advanced settings in its documentation are part of the deployment plan.
Operational Limits of Scheduled Mirroring and Beta Provider Paths
The first operational limitation is provider support. GitHub to Gitea is the supported default, but the README labels other sources and destinations beta. Feature coverage also changes by direction. A GitHub-to-Gitea mirror can include issues and pull requests represented as issues, while push targets retain a bare copy containing code, branches, and tags. Treating all supported combinations as equivalent would produce incorrect expectations.
The second limitation concerns destructive synchronization. Repository cleanup can remove a destination when the source repository has been deleted. Force-push protection offers backup-on-demand and block-and-approve modes, but those are configurable controls rather than proof that all historical changes are preserved. An operator who needs an immutable archive should not assume that a conventional repository mirror provides that retention model.
The third limitation concerns external endpoints. GitHub Enterprise support relies on settings including `GH_API_URL`, while reverse proxy deployment has explicit authentication URL requirements. Self-signed destinations need the custom CA options in the full Compose setup. These are normal integration constraints, but they make initial configuration more involved than a local GitHub-to-Gitea pair.
The README also documents notifications through ntfy, Apprise, Gotify, or webhooks with signed payloads. That helps expose sync events, but it does not replace destination-side access controls, source-token review, or database backup. The project is a mirroring control plane, not a complete backup and disaster-recovery system by itself.
Gitea Mirror Compared with a One-Off Repository Import
The practical alternative is a one-off repository import when the requirement is simply to place selected repositories on a self-hosted service. That approach does not provide Gitea Mirror's recurring schedule, automatic discovery, organization handling, activity dashboard, deletion cleanup, or force-push approval modes. It is narrower by design because it does not attempt to keep the destination synchronized over time.
Gitea Mirror is the relevant choice when repository state must converge repeatedly. It keeps source identity attached to each repository and manages the ongoing relationship. Its cost is an additional long-running service, source and destination credentials, a SQLite database, scheduled jobs, and configuration for proxy URLs or private certificate authorities.
The default GitHub-to-Gitea route should also be compared against GitHub or GitLab push targets on the basis of required content, not merely connectivity. Gitea and Forgejo destinations support the broader mirroring feature set described in the README. GitHub and GitLab targets retain a bare clone with branches and tags, copy code only, and overwrite the target on each sync. An organization that needs full metadata preservation should not select a code-only push target merely because it supports pushes.
For a small set of repositories that rarely changes, a one-off import can avoid this operational surface. For broad GitHub organization replication with recurring updates, Gitea Mirror provides the mechanisms the basic import does not.
Upgrade Work, Release Cadence, and AGPL-3.0 Obligations
The repository is not archived. Its last push was on 2026-10-15, and release `v3.40.5` was published on 2026-10-15. Releases also include `v3.40.4` from 2026-10-14 and `v3.40.3` from 2026-09-26. This is recent release activity, but operators still need to read `CHANGELOG.md` before changing image tags because the README does not summarize migration requirements for every version.
Containerized operation shifts some upgrade work into Docker image changes, Compose configuration, persistent data handling, and application migrations. The repository includes database commands such as `bun run db:migrate`, `bun run db:check`, and `bun run startup-recovery`. It also uses `bun install --frozen-lockfile` during the image build, which keeps the build tied to the committed lockfile rather than resolving a new dependency graph at build time.
Before upgrading, check the release notes for database and configuration changes, back up the persisted `data` directory or volume, and review changes to authentication and reverse-proxy settings. The repository's scripts for checking or repairing the database are relevant when an upgrade fails, but the README excerpt does not prescribe a blanket recovery procedure.
The project uses the `AGPL-3.0` license. Network deployment can trigger source-code obligations under that license, depending on how the software is modified and offered to users. This is not legal advice. Organizations planning to modify the application should review the repository `LICENSE` and their distribution model before deployment.
Editorial conclusion
Adopt Gitea Mirror when an operator needs recurring GitHub to Gitea or Forgejo replication through a self-hosted web service, especially when Git LFS, repository discovery, cleanup, or force-push controls matter. Do not treat beta source and destination combinations as equally mature as the default workflow. Verify token scope, expected metadata coverage, overwrite behavior for push targets, persistent database storage, reverse-proxy authentication settings, and the meaning of your force-push policy before enabling unattended synchronization.
Frequently asked questions
How do I install Gitea Mirror with Docker Compose?
Clone the repository and run `docker compose -f docker-compose.alt.yml up -d`. The README directs users to `http://localhost:4321`, where the first user to sign up becomes the administrator.
Which repository data does Gitea Mirror copy?
The documented GitHub mirror includes code and can include Git LFS, issues, pull requests as issues, labels, milestones, releases, and wiki content. GitHub or GitLab push targets are different: they retain a bare clone with branches and tags, copy code only, and overwrite the target during each sync.
Are GitLab and Forgejo sources supported by Gitea Mirror?
The README lists GitLab and Gitea or Forgejo sources as beta. GitHub to Gitea is the supported default, and metadata coverage varies by source and destination.
Why does Gitea Mirror sign-in fail behind a reverse proxy?
The `.env.example` documentation says the reverse proxy's external URL must be configured through `BETTER_AUTH_URL`, `PUBLIC_BETTER_AUTH_URL`, and `BETTER_AUTH_TRUSTED_ORIGINS`. Without those settings, sign-in can fail with `invalid origin` errors.
What license does Gitea Mirror use?
The repository declares the `AGPL-3.0` license. Operators modifying or offering the software over a network should review the repository `LICENSE` for their applicable obligations.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/raylabshq-gitea-mirror)Was this useful?