Gitea is a self-hosted Git forge with repositories, issues, pull requests, a package registry and Actions-compatible CI, shipped as one static binary or one container. It is the original project that Forgejo forked from, and it remains MIT licensed.
Our verdict on Gitea#
Gitea is excellent software with an ownership problem. Technically it is what it has always been: one binary, 150 MB idle, v1.27.x as of August 2026, and a UI that most GitHub refugees can use without training. The catch is governance. The domains and trademark belong to Gitea Ltd, a for-profit company, contributors sign a copyright assignment, and the subsidiary CommitGo sells a proprietary Gitea Enterprise built on the MIT core. None of that is illegitimate and CommitGo has kept contributing upstream, but MIT means nothing stops the good parts moving behind the paywall later. If you are starting fresh today, run Forgejo instead: the same product under nonprofit control and a copyleft licence. Choose Gitea when your organization genuinely cannot take GPL-3.0 code, when you want the commercial support contract, or when you are already running it happily, in which case there is no urgency to move.
Who Gitea is for#
Choose it if
- Shops with a legal policy that permits permissive licences only and treats GPL-3.0 as a blocker.
- Teams that want a paid support contract and an enterprise upgrade path from the same vendor.
- Existing Gitea operators on v1.23 or newer, where migrating to Forgejo is no longer a supported one-step move.
- Anyone embedding a forge inside a commercial appliance, where MIT terms are simply cheaper to comply with.
Look elsewhere if
- You are choosing a forge for the first time and care who controls the project; Forgejo is the same thing under nonprofit governance.
- You want a guarantee that features cannot migrate into a paid edition, which MIT plus a CLA cannot give you.
- You need heavyweight CI, merge queues or built-in security scanning, which means GitLab or GitHub rather than either fork.
What running it actually looks like#
One container mounting /data, or a single binary plus a systemd unit and an app.ini. Official builds cover linux amd64 and arm64, plus macOS, Windows and FreeBSD, all with SQLite, MySQL and PostgreSQL support compiled in. Set USER_UID and USER_GID to the owner of the data directory before first boot. Port 3000 is HTTP; SSH clones need either the container's SSH daemon on a published port or a host sshd shim. The first-run web installer writes app.ini and mints the admin account, and it is unauthenticated until completed, so do not expose it early. Upgrades are pull and restart, with schema migrations applied on startup. Enabling Actions means running act_runner as a second service with a registration token, and giving it a Docker socket.
Resource profile#
- Memory
- 150 MB idle, around 450 MB in ordinary use. Small Go resident set; growth comes from the bleve issue and code indexers and from concurrent git pack operations, not from how many users exist.
- CPU and acceleration
- Near idle at rest. Clones, pushes and mirror syncs pin a core briefly; Actions runners are the real load and belong on a different host.
- Storage growth
- Repository data dominates and grows with your commit habits. LFS objects and the package registry accumulate quietly and neither is pruned by default.
- Operational load
- 2 of 5, Light. One container, one volume, SQLite unless you choose otherwise, self-applying schema migrations on restart. Occasional config edits, upgrade notes worth skimming on a major bump, and otherwise it is quiet.
Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.
Data and backup surface#
Under /data you need gitea/conf/app.ini, git/repositories, gitea/gitea.db on SQLite, and gitea/lfs, gitea/avatars and gitea/attachments. The documented tool is gitea dump, which produces a zip holding app.ini, the custom/ tree, the data directory, the repository directory and an SQL dump of the database. The docs are explicit that the instance must be shut down during the dump to avoid the database and the repository files diverging mid-copy. Logs in the archive are not needed for recovery. gitea/indexers and gitea/queues are regenerable and can be excluded. After restoring into a different path, regenerate repository hooks or every push fails.
Derived backup shape
SQLite backup. sqlite3 <db> ".backup out.db" while running, or stop the container and copy. A live cp of a WAL-mode SQLite file can restore corrupt.
Traps and surprises#
Contributions carry a copyright assignment
Gitea requires a contributor agreement that assigns rights to the project entity, which is what makes a proprietary Gitea Enterprise possible alongside the MIT core. This is the practical difference from Forgejo, which does not. It does not affect you as an operator, but it does mean the MIT licence is a floor on the current code, not a promise about future features.
Switching database engines later is barely tested
The backup and restore documentation warns that converting an existing instance from SQLite to PostgreSQL or MySQL is not well tested and recommends choosing the right engine at install time. People routinely start on SQLite for a trial, then find the conversion path is a dump, a hand-edited SQL file and a lot of hope. Pick PostgreSQL up front if you expect more than a handful of active users.
Clone URLs come from config, not from Docker
The SSH clone URL in the web UI is built from SSH_DOMAIN and SSH_PORT in app.ini. Publish host port 222 to container port 22 without setting SSH_PORT = 222 and every URL the UI hands out points at a closed port. The same applies to ROOT_URL behind a reverse proxy: get it wrong and webhooks, OAuth redirects and avatar links all break in different ways.
Git hooks contain absolute paths
Each repository's hooks reference the absolute path of the Gitea binary and its config file. Move the installation, migrate from a distro package to a container, or restore a dump into a different directory layout, and pushes fail with a hook error while the web UI looks perfectly healthy. Run the admin hook regeneration command after any move or restore.
Actions runners want a Docker socket
Gitea Actions needs act_runner registered against the instance, and the common configuration hands it the host Docker socket so it can start job containers. That is root-equivalent access to the host for anyone who can push a workflow file. On a shared forge, run the runner on a separate machine or inside a rootless or nested Docker setup rather than on the box hosting your repositories.
Specifications#
- Category
- Git forges and developer infrastructure
- Licence
- MIT (Permissive)
- Written in
- Go / TypeScript
- First release
- 2016
- Maturity
- Mature
- Datastore
- SQLite (default), PostgreSQL or MySQL optional
- Default ports
3000,22- Ships as
- docker, native binary, helm chart
- arm64 builds
- Yes
- Identity
- Native OIDC. OAuth2/OIDC and LDAP are built-in authentication sources configured from the admin panel, with optional auto-provisioning of accounts.
- Replaces
- GitHub, Bitbucket Server, GitLab, Gogs
- Project site
- about.gitea.com
- Source
- github.com/go-gitea/gitea
- Documentation
- docs.gitea.com
Alternatives to Gitea#
Everything else in git forges and developer infrastructure, closest in operational weight first.
| Tool | Ops load | Idle RAM | Licence |
|---|---|---|---|
| Forgejo | 2, Light | 150 MB | GPL-3.0-or-later |
| Woodpecker CI | 2, Light | 90 MB | Apache-2.0 |
| code-server | 2, Light | 200 MB | MIT |
| GitLab CE | 4, Heavy | 4096 MB | MIT |
| Harbor | 4, Heavy | 2500 MB | Apache-2.0 |
Where Gitea comes up elsewhere#
Migration guides
Sources#
Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.