We are thrilled to announce the latest release of Gitea v28.0.0.
Gitea drops the historical 1. prefix from its version numbers, so this release is 28.0.0 rather than 1.28.0.
Highlights include audit logging, bot accounts, HTTPS deploy tokens, user impersonation for administrators, code-owner approval rules, diff file filters, and an Actions queue view. See the changelog for everything else.
We are very thankful for the many people who have contributed to the project by sending code patches, reporting issues, translating, and supporting us in many other ways.
This release contains security fixes. To give everyone time to upgrade, details will be added to this post in about a week.
You can download Gitea from our downloads page. Please read our installation guide for more information. Before upgrading, read the breaking changes. Then back up your data, replace the binary or Docker container, and restart.
Release binaries no longer include 32-bit x86 or gogit builds, and the Snap is no longer built for armhf. Download file names also no longer carry an OS version suffix, for example gitea-28.0.0-windows-amd64.exe, so update any download scripts.
We would like to thank all of our supporters on Open Collective who are helping to sustain the project financially.
Migrations, mirrors, and other Git network operations now go through an internal proxy that applies the egress settings to direct connections. Review your allow and block lists before upgrading:
The external preset is removed. For a deny-by-default policy, set EGRESS_MODE = strict and list the allowed hosts. [migrations] EGRESS_MODE covers migrations and mirrors, and [security] EGRESS_MODE covers webhooks and OAuth2.
In strict mode, entries without a port only allow ports 80 and 443.
In the default lax mode, [security] ALLOWED_HOST_LIST no longer restricts public hosts. Set [security] EGRESS_MODE = strict to keep it as an exclusive allowlist. Gitea logs a startup warning when the list is set without an explicit EGRESS_MODE.
IP address entries no longer accept wildcards, and * is no longer a valid entry.
Domain entries follow curl syntax: example.com matches the domain and all subdomains, *.example.com matches only subdomains, and example.* is invalid.
Invalid [migrations] BLOCKED_HOST_LIST entries now stop Gitea from starting.
[migrations] ALLOWED_DOMAINS, BLOCKED_DOMAINS, and ALLOW_LOCALNETWORKS are deprecated in favor of [migrations] ALLOWED_HOST_LIST and BLOCKED_HOST_LIST.
Thank you to @TheFox0x7 for contributing this change.
Completed Actions runs are now deleted after 400 days by default, together with their jobs, logs, and artifacts. The new cleanup_action_runs cron task deletes them, by default at midnight. To keep all runs, set the following before upgrading:
[actions]
RUN_RETENTION_DAYS = 0
0 now means “keep forever” for RUN_RETENTION_DAYS, LOG_RETENTION_DAYS, and ARTIFACT_RETENTION_DAYS. Logs and artifacts are always deleted along with their run.
Thank you to @facorazza for contributing this change.
Gitea now refuses to start with a Git version older than 2.25.0. If you install Git yourself, check git --version before upgrading.
Thank you to @silverwind for contributing this change.
⚠️ Self-registration is off by default and [server] DOMAIN is ignored (#39400)
Self-registration is now disabled unless [service] DISABLE_REGISTRATION = false is set explicitly.
Gitea no longer reads [server] DOMAIN. The instance domain, including the default SSH domain, now comes from ROOT_URL, so set ROOT_URL if you relied on DOMAIN.
Thank you to @wxiaoguang for contributing this change.
Job-level if: is now evaluated before the matrix is expanded and may only use the github, gitea, needs, vars, and inputs contexts. Move matrix conditions to strategy.matrix.include/exclude or to step-level if:.
Matrix fail-fast is now enforced, so a failing job can cancel the remaining combinations. Set strategy.fail-fast: false to let all of them finish.
Workflows in public repositories can no longer call reusable workflows from private repositories, and nested workflows can no longer exceed the caller’s token permissions.
Thank you to @silverwind for contributing these changes.
Administrators can now impersonate a user to see Gitea as that user does, which helps reproduce access problems without asking for the user’s password. A banner marks the session and links back to the administrator account. Everything done in the session is performed as the impersonated user, and with audit logging enabled, events record both accounts.
Thank you to @wxiaoguang and @bircni for contributing these improvements.
Gitea can now record security-relevant events and show them in the admin, organization, repository, and user settings. Events can be filtered by actor, action, and origin, and administrators can export them as JSONL.
Audit logging is off by default. Enable it with:
[audit]
RECORD_OUTPUT = database
Events are kept for 30 days by default. Change this with [audit] RETENTION_DAYS, where 0 keeps them forever.
Thank you to @bircni for contributing this feature.
A new [redis] section sets one CONN_STR as the default for cache, session, queue, global lock, and WebSocket pub/sub. It applies to subsystems that are already configured to use Redis but do not set their own connection string.
Bot accounts are meant for automation. They authenticate with access tokens, cannot sign in interactively, and receive no notifications or emails. Administrators can create bots, manage their tokens, and convert eligible local accounts between users and bots from the admin UI, API, or CLI.
Thank you to @joestump and @bircni for contributing this feature.
Notification counts, stopwatch updates, and logout events now use a WebSocket at /-/ws instead of server-sent events at /user/events. Reverse proxies must forward WebSocket upgrade headers, otherwise notification counts and stopwatch updates fall back to polling. Deployments with multiple Gitea processes need [websocket] PUBSUB_TYPE = redis and a Redis connection. The [ui.notification] EVENT_SOURCE_UPDATE_TIME setting is removed.
Thank you to @mohammad-rj for contributing this change.
Deploy tokens are the HTTPS counterpart to SSH deploy keys. Each token is scoped to one repository with read or read-write access and serves as the password for Git and LFS over HTTPS. Both deploy tokens and personal access tokens (#38907) can be regenerated in place.
The diff file tree gains a search box and a file-extension filter. Both narrow the file tree and the diff, and the extension filter is kept in the URL, so a filtered view can be shared.
The watch button is now a menu with Participating and mentions, All activity, Ignore, and Custom. Custom adds notifications for any of issues, pull requests, and releases. These choices apply to both UI and email notifications.
Thank you to @schonwetter for contributing this feature.
A dropdown next to the repository name lets you search and switch between repositories of the same owner.
Thank you to @bircni for contributing this feature.
Template repositories can list files and directories in an [exclude] section of .gitea/template to leave them out of generated repositories.
Thank you to @paarth-k2002 for contributing this feature.
Closing references such as Fixes: #123 can now close pull requests, not only issues.
Thank you to @silverwind for contributing this improvement.
Repositories can now use Gitea’s built-in issues together with an external tracker whose references use an alphanumeric or regular-expression format, such as JIRA-123. Leave the external tracker URL empty, otherwise the Issues tab still redirects to the external tracker.
Thank you to @breken-ai for contributing this improvement.
Gitea now detects REUSE-style license files named by their SPDX identifier and shows every detected license with a link to its file.
Thank you to @TheFox0x7 for contributing this feature.
The new queue view lists running jobs first, then waiting jobs in the order runners pick them up. Administrators get an instance-wide view with owner, repository, and status filters, and each repository has its own queue in the Actions tab. Both views refresh in place.
Thank you to @bircni for contributing this feature.
The Actions run list now refreshes automatically, except while the browser tab is in the background.
The Actions run view can now browse artifacts and preview text, images, PDFs, and generated HTML such as test reports. Previews require sign-in and read access to the run. HTML previews run in a sandboxed frame. ZIP downloads remain available.
[actions] ARTIFACT_PREVIEW_MAX_SIZE limits previews to artifacts of up to 10 MiB by default. 0 disables previews and -1 removes the limit. Individual files are also subject to [ui] MAX_DISPLAY_FILE_SIZE.
Thank you to @bircni for contributing this feature.
A job matrix can now be built from the outputs of earlier jobs, and strategy.max-parallel limits how many matrix jobs run at once. Properties such as runs-on can depend on needs and are resolved once those jobs finish. uses: accepts self: to reference actions and workflows on the same instance, and reusable workflow calls accept $/ for the same repository (#38822). Pushing an invalid workflow file now creates a failed run that shows the error.
The npm registry supports npm deprecate, richer version metadata, and the single-version API. Helm charts can be uploaded with provenance files, and site administrators can list all packages through a new API.