$$`
+ - The defaults are:
+ - `argon2`: `argon2$2$65536$8$50`
+ - `bcrypt`: `bcrypt$10`
+ - `pbkdf2`: `pbkdf2$50000$50`
+ - `pbkdf2_v1`: `pbkdf2$10000$50`
+ - `pbkdf2_v2`: `pbkdf2$50000$50`
+ - `pbkdf2_hi`: `pbkdf2$320000$50`
+ - `scrypt`: `scrypt$65536$16$2$50`
+ - Adjusting the algorithm parameters using this functionality is done at your own risk.
+- `CSRF_COOKIE_HTTP_ONLY`: **true**: Set false to allow JavaScript to read CSRF cookie.
+- `MIN_PASSWORD_LENGTH`: **8**: Minimum password length for new users.
+- `PASSWORD_COMPLEXITY`: **off**: Comma separated list of character classes required to pass minimum complexity. If left empty or no valid values are specified, checking is disabled (off):
+ - lower - use one or more lower latin characters
+ - upper - use one or more upper latin characters
+ - digit - use one or more digits
+ - spec - use one or more special characters as ``!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~``
+ - off - do not check password complexity
+- `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed.
+- `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
+- `DISABLE_QUERY_AUTH_TOKEN`: **false**: Reject API tokens sent in URL query string (Accept Header-based API tokens only). This setting will default to `true` in Gitea 1.23 and be deprecated in Gitea 1.24.
+- `TWO_FACTOR_AUTH`: **_empty_**: set to enforced to enforce two factor authentication. Only available in Gitea 1.24 and later.
+
+## Camo (`camo`)
+
+- `ENABLED`: **false**: Enable media proxy, we support images only at the moment.
+- `SERVER_URL`: **_empty_**: URL of camo server, it **is required** if camo is enabled.
+- `HMAC_KEY`: **_empty_**: Provide the HMAC key for encoding URLs, it **is required** if camo is enabled.
+- `ALWAYS`: **false**: Set to true to use camo for both HTTP and HTTPS content, otherwise only non-HTTPS URLs are proxied. `ALLWAYS` is deprecated and will be removed in a future release.
+
+## OpenID (`openid`)
+
+- `ENABLE_OPENID_SIGNIN`: **true**: Allow authentication in via OpenID.
+- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**: Allow registering via OpenID.
+- `WHITELISTED_URIS`: **_empty_**: If non-empty, list of POSIX regex patterns matching
+ OpenID URI's to permit.
+- `BLACKLISTED_URIS`: **_empty_**: If non-empty, list of POSIX regex patterns matching
+ OpenID URI's to block.
+
+## OAuth2 Client (`oauth2_client`)
+
+- `REGISTER_EMAIL_CONFIRM`: _[service]_ **REGISTER\_EMAIL\_CONFIRM**: Set this to enable or disable email confirmation of OAuth2 auto-registration. (Overwrites the REGISTER\_EMAIL\_CONFIRM setting of the `[service]` section)
+- `OPENID_CONNECT_SCOPES`: **_empty_**: List of additional openid connect scopes. (`openid` is implicitly added)
+- `ENABLE_AUTO_REGISTRATION`: **false**: Automatically create user accounts for new oauth2 users.
+- `USERNAME`: **nickname**: The source of the username for new oauth2 accounts:
+ - `userid` - use the userid / sub attribute
+ - `nickname` - use the nickname
+ - `preferred_username` - use the preferred_username
+ - `email` - use the username part of the email attribute
+ - Note: `nickname`, `preferred_username` and `email` options will normalize input strings using the following criteria:
+ - diacritics are removed
+ - the characters in the set ```['´`]``` are removed
+ - the characters in the set `[\s~+]` are replaced with `-`
+- `UPDATE_AVATAR`: **false**: Update avatar if available from oauth2 provider. Update will be performed on each login.
+- `ACCOUNT_LINKING`: **login**: How to handle if an account / email already exists:
+ - disabled - show an error
+ - login - show an account linking login
+ - auto - automatically link with the account (Please be aware that this will grant access to an existing account just because the same username or email is provided. You must make sure that this does not cause issues with your authentication providers.)
+
+## Service (`service`)
+
+- `ACTIVE_CODE_LIVE_MINUTES`: **180**: Time limit (min) to confirm account/email registration.
+- `RESET_PASSWD_CODE_LIVE_MINUTES`: **180**: Time limit (min) to confirm forgot password reset
+ process.
+- `REGISTER_EMAIL_CONFIRM`: **false**: Enable this to ask for mail confirmation of registration.
+ Requires `Mailer` to be enabled.
+- `REGISTER_MANUAL_CONFIRM`: **false**: Enable this to manually confirm new registrations.
+ Requires `REGISTER_EMAIL_CONFIRM` to be disabled.
+- `DISABLE_REGISTRATION`: **false**: Disable registration, after which only admin can create
+ accounts for users.
+- `REQUIRE_EXTERNAL_REGISTRATION_PASSWORD`: **false**: Enable this to force externally created
+ accounts (via GitHub, OpenID Connect, etc) to create a password.
+
+ :::warning
+ Enabling this will decrease security, so you should only enable it if you know what you're doing.
+ :::
+
+- `REQUIRE_SIGNIN_VIEW`: **false**: Enable this to force users to log in to view any page or to use API.
+ It could be set to "expensive" to block anonymous users accessing some pages which consume a lot of resources,
+ for example: block anonymous AI crawlers from accessing repo code pages.
+ The "expensive" mode is experimental and subject to change.
+- `ENABLE_NOTIFY_MAIL`: **false**: Enable this to send e-mail to watchers of a repository when
+ something happens, like creating issues. Requires `Mailer` to be enabled.
+- `ENABLE_BASIC_AUTHENTICATION`: **true**: Disable this to disallow authentication using HTTP
+ BASIC and the user's password. Please note if you disable this you will not be able to access the
+ tokens API endpoints using a password. Further, this only disables BASIC authentication using the
+ password - not tokens or OAuth Basic.
+- `ENABLE_PASSWORD_SIGNIN_FORM`: **true**: Show the password login form (for password-based login),
+ otherwise, only show OAuth2 or passkey login methods if they are enabled.
+ If you set it to false, maybe it also needs to set `ENABLE_BASIC_AUTHENTICATION` to false to
+ completely disable password-based authentication.
+- `ENABLE_PASSKEY_AUTHENTICATION`: **true**: Allow users to sign-in with a passkey
+- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: **false**: Enable this to allow reverse proxy authentication for web requests
+- `ENABLE_REVERSE_PROXY_AUTHENTICATION_API`: **false**: Enable this to allow reverse proxy authentication for API requests, the reverse proxy is responsible for ensuring that no CSRF is possible.
+- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: **false**: Enable this to allow auto-registration
+ for reverse authentication.
+- `ENABLE_REVERSE_PROXY_EMAIL`: **false**: Enable this to allow to auto-registration with a
+ provided email rather than a generated email.
+- `ENABLE_REVERSE_PROXY_FULL_NAME`: **false**: Enable this to allow to auto-registration with a
+ provided full name for the user.
+- `ENABLE_CAPTCHA`: **false**: Enable this to use captcha validation for registration.
+- `REQUIRE_CAPTCHA_FOR_LOGIN`: **false**: Enable this to require captcha validation for login. You also must enable `ENABLE_CAPTCHA`.
+- `REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA`: **false**: Enable this to force captcha validation
+ even for External Accounts (i.e. GitHub, OpenID Connect, etc). You also must enable `ENABLE_CAPTCHA`.
+- `CAPTCHA_TYPE`: **image**: \[image, recaptcha, hcaptcha, mcaptcha, cfturnstile\]
+- `RECAPTCHA_SECRET`: **""**: Go to https://www.google.com/recaptcha/admin to get a secret for recaptcha.
+- `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha.
+- `RECAPTCHA_URL`: **https://www.google.com/recaptcha/**: Set the recaptcha url - allows the use of recaptcha net.
+- `HCAPTCHA_SECRET`: **""**: Sign up at https://www.hcaptcha.com/ to get a secret for hcaptcha.
+- `HCAPTCHA_SITEKEY`: **""**: Sign up at https://www.hcaptcha.com/ to get a sitekey for hcaptcha.
+- `MCAPTCHA_SECRET`: **""**: Go to your mCaptcha instance to get a secret for mCaptcha.
+- `MCAPTCHA_SITEKEY`: **""**: Go to your mCaptcha instance to get a sitekey for mCaptcha.
+- `MCAPTCHA_URL` **https://demo.mcaptcha.org/**: Set the mCaptcha URL.
+- `CF_TURNSTILE_SECRET` **""**: Go to https://dash.cloudflare.com/?to=/:account/turnstile to get a secret for cloudflare turnstile.
+- `CF_TURNSTILE_SITEKEY` **""**: Go to https://dash.cloudflare.com/?to=/:account/turnstile to get a sitekey for cloudflare turnstile.
+- `DEFAULT_KEEP_EMAIL_PRIVATE`: **false**: By default set users to keep their email address private.
+- `DEFAULT_ALLOW_CREATE_ORGANIZATION`: **true**: Allow new users to create organizations by default.
+- `DEFAULT_USER_IS_RESTRICTED`: **false**: Give new users restricted permissions by default
+- `DEFAULT_ENABLE_DEPENDENCIES`: **true**: Enable this to have dependencies enabled by default.
+- `ALLOW_CROSS_REPOSITORY_DEPENDENCIES` : **true** Enable this to allow dependencies on issues from any repository where the user is granted access.
+- `USER_LOCATION_MAP_URL`: **""**: A map service URL to show user's location on a map. The location will be appended to the URL as escaped query parameter.
+- `ENABLE_USER_HEATMAP`: **true**: Enable this to display the heatmap on users profiles.
+- `ENABLE_TIMETRACKING`: **true**: Enable Timetracking feature.
+- `DEFAULT_ENABLE_TIMETRACKING`: **true**: Allow repositories to use timetracking by default.
+- `DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME`: **true**: Only allow users with write permissions to track time.
+- `EMAIL_DOMAIN_ALLOWLIST`: **_empty_**: If non-empty, comma separated list of domain names that can only be used to register on this instance, wildcard is supported.
+- `EMAIL_DOMAIN_BLOCKLIST`: **_empty_**: If non-empty, comma separated list of domain names that cannot be used to register on this instance, wildcard is supported.
+- `SHOW_REGISTRATION_BUTTON`: **! DISABLE\_REGISTRATION**: Show Registration Button
+- `SHOW_MILESTONES_DASHBOARD_PAGE`: **true** Enable this to show the milestones dashboard page - a view of all the user's milestones
+- `AUTO_WATCH_NEW_REPOS`: **true**: Enable this to let all organisation users watch new repos when they are created
+- `AUTO_WATCH_ON_CHANGES`: **false**: Enable this to make users watch a repository after their first commit to it
+- `DEFAULT_USER_VISIBILITY`: **public**: Set default visibility mode for users, either "public", "limited" or "private".
+- `ALLOWED_USER_VISIBILITY_MODES`: **public,limited,private**: Set which visibility modes a user can have
+- `DEFAULT_ORG_VISIBILITY`: **public**: Set default visibility mode for organisations, either "public", "limited" or "private".
+- `DEFAULT_ORG_MEMBER_VISIBLE`: **false** True will make the membership of the users visible when added to the organisation.
+- `ALLOW_ONLY_INTERNAL_REGISTRATION`: **false** Set to true to force registration only via Gitea.
+- `ALLOW_ONLY_EXTERNAL_REGISTRATION`: **false** Set to true to force registration only using third-party services.
+- `NO_REPLY_ADDRESS`: **noreply.DOMAIN** Value for the domain part of the user's email address in the Git log if user has set KeepEmailPrivate to true. DOMAIN resolves to the value in server.DOMAIN.
+ The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
+- `USER_DELETE_WITH_COMMENTS_MAX_TIME`: **0** Minimum amount of time a user must exist before comments are kept when the user is deleted.
+- `VALID_SITE_URL_SCHEMES`: **http, https**: Valid site url schemes for user profiles
+
+### Service - Explore (`service.explore`)
+
+- `REQUIRE_SIGNIN_VIEW`: **false**: Only allow signed in users to view the explore pages.
+- `DISABLE_USERS_PAGE`: **false**: Disable the users explore page.
+- `DISABLE_ORGANIZATIONS_PAGE`: **false**: Disable the organizations explore page.
+- `DISABLE_CODE_PAGE`: **false**: Disable the code explore page.
+
+### Request Quality of Service (`qos`)
+
+- `ENABLED`: **false**: Enable request quality of service and overload protection.
+- `MAX_INFLIGHT`: **(dynamic)**: The maximum number of concurrent requests that the server will process before enqueueing new requests. Default is "CpuNum * 4".
+- `MAX_WAITING`: **100**: The maximum number of requests that can be enqueued before new requests will be dropped.
+- `TARGET_WAIT_TIME`: **250ms**: Target maximum wait time a request may be enqueued for. Requests that are enqueued for less than this amount of time will not be dropped. When wait times exceed this amount, a portion of requests will be dropped until wait times have decreased below this amount.
+
+## SSH Minimum Key Sizes (`ssh.minimum_key_sizes`)
+
+Define allowed algorithms and their minimum key length (use -1 to disable a type):
+
+- `ED25519`: **256**
+- `ECDSA`: **256**
+- `RSA`: **3071**: We set 3071 here because an otherwise valid 3072 RSA key can be reported as 3071 length.
+- `DSA`: **-1**: DSA is now disabled by default. Set to **1024** to re-enable but ensure you may need to reconfigure your SSHD provider
+
+## Webhook (`webhook`)
+
+- `QUEUE_LENGTH`: **1000**: Hook task queue length. Use caution when editing this value.
+- `DELIVER_TIMEOUT`: **5**: Delivery timeout (sec) for shooting webhooks.
+- `ALLOWED_HOST_LIST`: **external**: Webhook can only call allowed hosts for security reasons. Comma separated list.
+ - Built-in networks:
+ - `loopback`: 127.0.0.0/8 for IPv4 and ::1/128 for IPv6, localhost is included.
+ - `private`: RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and RFC 4193 (FC00::/7). Also called LAN/Intranet.
+ - `external`: A valid non-private unicast IP, you can access all hosts on public internet.
+ - `*`: All hosts are allowed.
+ - CIDR list: `1.2.3.0/8` for IPv4 and `2001:db8::/32` for IPv6
+ - Wildcard hosts: `*.mydomain.com`, `192.168.100.*`
+- `SKIP_TLS_VERIFY`: **false**: Allow insecure certification.
+- `PAGING_NUM`: **10**: Number of webhook history events that are shown in one page.
+- `PROXY_URL`: **_empty_**: Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy. If not given, will use global proxy setting.
+- `PROXY_HOSTS`: **_empty_`**: Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts. If not given, will use global proxy setting.
+
+## Mailer (`mailer`)
+
+:::warning
+This section is for Gitea 1.18 and later. If you are using Gitea 1.17 or older,
+please refer to
+[Gitea 1.17 app.ini example](https://github.com/go-gitea/gitea/blob/release/v1.17/custom/conf/app.example.ini)
+and
+[Gitea 1.17 configuration document](https://github.com/go-gitea/gitea/blob/release/v1.17/docs/content/doc/advanced/config-cheat-sheet.en-us.md)
+:::
+
+- `ENABLED`: **false**: Enable to use a mail service.
+- `PROTOCOL`: **_empty_**: Mail server protocol. One of "smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy". _Before 1.18, this was inferred from a combination of `MAILER_TYPE` and `IS_TLS_ENABLED`._
+ - SMTP family, if your provider does not explicitly say which protocol it uses but does provide a port, you can set SMTP_PORT instead and this will be inferred.
+ - **sendmail** Use the operating system's `sendmail` command instead of SMTP. This is common on Linux systems.
+ - **dummy** Send email messages to the log as a testing phase.
+ - Note that enabling sendmail will ignore all other `mailer` settings except `ENABLED`, `FROM`, `SUBJECT_PREFIX` and `SENDMAIL_PATH`.
+ - Enabling dummy will ignore all settings except `ENABLED`, `SUBJECT_PREFIX` and `FROM`.
+- `SMTP_ADDR`: **_empty_**: Mail server address. e.g. smtp.gmail.com. For smtp+unix, this should be a path to a unix socket instead. _Before 1.18, this was combined with `SMTP_PORT` under the name `HOST`._
+- `SMTP_PORT`: **_empty_**: Mail server port. If no protocol is specified, it will be inferred by this setting. Common ports are listed below. _Before 1.18, this was combined with `SMTP_ADDR` under the name `HOST`._
+ - 25: insecure SMTP
+ - 465: SMTP Secure
+ - 587: StartTLS
+- `USE_CLIENT_CERT`: **false**: Use client certificate for TLS/SSL.
+- `CLIENT_CERT_FILE`: **custom/mailer/cert.pem**: Client certificate file.
+- `CLIENT_KEY_FILE`: **custom/mailer/key.pem**: Client key file.
+- `FORCE_TRUST_SERVER_CERT`: **false**: If set to `true`, completely ignores server certificate validation errors. This option is unsafe. Consider adding the certificate to the system trust store instead.
+- `USER`: **_empty_**: Username of mailing user (usually the sender's e-mail address).
+- `PASSWD`: **_empty_**: Password of mailing user. Use \`your password\` for quoting if you use special characters in the password.
+ - Please note: authentication is only supported when the SMTP server communication is encrypted with TLS (this can be via `STARTTLS`) or SMTP host is localhost. See [Email Setup](email-setup.md) for more information.
+- `ENABLE_HELO`: **true**: Enable HELO operation.
+- `HELO_HOSTNAME`: **(retrieved from system)**: HELO hostname.
+- `FROM`: **_empty_**: Mail from address, RFC 5322. This can be just an email address, or the "Name" `\` format.
+- `ENVELOPE_FROM`: **_empty_**: Address set as the From address on the SMTP mail envelope. Set to `<>` to send an empty address.
+- `FROM_DISPLAY_NAME_FORMAT`: **`{{ .DisplayName }}`**: If gitea sends mails on behave of users, it will just use the name also displayed in the WebUI. If you want e.g. `Mister X (by CodeIt) `, set it to `{{ .DisplayName }} (by {{ .AppName }})`. Available Variables: `.DisplayName`, `.AppName` and `.Domain`.
+- `SUBJECT_PREFIX`: **_empty_**: Prefix to be placed before e-mail subject lines.
+- `SENDMAIL_PATH`: **sendmail**: The location of sendmail on the operating system (can be command or full path).
+- `SENDMAIL_ARGS`: **_empty_**: Specify any extra sendmail arguments. (NOTE: you should be aware that email addresses can look like options - if your `sendmail` command takes options you must set the option terminator `--`)
+- `SENDMAIL_TIMEOUT`: **5m**: default timeout for sending email through sendmail
+- `SENDMAIL_CONVERT_CRLF`: **true**: Most versions of sendmail prefer LF line endings rather than CRLF line endings. Set this to false if your version of sendmail requires CRLF line endings.
+- `SEND_BUFFER_LEN`: **100**: Buffer length of mailing queue. **DEPRECATED** use `LENGTH` in `[queue.mailer]`
+- `SEND_AS_PLAIN_TEXT`: **false**: Send mails only in plain text, without HTML alternative.
+- `EMBED_ATTACHMENT_IMAGES`: **false**: Embed attached images in base64 format in HTML emails. (for clients that do not load external images or disconnected vpn users still receiving emails; ATTENTION: online webclients like gmail will not show base64 embedded images)
+
+## Override Email Headers (`mailer.override_header`)
+
+:::warning
+This is empty by default, use it only if you know what you need it for.
+:::
+
+examples would be:
+
+```ini
+[mailer.override_header]
+Reply-To = test@example.com, test2@example.com
+Content-Type = text/html; charset=utf-8
+In-Reply-To =
+```
+
+## Incoming Email (`email.incoming`)
+
+- `ENABLED`: **false**: Enable handling of incoming emails.
+- `REPLY_TO_ADDRESS`: **_empty_**: The email address including the `%{token}` placeholder that will be replaced per user/action. Example: `incoming+%{token}@example.com`. The placeholder must appear in the user part of the address (before the `@`).
+- `HOST`: **_empty_**: IMAP server host.
+- `PORT`: **_empty_**: IMAP server port.
+- `USERNAME`: **_empty_**: Username of the receiving account.
+- `PASSWORD`: **_empty_**: Password of the receiving account.
+- `USE_TLS`: **false**: Whether the IMAP server uses TLS.
+- `SKIP_TLS_VERIFY`: **false**: If set to `true`, completely ignores server certificate validation errors. This option is unsafe.
+- `MAILBOX`: **INBOX**: The mailbox name where incoming mail will end up.
+- `DELETE_HANDLED_MESSAGE`: **true**: Whether handled messages should be deleted from the mailbox.
+- `MAXIMUM_MESSAGE_SIZE`: **10485760**: Maximum size of a message to handle. Bigger messages are ignored. Set to 0 to allow every size.
+
+## Cache (`cache`)
+
+- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
+- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory and twoqueue cache only.
+- `HOST`: **_empty_**: Connection string for `redis` and `memcache`. For `twoqueue` sets configuration for the queue.
+ - Redis: `redis://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (See [queue/CONN_STR](#queue-queue-and-queue) for information on additional supported connection types)
+ - For a Redis cluster: `redis+cluster://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
+ - For a Redis sentinel: `redis+sentinel://:macaron@sentinel0:26379,sentinel1:26379,sentinel2:26379/0?pool_size=100&idle_timeout=180s&master_name=mymaster`
+ - Memcache: `127.0.0.1:9090;127.0.0.1:9091`
+ - TwoQueue LRU cache: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000` representing the maximum number of objects stored in the cache.
+- `ITEM_TTL`: **16h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
+
+## Cache - LastCommitCache settings (`cache.last_commit`)
+
+- `ITEM_TTL`: **8760h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
+- `COMMITS_COUNT`: **1000**: Only enable the cache when repository's commits count great than.
+
+## Session (`session`)
+
+- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
+- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string. Relative paths will be made absolute against _`AppWorkPath`_.
+- `COOKIE_SECURE`:**_empty_**: `true` or `false`. Enable this to force using HTTPS for all session access. If not set, it defaults to `true` if the ROOT_URL is an HTTPS URL.
+- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
+- `GC_INTERVAL_TIME`: **86400**: GC interval in seconds.
+- `SESSION_LIFE_TIME`: **86400**: Session life time in seconds, default is 86400 (1 day)
+- `DOMAIN`: **_empty_**: Sets the cookie Domain
+- `SAME_SITE`: **lax** \[strict, lax, none\]: Set the SameSite setting for the cookie.
+
+## Picture (`picture`)
+
+- `GRAVATAR_SOURCE`: **gravatar**: Can be `gravatar`, `duoshuo` or anything like
+ `http://cn.gravatar.com/avatar/`.
+- `DISABLE_GRAVATAR`: **false**: Enable this to use local avatars only. **DEPRECATED [v1.18+]** moved to database. Use admin panel to configure.
+- `ENABLE_FEDERATED_AVATAR`: **false**: Enable support for federated avatars (see
+ [http://www.libravatar.org](http://www.libravatar.org)). **DEPRECATED [v1.18+]** moved to database. Use admin panel to configure.
+
+- `AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
+- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store user avatar image files.
+- `AVATAR_MAX_WIDTH`: **4096**: Maximum avatar image width in pixels.
+- `AVATAR_MAX_HEIGHT`: **4096**: Maximum avatar image height in pixels.
+- `AVATAR_MAX_FILE_SIZE`: **1048576** (1MiB): Maximum avatar image file size in bytes.
+- `AVATAR_MAX_ORIGIN_SIZE`: **262144** (256KiB): If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting.
+- `AVATAR_RENDERED_SIZE_FACTOR`: **2**: The multiplication factor for rendered avatar images. Larger values result in finer rendering on HiDPI devices.
+
+- `REPOSITORY_AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
+- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: Path to store repository avatar image files.
+- `REPOSITORY_AVATAR_FALLBACK`: **none**: How Gitea deals with missing repository avatars
+ - none = no avatar will be displayed
+ - random = random avatar will be generated
+ - image = default image will be used (which is set in `REPOSITORY_AVATAR_FALLBACK_IMAGE`)
+- `REPOSITORY_AVATAR_FALLBACK_IMAGE`: **/img/repo_default.png**: Image used as default repository avatar (if `REPOSITORY_AVATAR_FALLBACK` is set to image and none was uploaded)
+
+## Project (`project`)
+
+Default templates for project board view:
+
+- `PROJECT_BOARD_BASIC_KANBAN_TYPE`: **To Do, In Progress, Done**
+- `PROJECT_BOARD_BUG_TRIAGE_TYPE`: **Needs Triage, High Priority, Low Priority, Closed**
+
+## Issue and pull request attachments (`attachment`)
+
+- `ENABLED`: **true**: Whether issue and pull request attachments are enabled.
+- `ALLOWED_TYPES`: **.avif,.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
+- `MAX_SIZE`: **2048**: Maximum size (MB).
+- `MAX_FILES`: **5**: Maximum number of attachments that can be uploaded at once.
+- `STORAGE_TYPE`: **local**: Storage type for attachments, it could be ``, `local`, `minio`, `azureblob` or `xxx` which defined in another section with `[storage.xxx]`.
+
+ For `STORAGE_TYPE = ` or there is no this configuration item, all storages will be derived from `[storage]` if configured or defult values.
+
+ For `STORAGE_TYPE = local`, below are possible configurations
+
+ - `PATH`: **attachments**: Path to store attachments only available when STORAGE_TYPE is `local`, relative paths will be resolved to `{AppDataPath}/{attachment.PATH}`.
+
+ For `STORAGE_TYPE = minio`, the configurations can be found at [Storage Minio](#storage_minio), you can override some configurations like below.
+
+ - `MINIO_BASE_PATH`: **attachments/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
+
+ For `STORAGE_TYPE = xxx`, the configuration will be derived from `[storage.xxx]` and some configurations can be overrided list below.
+
+ - `PATH`: the same as above
+ - `MINIO_BASE_PATH`: the same as above
+
+## Log (`log`)
+
+- `ROOT_PATH`: **_empty_**: Root path for log files.
+- `MODE`: **console**: Logging mode. For multiple modes, use a comma to separate values. You can configure each mode in per mode log subsections `\[log.writer-mode-name\]`.
+- `LEVEL`: **Info**: General log level. \[Trace, Debug, Info, Warn, Error, Critical, Fatal, None\]
+- `STACKTRACE_LEVEL`: **None**: Default log level at which to log create stack traces (rarely useful, do not set it). \[Trace, Debug, Info, Warn, Error, Critical, Fatal, None\]
+- `ENABLE_SSH_LOG`: **false**: save ssh log to log file
+- `logger.access.MODE`: **_empty_**: The "access" logger
+- `logger.router.MODE`: **,**: The "router" logger, a single comma means it will use the default MODE above
+- `logger.xorm.MODE`: **,**: The "xorm" logger
+
+### Access Log (`log`)
+
+- `ACCESS_LOG_TEMPLATE`: **`{{.Ctx.RemoteHost}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}" "{{.Ctx.Req.UserAgent}}"`**: Sets the template used to create the access log.
+ - The following variables are available:
+ - `Ctx`: the `context.Context` of the request.
+ - `Identity`: the SignedUserName or `"-"` if not logged in.
+ - `Start`: the start time of the request.
+ - `ResponseWriter`: the responseWriter from the request.
+ - `RequestID`: the value matching REQUEST_ID_HEADERS(default: `-`, if not matched).
+ - You must be very careful to ensure that this template does not throw errors or panics as this template runs outside the panic/recovery script.
+- `REQUEST_ID_HEADERS`: **_empty_**: You can configure multiple values that are splited by comma here. It will match in the order of configuration, and the first match will be finally printed in the access log.
+ - e.g.
+ - In the Request Header: X-Request-ID: **test-id-123**
+ - Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
+ - Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
+
+### Log subsections (`log.`)
+
+- `MODE`: **name**: Sets the mode of this log writer - Defaults to the provided subsection name. This allows you to have two different file loggers at different levels.
+- `LEVEL`: **log.LEVEL**: Sets the log-level of this writer. Defaults to the `LEVEL` set in the global `[log]` section.
+- `STACKTRACE_LEVEL`: **log.STACKTRACE_LEVEL**: Sets the log level at which to log stack traces.
+- `EXPRESSION`: **""**: A regular expression to match either the function name, file or message. Defaults to empty. Only log messages that match the expression will be saved in the logger.
+- `FLAGS`: **stdflags**: A comma separated string representing the log flags. Defaults to `stdflags` which represents the prefix: `2009/01/23 01:23:23 ...a/b/c/d.go:23:runtime.Caller() [I]: message`. `none` means don't prefix log lines. See `modules/log/flags.go` for more information.
+- `PREFIX`: **""**: An additional prefix for every log line in this logger. Defaults to empty.
+- `COLORIZE`: **false**: Whether to colorize the log lines
+
+### Console log mode (`log.console`, or `MODE=console`)
+
+- For the console logger `COLORIZE` will default to `true` if not on windows or the terminal is determined to be able to color.
+- `STDERR`: **false**: Use Stderr instead of Stdout.
+
+### File log mode (`log.file`, or `MODE=file`)
+
+- `FILE_NAME`: Set the file name for this logger. Defaults to `gitea.log` (exception: access log defaults to `access.log`). If relative will be relative to the `ROOT_PATH`
+- `LOG_ROTATE`: **true**: Rotate the log files.
+- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb.
+- `DAILY_ROTATE`: **true**: Rotate logs daily.
+- `MAX_DAYS`: **7**: Delete the log file after n days
+- `COMPRESS`: **true**: Compress old log files by default with gzip
+- `COMPRESSION_LEVEL`: **-1**: Compression level
+
+### Conn log mode (`log.conn`, or `MODE=conn`)
+
+- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
+- `RECONNECT`: **false**: Try to reconnect when connection is lost.
+- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
+- `ADDR`: **:7020**: Sets the address to connect to.
+
+## Cron (`cron`)
+
+- `ENABLED`: **false**: Enable to run all cron tasks periodically with default settings.
+- `RUN_AT_START`: **false**: Run cron tasks at application start-up.
+- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
+- `SCHEDULE` accept formats
+ - Full crontab specs, e.g. `* * * * * ?`
+ - Descriptors, e.g. `@midnight`, `@every 1h30m` ...
+ - See more: [cron documentation](https://pkg.go.dev/github.com/gogs/cron@v0.0.0-20171120032916-9f6c956d3e14)
+
+### Basic cron tasks - enabled by default
+
+#### Cron - Cleanup old repository archives (`cron.archive_cleanup`)
+
+- `ENABLED`: **true**: Enable service.
+- `RUN_AT_START`: **true**: Run tasks at start up time (if ENABLED).
+- `NOTICE_ON_SUCCESS`: **false**: Whether to emit notice on successful execution too
+- `SCHEDULE`: **@midnight**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
+- `OLDER_THAN`: **24h**: Archives created more than `OLDER_THAN` ago are subject to deletion, e.g. `12h`.
+
+#### Cron - Update Mirrors (`cron.update_mirrors`)
+
+- `ENABLED`: **true**: Enable running Update mirrors task periodically.
+- `SCHEDULE`: **@every 10m**: Cron syntax for scheduling update mirrors, e.g. `@every 3h`.
+- `RUN_AT_START`: **false**: Run Update mirrors task when Gitea starts.
+- `NOTICE_ON_SUCCESS`: **false**: Notice if not success
+- `PULL_LIMIT`: **50**: Limit the number of mirrors added to the queue to this number (negative values mean no limit, 0 will result in no mirrors being queued effectively disabling pull mirror updating).
+- `PUSH_LIMIT`: **50**: Limit the number of mirrors added to the queue to this number (negative values mean no limit, 0 will result in no mirrors being queued effectively disabling push mirror updating).
+
+#### Cron - Repository Health Check (`cron.repo_health_check`)
+
+- `ENABLED`: **true**: Enable running Update mirrors task periodically.
+- `SCHEDULE`: **@midnight**: Cron syntax for scheduling repository health check.
+- `RUN_AT_START`: **false**: Run Update mirrors task when Gitea starts.
+- `NOTICE_ON_SUCCESS`: **false**: Notice if not success
+- `TIMEOUT`: **60s**: Time duration syntax for health check execution timeout.
+- `ARGS`: **_empty_**: Arguments for command `git fsck`, e.g. `--unreachable --tags`. See more on http://git-scm.com/docs/git-fsck
+
+#### Cron - Repository Statistics Check (`cron.check_repo_stats`)
+
+- `SCHEDULE`: **@midnight**: Cron syntax for scheduling repository statistics check.
+- `ENABLED`: **true**: Enable running Update mirrors task periodically.
+- `RUN_AT_START`: **true**: Run Update mirrors task when Gitea starts.
+- `NOTICE_ON_SUCCESS`: **false**: Notice if not success
+
+#### Cron - Cleanup hook_task Table (`cron.cleanup_hook_task_table`)
+
+- `ENABLED`: **true**: Enable cleanup hook_task job.
+- `RUN_AT_START`: **false**: Run cleanup hook_task at start time (if ENABLED).
+- `SCHEDULE`: **@midnight**: Cron syntax for cleaning hook_task table.
+- `CLEANUP_TYPE` **OlderThan** OlderThan or PerWebhook Method to cleanup hook_task, either by age (i.e. how long ago hook_task record was delivered) or by the number to keep per webhook (i.e. keep most recent x deliveries per webhook).
+- `OLDER_THAN`: **168h**: If CLEANUP_TYPE is set to OlderThan, then any delivered hook_task records older than this expression will be deleted.
+- `NUMBER_TO_KEEP`: **10**: If CLEANUP_TYPE is set to PerWebhook, this is number of hook_task records to keep for a webhook (i.e. keep the most recent x deliveries).
+
+#### Cron - Cleanup expired packages (`cron.cleanup_packages`)
+
+- `ENABLED`: **true**: Enable cleanup expired packages job.
+- `RUN_AT_START`: **true**: Run job at start time (if ENABLED).
+- `NOTICE_ON_SUCCESS`: **false**: Notify every time this job runs.
+- `SCHEDULE`: **@midnight**: Cron syntax for the job.
+- `OLDER_THAN`: **24h**: Unreferenced package data created more than OLDER_THAN ago is subject to deletion.
+
+#### Cron - Update Migration Poster ID (`cron.update_migration_poster_id`)
+
+Update migrated repositories' issues and comments' posterid, it will always attempt synchronization when the instance starts.
+
+- `ENABLED`: **true**: Enable update migration poster id job.
+- `RUN_AT_START`: **true**: Update migrated repositories' issues and comments' posterid when starting server
+- `NOTICE_ON_SUCCESS`: **false**: Notice if not success
+- `SCHEDULE`: **@midnight** : Interval as a duration between each synchronization, it will always attempt synchronization when the instance starts.
+
+#### Cron - Sync External Users (`cron.sync_external_users`)
+
+Synchronize external user data (only LDAP user synchronization is supported)
+
+- `ENABLED`: **true**: Enable synchronize external user data job
+- `RUN_AT_START`: **false**: Synchronize external user data when starting server
+- `NOTICE_ON_SUCCESS`: **false**: Notice if not success
+- `SCHEDULE`: **@midnight** : Interval as a duration between each synchronization, it will always attempt synchronization when the instance starts.
+- `UPDATE_EXISTING`: **true**: Create new users, update existing user data and disable users that are not in external source anymore (default) or only create new users if UPDATE_EXISTING is set to false.
+
+#### Cron - Cleanup Expired Actions Assets (`cron.cleanup_actions`)
+
+- `ENABLED`: **true**: Enable cleanup expired actions assets job.
+- `RUN_AT_START`: **true**: Run job at start time (if ENABLED).
+- `SCHEDULE`: **@midnight** : Cron syntax for the job.
+
+#### Cron - Cleanup Deleted Branches (`cron.deleted_branches_cleanup`)
+
+- `ENABLED`: **true**: Enable deleted branches cleanup.
+- `RUN_AT_START`: **true**: Run job at start time (if ENABLED).
+- `NOTICE_ON_SUCCESS`: **false**: Set to true to log a success message.
+- `SCHEDULE`: **@midnight**: Cron syntax for scheduling deleted branches cleanup.
+- `OLDER_THAN`: **24h**: Branches deleted OLDER_THAN ago will be cleaned up.
+
+### Extended cron tasks
+
+#### Cron - Delete all repository archives (`cron.delete_repo_archives`)
+
+- `ENABLED`: **false**: Enable service.
+- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
+- `NOTICE_ON_SUCCESS`: **false**: Set to true to enable success notices.
+- `SCHEDULE`: **@annually**: Cron schedule for deleting all repository archives, e.g. `@annually`.
+
+#### Cron - Garbage collect all repositories (`cron.git_gc_repos`)
+
+- `ENABLED`: **false**: Enable service.
+- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
+- `SCHEDULE`: **@every 72h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
+- `TIMEOUT`: **60s**: Time duration syntax for garbage collection execution timeout.
+- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
+- `ARGS`: **_empty_**: Arguments for command `git gc`, e.g. `--aggressive --auto`. The default value is same with [git] -> GC_ARGS
+
+#### Cron - Update the '.ssh/authorized_keys' file with Gitea SSH keys (`cron.resync_all_sshkeys`)
+
+- `ENABLED`: **false**: 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 72h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
+
+#### Cron - Resynchronize pre-receive, update and post-receive hooks of all repositories (`cron.resync_all_hooks`)
+
+- `ENABLED`: **false**: 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 72h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
+
+#### Cron - Reinitialize all missing Git repositories for which records exist (`cron.reinit_missing_repos`)
+
+- `ENABLED`: **false**: 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 72h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
+
+#### Cron - Delete all repositories missing their Git files (`cron.delete_missing_repos`)
+
+- `ENABLED`: **false**: 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 72h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
+
+#### Cron - Delete generated repository avatars (`cron.delete_generated_repository_avatars`)
+
+- `ENABLED`: **false**: 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 72h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
+
+#### Cron - Delete all old actions from database (`cron.delete_old_actions`)
+
+- `ENABLED`: **false**: 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 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.
+
+#### Cron - Check for new Gitea versions (`cron.update_checker`)
+
+- `ENABLED`: **true**: Enable service.
+- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
+- `ENABLE_SUCCESS_NOTICE`: **true**: Set to false to switch off success notices.
+- `SCHEDULE`: **@every 168h**: Cron syntax for scheduling a work, e.g. `@every 168h`.
+- `HTTP_ENDPOINT`: **https://dl.gitea.com/gitea/version.json**: the endpoint that Gitea will check for newer versions
+
+#### Cron - Delete all old system notices from database (`cron.delete_old_system_notices`)
+
+- `ENABLED`: **false**: Enable service.
+- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
+- `NO_SUCCESS_NOTICE`: **false**: Set to true to switch off success notices.
+- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
+- `OLDER_THAN`: **8760h**: any system notice older than this expression will be deleted from database.
+
+#### Cron - Garbage collect LFS pointers in repositories (`cron.gc_lfs`)
+
+- `ENABLED`: **false**: Enable service.
+- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
+- `SCHEDULE`: **@every 24h**: Cron syntax to set how often to check.
+- `OLDER_THAN`: **168h**: Only attempt to garbage collect LFSMetaObjects older than this (default 7 days)
+- `LAST_UPDATED_MORE_THAN_AGO`: **72h**: Only attempt to garbage collect LFSMetaObjects that have not been attempted to be garbage collected for this long (default 3 days)
+- `NUMBER_TO_CHECK_PER_REPO`: **100**: Minimum number of stale LFSMetaObjects to check per repo. Set to `0` to always check all.
+- `PROPORTION_TO_CHECK_PER_REPO`: **0.6**: Check at least this proportion of LFSMetaObjects per repo. (This may cause all stale LFSMetaObjects to be checked.)
+
+## Git (`git`)
+
+- `PATH`: **""**: The path of Git executable. If empty, Gitea searches through the PATH environment.
+- `HOME_PATH`: **`{APP_DATA_PATH}/home`**: The HOME directory for Git.
+ This directory will be used to contain the `.gitconfig` and possible `.gnupg` directories that Gitea's git calls will use. If you can confirm Gitea is the only application running in this environment, you can set it to the normal home directory for Gitea user.
+- `DISABLE_DIFF_HIGHLIGHT`: **false**: Disables highlight of added and removed changes.
+- `MAX_GIT_DIFF_LINES`: **1000**: Max number of lines allowed of a single file in diff view.
+- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
+- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
+- `COMMITS_RANGE_SIZE`: **50**: Set the default commits range size
+- `BRANCHES_RANGE_SIZE`: **20**: Set the default branches range size
+- `GC_ARGS`: **_empty_**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
+- `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: If use Git wire protocol version 2 when Git version >= 2.18, default is true, set to false when you always want Git wire protocol version 1.
+ To enable this for Git over SSH when using a OpenSSH server, add `AcceptEnv GIT_PROTOCOL` to your sshd_config file.
+- `PULL_REQUEST_PUSH_MESSAGE`: **true**: Respond to pushes to a non-default branch with a URL for creating a Pull Request (if the repository has them enabled)
+- `VERBOSE_PUSH`: **true**: Print status information about pushes as they are being processed.
+- `VERBOSE_PUSH_DELAY`: **5s**: Only print verbose information if push takes longer than this delay.
+- `LARGE_OBJECT_THRESHOLD`: **1048576**: (Go-Git only), don't cache objects greater than this in memory. (Set to 0 to disable.)
+- `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false.
+- `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git.
+
+### Git - Timeout settings (`git.timeout`)
+
+- `DEFAULT`: **360**: Git operations default timeout seconds.
+- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
+- `MIRROR`: **300**: Mirror external repositories timeout seconds.
+- `CLONE`: **300**: Git clone from internal repositories timeout seconds.
+- `PULL`: **300**: Git pull from internal repositories timeout seconds.
+- `GC`: **60**: Git repository GC timeout seconds.
+
+### Git - Config options (`git.config`)
+
+The key/value pairs in this section will be used as git config.
+This section only does "set" config, a removed config key from this section won't be removed from git config automatically. The format is `some.configKey = value`.
+
+- `diff.algorithm`: **histogram**
+- `core.logAllRefUpdates`: **true**
+- `gc.reflogExpire`: **90**
+
+## Metrics (`metrics`)
+
+- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
+- `ENABLED_ISSUE_BY_LABEL`: **false**: Enable issue by label metrics with format `gitea_issues_by_label{label="bug"} 2`.
+- `ENABLED_ISSUE_BY_REPOSITORY`: **false**: Enable issue by repository metrics with format `gitea_issues_by_repository{repository="org/repo"} 5`.
+- `TOKEN`: **_empty_**: You need to specify the token, if you want to include in the authorization the metrics . The same token need to be used in prometheus parameters `bearer_token` or `bearer_token_file`.
+
+## API (`api`)
+
+- `ENABLE_SWAGGER`: **true**: Enables the API documentation endpoints (`/api/swagger`, `/api/v1/swagger`, …). True or false.
+- `MAX_RESPONSE_ITEMS`: **50**: Max number of items in a page.
+- `DEFAULT_PAGING_NUM`: **30**: Default paging number of API.
+- `DEFAULT_GIT_TREES_PER_PAGE`: **1000**: Default and maximum number of items per page for Git trees API.
+- `DEFAULT_MAX_BLOB_SIZE`: **10485760** (10MiB): Default max size of a blob that can be returned by the blobs API.
+
+## OAuth2 (`oauth2`)
+
+- `ENABLED`: **true**: Enables OAuth2 provider.
+- `ACCESS_TOKEN_EXPIRATION_TIME`: **3600**: Lifetime of an OAuth2 access token in seconds
+- `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 refresh token in hours
+- `INVALIDATE_REFRESH_TOKENS`: **false**: Check if refresh token has already been used
+- `JWT_SIGNING_ALGORITHM`: **RS256**: Algorithm used to sign OAuth2 tokens. Valid values: \[`HS256`, `HS384`, `HS512`, `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`\]
+- `JWT_SECRET`: **_empty_**: OAuth2 authentication secret for access and refresh tokens, change this to a unique string. This setting is only needed if `JWT_SIGNING_ALGORITHM` is set to `HS256`, `HS384` or `HS512`.
+- `JWT_SECRET_URI`: **_empty_**: Instead of defining JWT_SECRET in the configuration, this configuration option can be used to give Gitea a path to a file that contains the secret (example value: `file:/etc/gitea/oauth2_jwt_secret`)
+- `JWT_SIGNING_PRIVATE_KEY_FILE`: **jwt/private.pem**: Private key file path used to sign OAuth2 tokens. The path is relative to `APP_DATA_PATH`. This setting is only needed if `JWT_SIGNING_ALGORITHM` is set to `RS256`, `RS384`, `RS512`, `ES256`, `ES384` or `ES512`. The file must contain a RSA or ECDSA private key in the PKCS8 format. If no key exists a 4096 bit key will be created for you.
+- `MAX_TOKEN_LENGTH`: **32767**: Maximum length of token/cookie to accept from OAuth2 provider
+- `DEFAULT_APPLICATIONS`: **git-credential-oauth, git-credential-manager, tea**: Pre-register OAuth applications for some services on startup. See the [OAuth2 documentation](/development/oauth2-provider.md) for the list of available options.
+
+## i18n (`i18n`)
+
+- `LANGS`: **en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sv-SE,ko-KR,el-GR,fa-IR,hu-HU,id-ID,ml-IN**:
+ List of locales shown in language selector. The first locale will be used as the default if user browser's language doesn't match any locale in the list.
+- `NAMES`: **English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,Français,Nederlands,Latviešu,Русский,Українська,日本語,Español,Português do Brasil,Português de Portugal,Polski,Български,Italiano,Suomi,Türkçe,Čeština,Српски,Svenska,한국어,Ελληνικά,فارسی,Magyar nyelv,Bahasa Indonesia,മലയാളം**: Visible names corresponding to the locales
+
+## Markup (`markup`)
+
+- `MERMAID_MAX_SOURCE_CHARACTERS`: **50000**: Set the maximum size of a Mermaid source. (Set to -1 to disable)
+
+## Markup External Render (`markup.external-render-name`)
+
+Gitea can support Markup using external tools. The example below will add a markup named `asciidoc`.
+
+```ini
+[markup.asciidoc]
+ENABLED = true
+NEED_POSTPROCESS = true
+FILE_EXTENSIONS = .adoc,.asciidoc
+RENDER_COMMAND = "asciidoctor --embedded --safe-mode=secure --out-file=- -"
+IS_INPUT_FILE = false
+```
+
+- ENABLED: **false** Enable markup support; set to **true** to enable this renderer.
+- FILE\_EXTENSIONS: **_empty_** List of file extensions that should be rendered by an external
+ command. Multiple extensions needs a comma as splitter.
+- RENDER\_COMMAND: External command to render all matching extensions.
+- IS\_INPUT\_FILE: **false** Input is not a standard input but a file param followed `RENDER_COMMAND`.
+- RENDER_CONTENT_MODE: **sanitized** How the content will be rendered.
+ - sanitized: Sanitize the content and render it inside current page, default to only allow a few HTML tags and attributes. Customized sanitizer rules can be defined in `[markup.sanitizer.*]`.
+ - no-sanitizer: Disable the sanitizer and render the content inside current page. It's **insecure** and may lead to XSS attack if the content contains malicious code.
+ - iframe: Render the content in a separate standalone page and embed it into current page by iframe. The iframe is in sandbox mode with same-origin disabled, and the JS code are safely isolated from parent page.
+- RENDER_CONTENT_SANDBOX: **_empty_** The sandbox applied to the iframe and Content-Security-Policy header when RENDER_CONTENT_MODE is `iframe`. It defaults to a safe set of "allow-*" restrictions (space separated). You can also set it by your requirements or use "disabled" to disable the sandbox completely. When set it, make sure there is no security risk:
+ - PDF-only content: generally safe to use "disabled", and it needs to be "disabled" because PDF only renders with no sandbox.
+ - HTML content with JS: if the "RENDER_COMMAND" can guarantee there is no XSS, then it is safe, otherwise, you need to fine tune the "allow-*" restrictions.
+- NEED_POST_PROCESS: **false** Whether post-process the rendered HTML content, including: resolve relative links and image sources, recognizing issue/commit references, escaping invisible characters, mentioning users, rendering permlink code blocks, replacing emoji shorthands, etc. By default, this is true when RENDER_CONTENT_MODE is `sanitized`, otherwise false.
+
+Two special environment variables are passed to the render command:
+
+- `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links.
+- `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths.
+
+If `RENDER_CONTENT_MODE` is `sanitized`, Gitea supports customizing the sanitization policy for rendered HTML. The example below will support KaTeX output from pandoc.
+
+```ini
+[markup.sanitizer.TeX]
+; Pandoc renders TeX segments as s with the "math" class, optionally
+; with "inline" or "display" classes depending on context.
+ELEMENT = span
+ALLOW_ATTR = class
+REGEXP = ^\s*((math(\s+|$)|inline(\s+|$)|display(\s+|$)))+
+ALLOW_DATA_URI_IMAGES = true
+```
+
+- `ELEMENT`: The element this policy applies to. Must be non-empty.
+- `ALLOW_ATTR`: The attribute this policy allows. Must be non-empty.
+- `REGEXP`: A regex to match the contents of the attribute against. Must be present but may be empty for unconditional whitelisting of this attribute.
+- `ALLOW_DATA_URI_IMAGES`: **false** Allow data uri images (`
`).
+
+Multiple sanitisation rules can be defined by adding unique subsections, e.g. `[markup.sanitizer.TeX-2]`.
+To apply a sanitisation rules only for a specify external renderer they must use the renderer name, e.g. `[markup.sanitizer.asciidoc.rule-1]`.
+If the rule is defined above the renderer ini section or the name does not match a renderer it is applied to every renderer.
+
+## Highlight Mappings (`highlight.mapping`)
+
+- `file_extension e.g. .toml`: **language e.g. ini**. File extension to language mapping overrides.
+
+- Gitea will highlight files using the `linguist-language` or `gitlab-language` attribute from the `.gitattributes` file
+if available. If this is not set or the language is unavailable, the file extension will be looked up
+in this mapping or the filetype using heuristics.
+
+## Time (`time`)
+
+- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai
+
+## Migrations (`migrations`)
+
+- `MAX_ATTEMPTS`: **3**: Max attempts per http/https request on migrations.
+- `RETRY_BACKOFF`: **3**: Backoff time per http/https request retry (seconds)
+- `ALLOWED_DOMAINS`: **_empty_**: Domains allowlist for migrating repositories, default is blank. It means external hosts will be allowed. Multiple domains could be separated by commas. Wildcard is supported: `github.com, *.github.com`.
+- `BLOCKED_DOMAINS`: **_empty_**: Domains blocklist for migrating repositories, default is blank. Multiple domains could be separated by commas. When `ALLOWED_DOMAINS` is not blank, this option has a higher priority to deny domains. Wildcard is supported.
+- `ALLOW_LOCALNETWORKS`: **false**: Allow private addresses defined by RFC 1918, RFC 1122, RFC 4632 and RFC 4291. If a domain is allowed by `ALLOWED_DOMAINS`, this option will be ignored.
+- `SKIP_TLS_VERIFY`: **false**: Allow skip tls verify
+
+## Federation (`federation`)
+
+- `ENABLED`: **false**: Enable/Disable federation capabilities
+- `SHARE_USER_STATISTICS`: **true**: Enable/Disable user statistics for nodeinfo if federation is enabled
+- `MAX_SIZE`: **4**: Maximum federation request and response size (MB)
+
+ :::warning
+ Changing the settings below can break federation.
+ :::
+
+- `ALGORITHMS`: **rsa-sha256, rsa-sha512, ed25519**: HTTP signature algorithms
+- `DIGEST_ALGORITHM`: **SHA-256**: HTTP signature digest algorithm
+- `GET_HEADERS`: **(request-target), Date**: GET headers for federation requests
+- `POST_HEADERS`: **(request-target), Date, Digest**: POST headers for federation requests
+
+## Packages (`packages`)
+
+- `ENABLED`: **true**: Enable/Disable package registry capabilities
+- `CHUNKED_UPLOAD_PATH`: **tmp/package-upload**: Path for chunked uploads. Defaults to `APP_DATA_PATH` + `tmp/package-upload`
+- `LIMIT_TOTAL_OWNER_COUNT`: **-1**: Maximum count of package versions a single owner can have (`-1` means no limits)
+- `LIMIT_TOTAL_OWNER_SIZE`: **-1**: Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_ALPINE`: **-1**: Maximum size of an Alpine upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_CARGO`: **-1**: Maximum size of a Cargo upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_CHEF`: **-1**: Maximum size of a Chef upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_COMPOSER`: **-1**: Maximum size of a Composer upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_CONAN`: **-1**: Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_CONDA`: **-1**: Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_CONTAINER`: **-1**: Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_CRAN`: **-1**: Maximum size of a CRAN upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_DEBIAN`: **-1**: Maximum size of a Debian upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_GENERIC`: **-1**: Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_GO`: **-1**: Maximum size of a Go upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_HELM`: **-1**: Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_MAVEN`: **-1**: Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_NPM`: **-1**: Maximum size of a npm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_NUGET`: **-1**: Maximum size of a NuGet upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_PUB`: **-1**: Maximum size of a Pub upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_PYPI`: **-1**: Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_RPM`: **-1**: Maximum size of a RPM upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_RUBYGEMS`: **-1**: Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_SWIFT`: **-1**: Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+- `LIMIT_SIZE_VAGRANT`: **-1**: Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+
+## Mirror (`mirror`)
+
+- `ENABLED`: **true**: Enables the mirror functionality. Set to **false** to disable all mirrors. Pre-existing mirrors remain valid but won't be updated; may be converted to regular repo.
+- `DISABLE_NEW_PULL`: **false**: Disable the creation of **new** pull mirrors. Pre-existing mirrors remain valid. Will be ignored if `mirror.ENABLED` is `false`.
+- `DISABLE_NEW_PUSH`: **false**: Disable the creation of **new** push mirrors. Pre-existing mirrors remain valid. Will be ignored if `mirror.ENABLED` is `false`.
+- `DEFAULT_INTERVAL`: **8h**: Default interval between each check
+- `MIN_INTERVAL`: **10m**: Minimum interval for checking. (Must be >1m).
+
+## LFS (`lfs`)
+
+Storage configuration for lfs data. It will be derived from default `[storage]` or
+`[storage.xxx]` when set `STORAGE_TYPE` to `xxx`. When derived, the default of `PATH`
+is `data/lfs` and the default of `MINIO_BASE_PATH` is `lfs/`.
+
+- `STORAGE_TYPE`: **local**: Storage type for lfs, it could be ``, `local`, `minio`, `azureblob` or `xxx` which defined in another section with `[storage.xxx]`.
+
+ For `STORAGE_TYPE = ` or there is no this configuration item, all storages will be derived from `[storage]` if configured or defult values.
+
+ For `STORAGE_TYPE = local`, below are possible configurations
+
+- `PATH`: **./data/lfs**: Where to store LFS files, only available when `STORAGE_TYPE` is `local`. If not set it fall back to deprecated LFS_CONTENT_PATH value in [server] section.
+
+ For `STORAGE_TYPE = minio`, the configurations can be found at [Storage Minio](#storage_minio), you can also define configurations like below to override derived or default values.
+
+ - `MINIO_BASE_PATH`: **attachments/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
+
+ For `STORAGE_TYPE = xxx`, the configuration will be derived from `[storage.xxx]` and some configurations can be overrided list below.
+
+- `PATH`: the same as above
+- `MINIO_BASE_PATH`: the same as above
+
+## LFS Client (`lfs_client`)
+
+- `BATCH_SIZE`: **20**: The number of LFS pointers to request per batch API request of an upstream mirror.
+- `BATCH_OPERATION_CONCURRENCY`: **8**: The number of concurrent upload/download operations within a batch.
+
+## Storage (`storage`)
+
+Default storage configuration for `attachments`, `lfs`, `avatars`, `repo-avatars`, `repo-archive`, `packages`, `actions_log`, `actions_artifact`. It's recommended to only configure this section and let other section derive from this one if all storages
+are under the same parent directory or minio bucket.
+
+- `STORAGE_TYPE`: **local**: Storage type, `local` for local disk, `minio` for s3 compatible object storage service, `azureblob` for azure blob storage service.
+
+### Minio Storage Configuration (`storage_minio`)
+
+- `SERVE_DIRECT`: **false**: Allows the storage driver to redirect to authenticated URLs to serve files directly. Currently, only Minio/S3 is supported via signed URLs, local does nothing.
+- `MINIO_ENDPOINT`: **localhost:9000**: Minio endpoint to connect only available when `STORAGE_TYPE` is `minio`
+- `MINIO_ACCESS_KEY_ID`: Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`. If not provided and STORAGE_TYPE is `minio`, will search for credentials in known environment variables (MINIO_ACCESS_KEY_ID, AWS_ACCESS_KEY_ID), credentials files (~/.mc/config.json, ~/.aws/credentials), and EC2 instance metadata.
+- `MINIO_SECRET_ACCESS_KEY`: Minio secretAccessKey to connect only available when `STORAGE_TYPE is` `minio`
+- `MINIO_IAM_ENDPOINT`: Preferred IAM Endpoint to override Minio's default IAM Endpoint resolution only available when STORAGE_TYPE is `minio`. If not provided and STORAGE_TYPE is `minio`, will search for and derive endpoint from known environment variables (AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, AWS_ROLE_SESSION_NAME, AWS_REGION), or the DefaultIAMRoleEndpoint if not provided otherwise.
+- `MINIO_BUCKET`: **gitea**: Minio bucket to store the data only available when `STORAGE_TYPE` is `minio`
+- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket only available when `STORAGE_TYPE` is `minio`
+- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
+- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
+- `MINIO_BUCKET_LOOKUP_TYPE`: **auto**: Minio bucket lookup method defaults to auto mode; set it to `dns` for virtual host style or `path` for path style, only available when STORAGE_TYPE is `minio`
+
+The recommended storage configuration for minio like below:
+
+```ini
+[storage]
+STORAGE_TYPE = minio
+; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
+MINIO_ENDPOINT = localhost:9000
+; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`.
+; If not provided and STORAGE_TYPE is `minio`, will search for credentials in known
+; environment variables (MINIO_ACCESS_KEY_ID, AWS_ACCESS_KEY_ID), credentials files
+; (~/.mc/config.json, ~/.aws/credentials), and EC2 instance metadata.
+MINIO_ACCESS_KEY_ID =
+; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio`
+MINIO_SECRET_ACCESS_KEY =
+; Preferred IAM Endpoint to override Minio's default IAM Endpoint resolution only available when STORAGE_TYPE is `minio`.
+; If not provided and STORAGE_TYPE is `minio`, will search for and derive endpoint from known environment variables
+; (AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,
+; AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, AWS_ROLE_SESSION_NAME, AWS_REGION), or
+; the DefaultIAMRoleEndpoint if not provided otherwise.
+MINIO_IAM_ENDPOINT =
+; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio`
+MINIO_BUCKET = gitea
+; Minio location to create bucket only available when STORAGE_TYPE is `minio`
+MINIO_LOCATION = us-east-1
+; Minio enabled ssl only available when STORAGE_TYPE is `minio`
+MINIO_USE_SSL = false
+; Minio skip SSL verification available when STORAGE_TYPE is `minio`
+MINIO_INSECURE_SKIP_VERIFY = false
+SERVE_DIRECT = true
+; Minio bucket lookup method defaults to auto mode; set it to `dns` for virtual host style or `path` for path style, only available when STORAGE_TYPE is `minio`
+MINIO_BUCKET_LOOKUP_TYPE = auto
+```
+
+### Azure Blob Storage Configuration (`storage_azureblob`)
+
+- `SERVE_DIRECT`: **false**: Allows the storage driver to redirect to authenticated URLs to serve files directly. Currently, only Minio/S3 is supported via signed URLs, local does nothing.
+- `AZURE_BLOB_ENDPOINT`: **_empty_**: Azure Blob endpoint to connect only available when STORAGE_TYPE is `azureblob`,
+ e.g. https://accountname.blob.core.windows.net or http://127.0.0.1:10000/devstoreaccount1
+- `AZURE_BLOB_ACCOUNT_NAME`: **_empty_**: Azure Blob account name to connect only available when STORAGE_TYPE is `azureblob`
+- `AZURE_BLOB_ACCOUNT_KEY`: **_empty_**: Azure Blob account key to connect only available when STORAGE_TYPE is `azureblob`
+- `AZURE_BLOB_CONTAINER`: **gitea**: Azure Blob container to store the data only available when STORAGE_TYPE is `azureblob`
+
+### Overrided Configurations (`storage_override`)
+
+The override could have 3 levels. `[LFS]/[attachment]...` >> `[storage.xxx]` >> `[storage]` >> Default Values.
+
+Defaultly every storage has their default base path like below
+
+| storage | default base path |
+| ----------------- | ------------------ |
+| attachments | attachments/ |
+| lfs | lfs/ |
+| avatars | avatars/ |
+| repo-avatars | repo-avatars/ |
+| repo-archive | repo-archive/ |
+| packages | packages/ |
+| actions_log | actions_log/ |
+| actions_artifacts | actions_artifacts/ |
+
+And bucket, basepath or `SERVE_DIRECT` could be special or overridden, if you want to use a different you can:
+
+```ini
+[storage.actions_log]
+MINIO_BUCKET = gitea_actions_log
+SERVE_DIRECT = true
+MINIO_BASE_PATH = my_actions_log/ ; default is actions_log/ if blank
+```
+
+If you want to customerize a different storage for `lfs` if above default storage defined
+
+```ini
+[lfs]
+STORAGE_TYPE = my_minio
+
+[storage.my_minio]
+STORAGE_TYPE = minio
+; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
+MINIO_ENDPOINT = localhost:9000
+; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`.
+; If not provided and STORAGE_TYPE is `minio`, will search for credentials in known
+; environment variables (MINIO_ACCESS_KEY_ID, AWS_ACCESS_KEY_ID), credentials files
+; (~/.mc/config.json, ~/.aws/credentials), and EC2 instance metadata.
+MINIO_ACCESS_KEY_ID =
+; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio`
+MINIO_SECRET_ACCESS_KEY =
+; Preferred IAM Endpoint to override Minio's default IAM Endpoint resolution only available when STORAGE_TYPE is `minio`.
+; If not provided and STORAGE_TYPE is `minio`, will search for and derive endpoint from known environment variables
+; (AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,
+; AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, AWS_ROLE_SESSION_NAME, AWS_REGION), or
+; the DefaultIAMRoleEndpoint if not provided otherwise.
+MINIO_IAM_ENDPOINT =
+; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio`
+MINIO_BUCKET = gitea
+; Minio location to create bucket only available when STORAGE_TYPE is `minio`
+MINIO_LOCATION = us-east-1
+; Minio enabled ssl only available when STORAGE_TYPE is `minio`
+MINIO_USE_SSL = false
+; Minio skip SSL verification available when STORAGE_TYPE is `minio`
+MINIO_INSECURE_SKIP_VERIFY = false
+; Minio bucket lookup method defaults to auto mode; set it to `dns` for virtual host style or `path` for path style, only available when STORAGE_TYPE is `minio`
+MINIO_BUCKET_LOOKUP_TYPE = auto
+```
+
+## Repository Archive Storage (`storage.repo-archive`)
+
+Configuration for repository archive storage. It will inherit from default `[storage]` or
+`[storage.xxx]` when set `STORAGE_TYPE` to `xxx`. The default of `PATH`
+is `data/repo-archive` and the default of `MINIO_BASE_PATH` is `repo-archive/`.
+
+- `STORAGE_TYPE`: **local**: Storage type for repo archive, it could be ``, `local`, `minio`, `azureblob` or `xxx` which defined in another section with `[storage.xxx]`.
+
+ For `STORAGE_TYPE = ` or there is no this configuration item, all storages will be derived from `[storage]` if configured or defult values.
+
+ For `STORAGE_TYPE = local`, below are possible configurations
+
+ - `PATH`: **./data/repo-archive**: Where to store archive files, only available when `STORAGE_TYPE` is `local`.
+
+ For `STORAGE_TYPE = minio`, the configurations can be found at [Storage Minio](#storage_minio), you can override some configurations like below.
+
+ - `MINIO_BASE_PATH`: **repo-archive/**: Minio base path on the bucket only available when `STORAGE_TYPE` is `minio`
+
+ For `STORAGE_TYPE = xxx`, the configuration will be derived from `[storage.xxx]` and some configurations can be overrided list below.
+
+ - `PATH`: the same as above
+ - `MINIO_BASE_PATH`: the same as above
+
+## Repository Archives (`repo-archive`)
+
+- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
+- `MINIO_BASE_PATH`: **repo-archive/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
+
+## Proxy (`proxy`)
+
+- `PROXY_ENABLED`: **false**: Enable the proxy if true, all requests to external via HTTP will be affected, if false, no proxy will be used even environment http_proxy/https_proxy
+- `PROXY_URL`: **_empty_**: Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy
+- `PROXY_HOSTS`: **_empty_**: Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
+
+i.e.
+
+```ini
+PROXY_ENABLED = true
+PROXY_URL = socks://127.0.0.1:1080
+PROXY_HOSTS = *.github.com
+```
+
+## Actions (`actions`)
+
+- `ENABLED`: **true**: Enable/Disable actions capabilities
+- `DEFAULT_ACTIONS_URL`: **github**: Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
+- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
+- `MINIO_BASE_PATH`: **actions_log/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
+- `LOG_RETENTION_DAYS`: **365**: Logs retention time in days. Old logs will be deleted after this period.
+- `LOG_COMPRESSION`: **zstd**: Log compression type, `none` for no compression, `zstd` for zstd compression.
+ Other compression types like `gzip` are NOT supported, since seekable stream is required for log view.
+ It's always recommended to use compression when using local disk as log storage if CPU or memory is not a bottleneck.
+ And for object storage services like S3, which is billed for requests, it would cause extra 2 times of get requests for each log view.
+ But it will save storage space and network bandwidth, so it's still recommended to use compression.
+- `ARTIFACT_RETENTION_DAYS`: **90**: Default number of days to keep artifacts. Artifacts could have their own retention periods by setting the `retention-days` option in `actions/upload-artifact` step.
+- `ZOMBIE_TASK_TIMEOUT`: **10m**: Timeout to stop the task which have running status, but haven't been updated for a long time
+- `ENDLESS_TASK_TIMEOUT`: **3h**: Timeout to stop the tasks which have running status and continuous updates, but don't end for a long time
+- `ABANDONED_JOB_TIMEOUT`: **24h**: Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time
+- `SKIP_WORKFLOW_STRINGS`: **[skip ci],[ci skip],[no ci],[skip actions],[actions skip]**: Strings committers can place inside a commit message or PR title to skip executing the corresponding actions workflow
+
+`DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path.
+For example, `uses: actions/checkout@v4` means `https://github.com/actions/checkout@v4` since the value of `DEFAULT_ACTIONS_URL` is `github`.
+And it can be changed to `self` to make it `root_url_of_your_gitea/actions/checkout@v4`.
+
+Please note that using `self` is not recommended for most cases, as it could make names globally ambiguous.
+Additionally, it requires you to mirror all the actions you need to your Gitea instance, which may not be worth it.
+Therefore, please use `self` only if you understand what you are doing.
+
+In earlier versions (`<= 1.19`), `DEFAULT_ACTIONS_URL` could be set to any custom URLs like `https://gitea.com` or `http://your-git-server,https://gitea.com`, and the default value was `https://gitea.com`.
+However, later updates removed those options, and now the only options are `github` and `self`, with the default value being `github`.
+However, if you want to use actions from other git server, you can use a complete URL in `uses` field, it's supported by Gitea (but not GitHub).
+Like `uses: https://gitea.com/actions/checkout@v4` or `uses: http://your-git-server/actions/checkout@v4`.
+
+## Other (`other`)
+
+- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
+- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
+- `SHOW_FOOTER_POWERED_BY`: **true**: Show the "powered by" text in the footer.
+- `ENABLE_SITEMAP`: **true**: Generate sitemap.
+- `ENABLE_FEED`: **true**: Enable/Disable RSS/Atom feed.
diff --git a/versioned_docs/version-1.25/administration/customizing-gitea.md b/versioned_docs/version-1.25/administration/customizing-gitea.md
new file mode 100644
index 00000000..3f06f7fb
--- /dev/null
+++ b/versioned_docs/version-1.25/administration/customizing-gitea.md
@@ -0,0 +1,507 @@
+---
+date: "2017-04-15T14:56:00+02:00"
+slug: "customizing-gitea"
+sidebar_position: 100
+aliases:
+ - /en-us/customizing-gitea
+---
+
+# Customizing Gitea
+
+Customizing Gitea is typically done using the `CustomPath` folder - by default this is
+the `custom` folder from the working directory (WorkPath), but may be different if your [installation](../installation/installation.md) has
+set this differently. This is the central place to override configuration settings,
+templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
+the path on the _Configuration_ tab in the _Site Administration_ page. You can override
+the `CustomPath` by setting either the `GITEA_CUSTOM` environment variable or by
+using the `--custom-path` option on the `gitea` binary. (The option will override the
+environment variable.)
+
+If Gitea is deployed from binary, all default paths will be relative to the Gitea
+binary. If installed from a distribution, these paths will likely be modified to
+the Linux Filesystem Standard. Gitea will attempt to create required folders, including
+`custom/`. Distributions may provide a symlink for `custom` using `/etc/gitea/`.
+
+Application settings can be found in file `CustomConf` which is by default,
+`$GITEA_CUSTOM/conf/app.ini` but may be different if your [installation](../installation/installation.md) has set this differently.
+Again `gitea help` will allow you review this variable and you can override it using the
+`--config` option on the `gitea` binary.
+
+- [Quick Cheat Sheet](../administration/config-cheat-sheet.md)
+- [Complete List](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
+
+If the `CustomPath` folder can't be found despite checking `gitea help`, check the `GITEA_CUSTOM`
+environment variable; this can be used to override the default path to something else.
+`GITEA_CUSTOM` might, for example, be set by an init script. You can check whether the value
+is set under the "Configuration" tab on the site administration page.
+
+- [List of Environment Variables](../administration/environment-variables.md)
+
+:::note
+Gitea must perform a full restart to see configuration changes.
+:::
+
+## Serving custom public files
+
+To make Gitea serve custom public files (like pages and images), use the folder
+`$GITEA_CUSTOM/public/` as the webroot. Symbolic links will be followed.
+At the moment, only the following files are served:
+
+- `public/robots.txt`
+- files in the `public/.well-known/` folder
+- files in the `public/assets/` folder
+
+For example, a file `image.png` stored in `$GITEA_CUSTOM/public/assets/`, can be accessed with
+the url `http://gitea.domain.tld/assets/image.png`.
+
+## Changing the logo
+
+To build a custom logo and/or favicon clone the Gitea source repository, replace `assets/logo.svg` and/or `assets/favicon.svg` and run
+`make generate-images`. `assets/favicon.svg` is used for the favicon only. This will update below output files which you can then place in `$GITEA_CUSTOM/public/assets/img` on your server:
+
+- `public/assets/img/logo.svg` - Used for site icon, app icon
+- `public/assets/img/logo.png` - Used for Open Graph
+- `public/assets/img/avatar_default.png` - Used as the default avatar image
+- `public/assets/img/apple-touch-icon.png` - Used on iOS devices for bookmarks
+- `public/assets/img/favicon.svg` - Used for favicon
+- `public/assets/img/favicon.png` - Used as fallback for browsers that don't support SVG favicons
+
+In case the source image is not in vector format, you can attempt to convert a raster image using tools like [this](https://www.aconvert.com/image/png-to-svg/).
+
+## Customizing Gitea pages and resources
+
+Gitea's executable contains all the resources required to run: templates, images, style-sheets
+and translations. Any of them can be overridden by placing a replacement in a matching path
+inside the `custom` directory. For example, to replace the default `.gitignore` provided
+for C++ repositories, we want to replace `options/gitignore/C++`. To do this, a replacement
+must be placed in `$GITEA_CUSTOM/options/gitignore/C++` (see about the location of the `CustomPath`
+directory at the top of this document).
+
+Every single page of Gitea can be changed. Dynamic content is generated using [go templates](https://pkg.go.dev/html/template),
+which can be modified by placing replacements below the `$GITEA_CUSTOM/templates` directory.
+
+To obtain any embedded file (including templates), the [`gitea embedded` tool](../administration/cmd-embedded.md) can be used. Alternatively, they can be found in the [`templates`](https://github.com/go-gitea/gitea/tree/main/templates) directory of Gitea source (Note: the example link is from the `main` branch. Make sure to use templates compatible with the release you are using).
+
+Be aware that any statement contained inside `{{` and `}}` are Gitea's template syntax and
+shouldn't be touched without fully understanding these components.
+
+### Customizing startpage / homepage
+
+Copy [`home.tmpl`](https://github.com/go-gitea/gitea/blob/main/templates/home.tmpl) for your version of Gitea from `templates` to `$GITEA_CUSTOM/templates`.
+Edit as you wish.
+Dont forget to restart your Gitea to apply the changes.
+
+### Adding links and tabs
+
+If all you want is to add extra links to the top navigation bar or footer, or extra tabs to the repository view, you can put them in `extra_links.tmpl` (links added to the navbar), `extra_links_footer.tmpl` (links added to the left side of footer), and `extra_tabs.tmpl` inside your `$GITEA_CUSTOM/templates/custom/` directory.
+
+For instance, let's say you are in Germany and must add the famously legally-required "Impressum"/about page, listing who is responsible for the site's content:
+just place it under your "$GITEA_CUSTOM/public/assets/" directory (for instance `$GITEA_CUSTOM/public/assets/impressum.html`) and put a link to it in either `$GITEA_CUSTOM/templates/custom/extra_links.tmpl` or `$GITEA_CUSTOM/templates/custom/extra_links_footer.tmpl`.
+
+To match the current style, the link should have the class name "item", and you can use `{{AppSubUrl}}` to get the base URL:
+`Impressum`
+
+For more information, see [Adding Legal Pages](../administration/adding-legal-pages.md).
+
+You can add new tabs in the same way, putting them in `extra_tabs.tmpl`.
+The exact HTML needed to match the style of other tabs is in the file
+`templates/repo/header.tmpl`
+([source in GitHub](https://github.com/go-gitea/gitea/blob/main/templates/repo/header.tmpl))
+
+### Other additions to the page
+
+Apart from `extra_links.tmpl` and `extra_tabs.tmpl`, there are other useful templates you can put in your `$GITEA_CUSTOM/templates/custom/` directory:
+
+- `header.tmpl`, just before the end of the `` tag where you can add custom CSS files for instance.
+- `body_outer_pre.tmpl`, right after the start of ``.
+- `body_inner_pre.tmpl`, before the top navigation bar, but already inside the main container ``.
+- `body_inner_post.tmpl`, before the end of the main container.
+- `body_outer_post.tmpl`, before the bottom `