Gitea jumps from 1.27 to 28.0 and tightens repository authorization
Gitea drops the historical ‘1.’ prefix and ships 28.0.0, a major release that changes Git egress routing and fixes several authorization flaws. An upgrade to read before you deploy, not to apply blind.
September 30, 2026. Gitea ships 28.0.0, dropping the historical “1.” prefix from its versioning: the release that would have been 1.28.0 becomes 28.0.0, the way Java went from 1.8 to 9 in 2017. September 30, 2026. The major bump carries five breaking changes, including routing Git network operations through an internal proxy with new egress rules. September 30, 2026. The changelog lists several security fixes, but Gitea is withholding details for about a week to give people time to upgrade. Why it matters: if you self-host Gitea and rely on its Actions runner, this is an upgrade to read before you deploy, not to apply in one go.
A version number that actually says something
The jump from 1.27.3 to 28.0.0 is not cosmetic: it is a versioning decision. Gitea strips the historical “1.” that no longer carried information, exactly as Java did when it moved from 1.8 to 9. The practical consequence is immediate: a major version signals breaking changes, and this one has five. An administrator who upgrades without reading them is heading toward an instance that either fails to start or silently changes behavior.
The list of breaking changes deserves careful reading, because it touches configuration points many instances have already customized. The first concerns Git network operations — migrations, mirrors, and other outbound calls — which now route through an internal proxy that applies egress settings to direct connections (change #39426). The “external” preset is removed, and for a deny-by-default policy you must now set EGRESS_MODE = strict and explicitly list the allowed hosts. In strict mode, an entry without a port only allows ports 80 and 443. In lax mode, ALLOWED_HOST_LIST no longer restricts public hosts, and IP address entries no longer accept wildcards — * is no longer a valid entry. The old ALLOWED_DOMAINS, BLOCKED_DOMAINS, and ALLOW_LOCALNETWORKS keys are deprecated in favor of ALLOWED_HOST_LIST and BLOCKED_HOST_LIST, and an invalid BLOCKED_HOST_LIST entry now stops Gitea from starting.
Five breakages, and their consequences
The second breaking change hits Actions. Completed runs are now deleted after 400 days by default, together with their jobs, logs, and artifacts, through a new cleanup_action_runs cron task (#38855). To keep everything, set [actions] RUN_RETENTION_DAYS = 0 before upgrading — the value 0 now means “keep forever” for all three retention settings. It is a welcome cleanup, but also a trap for anyone counting on old logs.
The third is a Git 2.25.0 minimum requirement (#39131): Gitea refuses to start with an older Git, something to check on distributions that do not install Git from official repositories. The fourth disables self-registration by default (#39400) — you must now explicitly set [service] DISABLE_REGISTRATION = false — and moves the instance domain to ROOT_URL, with [server] DOMAIN no longer read. The fifth tightens workflow evaluation: the job-level if: is evaluated before the matrix expands, matrix fail-fast is enforced, and public repositories can no longer call reusable workflows from private repositories (#39358).
There is also an operational detail: the 28.0.0 binaries no longer include 32-bit x86 or gogit builds, and the Snap is no longer built for armhf. Download file names also drop their OS version suffix. If a download script relied on the old gitea-28.0.0-windows-amd64.exe format, it needs updating.
A wave of authorization hardening
28.0.0 is also a security release, even if Gitea is being cautious: the blog post says details will be added “in about a week” to give people time to patch. The repository changelog still lists the fixes, and several deserve an operator’s attention.
The most structural one is enforcing repository-scoped authorization for team access, deletion, and package unlinking (#39063). In plain terms, Gitea now ensures that the rights granted to a team on a repository stay bounded to that repository’s scope, instead of potentially spilling into other resources — a fix that shrinks the surface for privilege escalation through a compromised account.
Two fixes harden the Git transport itself. The first makes Gitea reject invalid or duplicate Git objects on push (#39472), closing a class of attacks where a malformed repository acts as a vector. The second identifies presented public keys by fingerprint rather than an ambiguous identifier (#39423), making SSH authentication more robust. Finally, the golang.org/x/crypto update patches a denial-of-service flaw in the SSH package (#39219), and cancelled or unapproved fork pull request runs stay behind the approval gate (#39399).
What 28.0.0 adds to the day-to-day
Beyond security, 28.0.0 ships features that speak directly to a self-hosting operator. Audit logging (#38189) — off by default, enabled via [audit] RECORD_OUTPUT = database, with a default 30-day retention — records security-relevant events and exports them as JSONL. It fills a glaring gap the forge previously covered with barely-usable application logs.
Managing bot accounts from the admin UI, API, and CLI (#38966) replaces a widespread hack — creating a “robot” account with hand-made rights — with a first-class object. Admin user impersonation (#38614) shows a banner marking the session and links actions to both accounts when audit logging is on, which eases support without breaking traceability. HTTPS deploy tokens and code-owner approval rules round out an already substantial release.
On the Actions side, the additions follow the same thread: a build queue view, support for the $/ and self: prefixes in reusable workflows, a force-cancel API, and adaptive auto-refresh of the run list. For a team that has made Gitea Actions its internal CI/CD, that is a handful of small frictions removed — provided you first digest the five breaking changes.
Gitea Runner 4.0.0, released on September 24, lands alongside the forge itself, so teams should review the runner’s own changelog at the same time. The upgrade guidance from Gitea is deliberately conservative: back up your data, read the breaking changes, then replace the binary or container and restart. For a self-hosted forge that quietly anchors an entire team’s Git workflow, that caution is the right default — the cost of a botched upgrade is every push, review, and CI/CD run going dark at once.
Verdict
If you self-host Gitea in production, do not upgrade blind: read the five breaking changes, especially moving egress to EGRESS_MODE = strict and setting RUN_RETENTION_DAYS = 0 if you want to keep your logs, then test on a staging instance before touching production. If you manage access by team, the repository-scoped authorization fix (#39063) and invalid-object rejection (#39472) justify a fast upgrade on their own. If you stay on 1.27.x for now, at least check your Git version and the SSH denial-of-service fix in x/crypto, and schedule the migration — the security fixes will not backport as a simple patch on the 1.x branch. Either way, treat this release as the maintenance window it is: the hardening it delivers is worth the reading.