mirror of
https://gitea.com/gitea/docs.git
synced 2026-09-17 19:55:34 +00:00
docs: Document audit logging
This commit is contained in:
@@ -0,0 +1,142 @@
|
|||||||
|
---
|
||||||
|
date: "2026-09-12T00:00:00+00:00"
|
||||||
|
slug: "audit-logging"
|
||||||
|
sidebar_position: 41
|
||||||
|
aliases:
|
||||||
|
- /en-us/audit-logging
|
||||||
|
---
|
||||||
|
|
||||||
|
# Audit Logging
|
||||||
|
|
||||||
|
Gitea can record security-relevant events as structured audit records: each
|
||||||
|
event has an `action`, `actor`, `scope`, `origin`, `message` and a JSON
|
||||||
|
`metadata` blob. Recording is **off by default** and does not change request
|
||||||
|
behavior when it is disabled.
|
||||||
|
|
||||||
|
This is separate from the application, router and access logs described in
|
||||||
|
[Logging Configuration](logging-config.md). Those logs are for operations and
|
||||||
|
debugging. The audit log is a durable trail of who changed what.
|
||||||
|
|
||||||
|
## Enable recording
|
||||||
|
|
||||||
|
Set `[audit].RECORD_OUTPUT` to `database` in `app.ini` and restart Gitea:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[audit]
|
||||||
|
RECORD_OUTPUT = database
|
||||||
|
RETENTION_DAYS = 30
|
||||||
|
```
|
||||||
|
|
||||||
|
Invalid values of `RECORD_OUTPUT` fall back to `disabled`. See the
|
||||||
|
[configuration cheat sheet](config-cheat-sheet.md#audit-audit) for every option.
|
||||||
|
|
||||||
|
With Docker, the same settings can be applied as
|
||||||
|
`GITEA__audit__RECORD_OUTPUT=database` and `GITEA__audit__RETENTION_DAYS=30`
|
||||||
|
before Gitea writes them into `app.ini`.
|
||||||
|
|
||||||
|
## View events
|
||||||
|
|
||||||
|
The Audit Log page is always available. When recording is disabled, it shows a
|
||||||
|
warning and still lists any events that were stored earlier.
|
||||||
|
|
||||||
|
| Audience | Location | Events shown |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Site administrators | Site administration → Monitoring → Audit Log (`/-/admin/monitor/audit_logs`) | Every event |
|
||||||
|
| Signed-in users | User settings → Audit Log (`/user/settings/audit_logs`) | Events scoped to that user |
|
||||||
|
| Organization owners | Organization settings → Audit Log (`/<org>/settings/audit_logs`) | Events scoped to that organization |
|
||||||
|
| Repository administrators | Repository settings → Audit Log (`/<owner>/<repo>/settings/audit_logs`) | Events scoped to that repository |
|
||||||
|
|
||||||
|
Each listing can be filtered by actor (username), action and origin, and sorted
|
||||||
|
by timestamp. Action filters accept an exact action or a family prefix such as
|
||||||
|
`user:impersonation` or `repository:webhook`.
|
||||||
|
|
||||||
|
Site administrators can download the current filtered result as JSONL
|
||||||
|
(newline-delimited JSON) from **Export JSONL**. The file name is
|
||||||
|
`gitea-audit-log-<timestamp>.jsonl`.
|
||||||
|
|
||||||
|
## Event shape
|
||||||
|
|
||||||
|
A recorded event contains:
|
||||||
|
|
||||||
|
- **Action**: a stable, colon-separated identifier such as `repository:archive`
|
||||||
|
or `user:accesstoken:add`.
|
||||||
|
- **Actor**: the user who performed the action. Actions taken while impersonating
|
||||||
|
a user record both the impersonator and the impersonated user.
|
||||||
|
- **Actor credential**: when the request authenticated with a named credential,
|
||||||
|
the event stores its kind and id, never the secret. Typical values:
|
||||||
|
`access-token:<id>`, `oauth2-grant:<id>`, `gitea-actions:<task id>`,
|
||||||
|
`deploy-key:<key id>`.
|
||||||
|
- **Scope**: the affected unit — `user`, `organization`, `repository` or
|
||||||
|
`system` (instance-wide).
|
||||||
|
- **Origin**: how the action was initiated — `ui`, `api`, `cli` or `system`.
|
||||||
|
- **Message**: a human-readable sentence rendered from a per-action template.
|
||||||
|
- **Metadata**: extra fields that fill the message template (token name, new
|
||||||
|
visibility, and so on). Secrets and token values are not stored.
|
||||||
|
- **IP address**: the client address of the request, when one exists.
|
||||||
|
- **Timestamp**: when the event was recorded.
|
||||||
|
|
||||||
|
An exported JSONL line looks like:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"action":"repository:archive","actor":{"type":"user","id":1,"name":"alice"},"scope":{"type":"repository","id":42,"name":"org/repo"},"message":"Archived repository org/repo.","time":"2026-09-12T11:00:00Z","ip_address":"203.0.113.10","origin":"ui"}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `system:startup` message is kept stable across Gitea versions so operators
|
||||||
|
can parse it: `System started [Gitea {version}]`.
|
||||||
|
|
||||||
|
## Actors and origins
|
||||||
|
|
||||||
|
Most web and API requests pick up the signed-in user automatically.
|
||||||
|
|
||||||
|
Some entry points have no signed-in user. Those events use a dedicated actor:
|
||||||
|
|
||||||
|
- `CLI` for `gitea` command-line operations
|
||||||
|
- `AuthenticationSource` for authentication-source syncs and related background
|
||||||
|
work
|
||||||
|
- `Unknown` if the actor cannot be resolved; the event is still recorded
|
||||||
|
|
||||||
|
Cron tasks and other background work use origin `system`. Git hooks and similar
|
||||||
|
non-interactive paths are attributed the same way.
|
||||||
|
|
||||||
|
## What is recorded
|
||||||
|
|
||||||
|
Events cover security-relevant changes, grouped by action family:
|
||||||
|
|
||||||
|
- **User**: create and delete, name, password, visibility, emails, 2FA,
|
||||||
|
WebAuthn, OpenID, external logins, access tokens, OAuth2 applications and
|
||||||
|
grants, SSH/GPG/principal keys, secrets, webhooks, impersonation, failed
|
||||||
|
two-factor authentication
|
||||||
|
- **Organization**: create and delete, name, visibility, members, teams,
|
||||||
|
OAuth2 applications, secrets, webhooks
|
||||||
|
- **Repository**: create, fork, archive, delete, rename, visibility, transfer,
|
||||||
|
mirrors, signing verification, collaborators and teams, default branch,
|
||||||
|
branch and tag protection, deploy keys, webhooks, secrets
|
||||||
|
- **Issues, pull requests, projects and wiki**: create, update, delete, comments
|
||||||
|
and merges
|
||||||
|
- **Actions**: enable, disable and dispatch a workflow
|
||||||
|
- **System**: startup and shutdown, instance-wide webhooks, authentication
|
||||||
|
sources, instance-wide OAuth2 applications
|
||||||
|
|
||||||
|
Recording never fails the request that triggered it. A write error is logged
|
||||||
|
and the original operation continues.
|
||||||
|
|
||||||
|
## What is not recorded
|
||||||
|
|
||||||
|
- Read-only access such as browsing, clone, fetch or API GET requests
|
||||||
|
- Successful password or SSH logins (use the [access log](logging-config.md)
|
||||||
|
and [Fail2ban Setup](fail2ban-setup.md) for authentication traffic)
|
||||||
|
- Token or secret values
|
||||||
|
- Which SSH key a real user pushed with (deploy keys are named; ordinary SSH
|
||||||
|
user pushes are not)
|
||||||
|
|
||||||
|
## Retention
|
||||||
|
|
||||||
|
`RETENTION_DAYS` (default **30**) is the age after which recorded events are
|
||||||
|
eligible for deletion. Set it to `0` to keep events forever.
|
||||||
|
|
||||||
|
Cleanup is performed by the `cron.delete_old_audit_events` task (`SCHEDULE`
|
||||||
|
defaults to `@every 24h`, `OLDER_THAN` defaults to `[audit].RETENTION_DAYS`).
|
||||||
|
The task is registered only while `RECORD_OUTPUT` records events **and**
|
||||||
|
`RETENTION_DAYS` is greater than `0`. Turning recording off therefore also
|
||||||
|
stops pruning; existing rows stay until you delete them or turn recording back
|
||||||
|
on.
|
||||||
@@ -656,6 +656,11 @@ And the following unique queues:
|
|||||||
- CIDR list: `1.2.3.0/8` for IPv4 and `2001:db8::/32` for IPv6
|
- CIDR list: `1.2.3.0/8` for IPv4 and `2001:db8::/32` for IPv6
|
||||||
- Wildcard hosts: `*.mydomain.com`, `192.168.100.*`
|
- Wildcard hosts: `*.mydomain.com`, `192.168.100.*`
|
||||||
|
|
||||||
|
## Audit (`audit`)
|
||||||
|
|
||||||
|
- `RECORD_OUTPUT`: **disabled**: Where security-relevant events are recorded. `disabled` records nothing. `database` writes events to the `audit_event` table and shows them in the admin, organization, repository and user settings. Invalid values fall back to `disabled`. See [Audit Logging](audit-logging.md).
|
||||||
|
- `RETENTION_DAYS`: **30**: Days to keep recorded events. `0` keeps them forever. Pruning is done by `cron.delete_old_audit_events`. That task is only registered while `RECORD_OUTPUT` records events and `RETENTION_DAYS` is greater than `0`.
|
||||||
|
|
||||||
## Camo (`camo`)
|
## Camo (`camo`)
|
||||||
|
|
||||||
- `ENABLED`: **false**: Enable media proxy, we support images only at the moment.
|
- `ENABLED`: **false**: Enable media proxy, we support images only at the moment.
|
||||||
@@ -1198,6 +1203,16 @@ Synchronize external user data (only LDAP user synchronization is supported)
|
|||||||
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
||||||
- `OLDER_THAN`: **8760h**: any action older than this expression will be deleted from database, suggest using `8760h` (1 year) because that's the max length of heatmap.
|
- `OLDER_THAN`: **8760h**: any action older than this expression will be deleted from database, suggest using `8760h` (1 year) because that's the max length of heatmap.
|
||||||
|
|
||||||
|
#### Cron - Delete old audit events (`cron.delete_old_audit_events`)
|
||||||
|
|
||||||
|
Deletes audit events older than the retention period. The task is only registered when `[audit].RECORD_OUTPUT` records events and `[audit].RETENTION_DAYS` is greater than `0`. See [Audit Logging](audit-logging.md).
|
||||||
|
|
||||||
|
- `ENABLED`: **true**: Enable service.
|
||||||
|
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
||||||
|
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
|
||||||
|
- `SCHEDULE`: **@every 24h**: Cron syntax to set how often to check.
|
||||||
|
- `OLDER_THAN`: **720h**: any audit event older than this expression will be deleted from the database. Defaults to `[audit].RETENTION_DAYS`.
|
||||||
|
|
||||||
#### Cron - Check for new Gitea versions (`cron.update_checker`)
|
#### Cron - Check for new Gitea versions (`cron.update_checker`)
|
||||||
|
|
||||||
- `ENABLED`: **true**: Enable service.
|
- `ENABLED`: **true**: Enable service.
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ The logging configuration of Gitea mainly consists of 3 types of components:
|
|||||||
|
|
||||||
There is a fully functional log output by default, so it is not necessary to define one.
|
There is a fully functional log output by default, so it is not necessary to define one.
|
||||||
|
|
||||||
|
Security-relevant events (repository transfers, token changes, impersonation, and similar) are recorded separately. See [Audit Logging](audit-logging.md).
|
||||||
|
|
||||||
## Collecting Logs for Help
|
## Collecting Logs for Help
|
||||||
|
|
||||||
To collect logs for help and issue report, see [Support Options](help/support.md).
|
To collect logs for help and issue report, see [Support Options](help/support.md).
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ You can try it out using [the online demo](https://demo.gitea.com).
|
|||||||
|
|
||||||
- **Security**
|
- **Security**
|
||||||
|
|
||||||
Gitea places a strong emphasis on security, offering features such as user permission management, access control lists, and more to ensure the security of code and data.
|
Gitea places a strong emphasis on security, offering features such as user permission management, access control lists, [audit logging](administration/audit-logging.md), and more to ensure the security of code and data.
|
||||||
|
|
||||||
- **Code Review**
|
- **Code Review**
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ _Symbols used in table:_
|
|||||||
| Telemetry | **✘** | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
| Telemetry | **✘** | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||||
| Third-party render tool support | ✓ | ✘ | ✘ | ✘ | ✓ | ✘ | ✘ |
|
| Third-party render tool support | ✓ | ✘ | ✘ | ✘ | ✓ | ✘ | ✘ |
|
||||||
| WebAuthn (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
| WebAuthn (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
||||||
|
| Audit log | ✓ | ✓ | ⁄ | ✓ | ✓ | ? | ? |
|
||||||
| Extensive API | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
| Extensive API | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
| Built-in Package/Container Registry | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ |
|
| Built-in Package/Container Registry | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ |
|
||||||
| Sync commits to an external repo (push mirror) | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ | ✓ |
|
| Sync commits to an external repo (push mirror) | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ | ✓ |
|
||||||
|
|||||||
Reference in New Issue
Block a user