Gitea 28 drops the 1.x prefix and adds audit logging
Gitea 28 adds audit records, but its upgrade also changes settings worth checking before deployment.
Knowing who changed what in your forge
On a self-hosted instance, ordinary logs are useful for troubleshooting, but they are not ideal for answering control questions: who changed a repository’s visibility, who created a token, or where a webhook was edited. Gitea 28.0.0 adds an audit log that is separate from application, router, and access logs. Its purpose is to keep a structured record of security-relevant and administrative changes. (docs.gitea.com)
The versioning change is worth noticing as well: Gitea has dropped the historical 1. prefix, so the next release is called 28.0.0 rather than 1.28.0. I would not treat this as a routine upgrade just because the version number looks unusual; several behavior changes can affect integrations, automation, and network policies. (blog.gitea.com)
Enabling auditing without another service
Audit recording is disabled by default and uses the database when enabled. Each event includes fields such as a stable action name, actor, scope, origin, message, and JSON metadata. Docker deployments can use GITEA__audit__RECORD_OUTPUT and GITEA__audit__RETENTION_DAYS, which Gitea writes into app.ini. (docs.gitea.com)
[audit]
RECORD_OUTPUT = database
RETENTION_DAYS = 30I would start with a limited retention period, then adjust it after checking database growth and the team’s actual needs. Setting RETENTION_DAYS = 0 keeps events indefinitely. The cron.delete_old_audit_events scheduled task handles cleanup while recording is enabled and the retention period is greater than zero. (docs.gitea.com)
A practical format for review and export
Site administrators can filter events by actor, action, and origin, then export the filtered result as JSONL from the interface. That makes it possible to preserve a specific snapshot, send it to another system, or process it with scripts without parsing free-form log messages. Organization owners, repository administrators, and signed-in users also get audit views limited to their own scope. (docs.gitea.com)
For me, the useful part is being able to compare administrative changes with deployments or automation runs. The origin field can tell you whether an action came from the UI, API, CLI, or a system process. Gitea Actions tasks are also represented by a system actor, which is useful when automation changes secrets, webhooks, or repository settings. (docs.gitea.com)
The upgrade requires more than replacing the container
Gitea 28 changes outbound network rules for migrations, mirrors, webhooks, and OAuth2. Git network operations now go through an internal proxy, so allow and block lists should be reviewed before upgrading. If you run a restrictive policy, EGRESS_MODE = strict is what keeps an allow list exclusive; without it, an older setup may no longer behave as intended. (blog.gitea.com)
Gitea Actions retention changes too: completed runs are removed after 400 days by default, together with their jobs, logs, and artifacts. If you need to retain that history indefinitely, define RUN_RETENTION_DAYS = 0 in [actions] before upgrading. I would not postpone that decision if your runs contain CI evidence, test reports, or delivery artifacts. (blog.gitea.com)
[actions]
RUN_RETENTION_DAYS = 0Public self-registration is now disabled by default. If your instance accepts open sign-ups, you must explicitly set [service] DISABLE_REGISTRATION = false; relying on the previous behavior is no longer enough. It is also worth reviewing ROOT_URL, because Gitea no longer uses [server] DOMAIN to determine the instance domain or the default SSH domain. (blog.gitea.com)
The limits of audit logging
Audit logging is not a replacement for access logs, nor is it a complete recording of every activity. It does not store read-only operations such as browsing, clones, fetches, or API GET requests, and it does not log successful or failed sign-ins except failed two-factor authentication. It also avoids token and secret values, and it does not identify the SSH key used by a regular user push. (docs.gitea.com)
There is another important limitation: if an audit write fails, the original operation still continues and the failure is written to the logs. That prevents audit storage from blocking normal work, but it also means the record should not be treated as an absolute guarantee without monitoring database and log health. I would check alerts, backups, and capacity before making it part of an internal compliance process. (docs.gitea.com)
How I would approach the change
I would take a backup, test the upgrade on a non-production instance, and review egress rules and Actions workflows first. Then I would enable auditing with a short retention period, confirm that useful events appear, and decide which exports should live outside Gitea. Finally, I would check public registration, ROOT_URL, the installed Git version, and any download scripts that rely on old binary names. (blog.gitea.com)
Source: Self-Host Lab.
Official release announcement: Gitea 28.0.0 is released.
Official documentation: Audit Logging.