mirror of
https://gitea.com/gitea/docs.git
synced 2026-09-17 19:55:34 +00:00
docs: postgres example version, SELinux, OAuth2/OIDC, IIS host rewrite and ACME in containers (#513)
Five documentation fixes that do not depend on anything upstream. **PostgreSQL version in the docker guide** (closes #224) The compose example pinned `postgres:14`, the oldest version Gitea still tests against, and PostgreSQL does not upgrade its data directory on its own, so every new deployment that copies the example is one major upgrade behind from day one. The example now uses `postgres:18`, with a note about why the major version is pinned and a pointer to the supported range. **SELinux** (closes #211) `setcap 'cap_net_bind_service=+ep'` is what the docs suggest for binding to a port below 1024, but it is denied under SELinux depending on the label of the binary, and it is lost on every upgrade because the capability lives in an extended attribute of the file. A new page describes granting the capability through the systemd unit instead (`AmbientCapabilities`, plus `PrivateUsers=false` when the sandboxing gets in the way), the `semanage fcontext` / `restorecon` labels for the binary and the data directory, and how to read the denials with `ausearch` and `audit2allow`. It is linked from the binary and source installation pages and from the `gitea web` notes. **OAuth2 and OpenID Connect** (closes #106) The authentication page documented LDAP, PAM, SMTP, FreeIPA, SPNEGO and the reverse proxy, but not that Gitea can log users in against an external OAuth2 or OpenID Connect provider, which made it look like the only OAuth2 support is Gitea acting as the provider. The new section covers the fields of the authentication source, the callback URL to register at the provider, the group and claim mappings, and the `[oauth2_client]` settings, and separates it from the older OpenID 2.0 sign-in. **IIS reverse proxy** (closes #39) Application Request Routing rewrites the host of the `Location` header back to the internal one while "Reverse rewrite host in response headers" is on, which sends the browser to `127.0.0.1:3000` after a sign-in. The IIS section now says to turn it off and where the setting lives. **ACME in containers** (closes #292) `ACME_DIRECTORY` defaults to the relative path `https`, which is resolved against the working directory of the process. In the official image that is `/app/gitea`, outside the `/data` volume, so a recreated container asks the CA for a new certificate and runs into the Let's Encrypt limit of 5 certificates per week for the same domains. The HTTPS page now warns about it and shows an absolute path inside the volume; the cheat sheet entry points at the warning. The default itself is being changed in https://github.com/go-gitea/gitea/pull/35851, the note stays useful for every released version. Only `docs/` is touched, the released versions keep their content. <!-- cloudflare-preview --> Preview: https://pr-513.docs-gitea-com.pages.dev Reviewed-on: https://gitea.com/gitea/docs/pulls/513 Reviewed-by: bircni <[email protected]> Co-authored-by: Lunny Xiao <[email protected]>
This commit is contained in:
@@ -349,3 +349,86 @@ ENABLE_REVERSE_PROXY_AUTHENTICATION_API = true
|
||||
:::note
|
||||
When this method is enabled for the API, the reverse proxy is responsible for handling CSRF protection.
|
||||
:::
|
||||
|
||||
## OAuth2 and OpenID Connect
|
||||
|
||||
Gitea can delegate the login to an external OAuth2 or OpenID Connect provider,
|
||||
which is what "Sign in with ..." on the login page uses. This is the client side
|
||||
of the protocol; for the other direction, using a Gitea instance as the provider
|
||||
for another application, see
|
||||
[Gitea as an OAuth2 provider](../development/oauth2-provider.md).
|
||||
|
||||
A source is added under `Site Administration -> Identity & Access ->
|
||||
Authentication Sources -> Add Authentication Source`, with `OAuth2` as the
|
||||
authentication type, or on the command line with
|
||||
`gitea admin auth add-oauth`. The fields are:
|
||||
|
||||
- **Authentication Name (required)**
|
||||
|
||||
- The name of the source. It is part of the callback URL, so it cannot be
|
||||
changed later without registering a new callback URL at the provider.
|
||||
|
||||
- **OAuth2 Provider (required)**
|
||||
|
||||
- `OpenID Connect` for any provider that implements OpenID Connect discovery
|
||||
(Keycloak, Authentik, Authelia, Entra ID, Okta, Zitadel and others), or one
|
||||
of the providers Gitea knows about directly: Gitea, GitHub, GitLab, Google,
|
||||
Discord, Bitbucket, Dropbox, Facebook, Mastodon, Nextcloud, Twitter, Yandex
|
||||
and Azure AD v2.
|
||||
|
||||
- **Client ID (Key)** and **Client Secret (required)**
|
||||
|
||||
- The credentials of the application registered at the provider.
|
||||
|
||||
- **OpenID Connect Auto Discovery URL**
|
||||
|
||||
- Only for the `OpenID Connect` provider: the discovery document of the
|
||||
provider, usually `https://provider.example.com/.well-known/openid-configuration`.
|
||||
Gitea reads the endpoints from it.
|
||||
|
||||
- **Additional Scopes**
|
||||
|
||||
- Scopes to request on top of the ones the provider needs by default. For
|
||||
OpenID Connect, `openid` is always added, and the scopes are taken from
|
||||
`OPENID_CONNECT_SCOPES` in `app.ini` when it is set.
|
||||
|
||||
- **Required Claim Name** and **Required Claim Value**
|
||||
|
||||
- Restrict the login to accounts whose token carries this claim, optionally
|
||||
with this exact value.
|
||||
|
||||
- **Claim name providing group names**, **Group Claim value for administrator
|
||||
users**, **Group Claim value for restricted users** and **Map claimed groups
|
||||
to Organization teams**
|
||||
|
||||
- Grant the administrator or the restricted flag, and organization team
|
||||
membership, from the groups the provider reports. They all need the claim
|
||||
name to be set.
|
||||
|
||||
- **Icon URL**
|
||||
|
||||
- Image shown next to the button on the login page.
|
||||
|
||||
Register `{ROOT_URL}/user/oauth2/{Authentication Name}/callback` as the
|
||||
redirect URI at the provider, for example
|
||||
`https://gitea.example.com/user/oauth2/keycloak/callback` for a source named
|
||||
`keycloak`. A wrong redirect URI is the most common reason for the login to
|
||||
fail at the provider.
|
||||
|
||||
What happens to accounts that log in this way is configured in `app.ini`, see
|
||||
[OAuth2 Client](config-cheat-sheet.md#oauth2-client-oauth2_client):
|
||||
|
||||
```ini title="app.ini"
|
||||
[oauth2_client]
|
||||
; create an account for a user who logs in for the first time
|
||||
ENABLE_AUTO_REGISTRATION = true
|
||||
; where the username of a new account comes from
|
||||
USERNAME = nickname
|
||||
; what to do when the username or email is already taken
|
||||
ACCOUNT_LINKING = login
|
||||
```
|
||||
|
||||
:::note
|
||||
This is unrelated to `ENABLE_OPENID_SIGNIN` and the `[openid]` section, which
|
||||
configure the older OpenID 2.0 sign-in.
|
||||
:::
|
||||
|
||||
@@ -45,6 +45,9 @@ Starts the server:
|
||||
- Gitea should not be run as root. To bind to a port below 1024, you can use setcap on
|
||||
Linux: `sudo setcap 'cap_net_bind_service=+ep' /path/to/gitea`. This will need to be
|
||||
redone every time you update Gitea.
|
||||
A systemd unit can grant the capability to the process instead, which survives an
|
||||
upgrade and works with SELinux in enforcing mode, see
|
||||
[running Gitea with SELinux](../installation/selinux.md).
|
||||
|
||||
### admin
|
||||
|
||||
|
||||
@@ -459,7 +459,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `ENABLE_ACME`: **false**: Flag to enable automatic certificate management via an ACME capable Certificate Authority (CA) server (default: Lets Encrypt). If enabled, `CERT_FILE` and `KEY_FILE` are ignored, and the CA must resolve `DOMAIN` to this gitea server. Ensure that DNS records are set and either port `80` or port `443` are accessible by the CA server (the public internet by default), and redirected to the appropriate ports `PORT_TO_REDIRECT` or `HTTP_PORT` respectively.
|
||||
- `ACME_URL`: **_empty_**: The CA's ACME directory URL, e.g. for a self-hosted [smallstep CA server](https://github.com/smallstep/certificates), it can look like `https://ca.example.com/acme/acme/directory`. If left empty, it defaults to using Let's Encerypt's production CA (check `LETSENCRYPT_ACCEPTTOS` as well).
|
||||
- `ACME_ACCEPTTOS`: **false**: This is an explicit check that you accept the terms of service of the ACME provider. The default is Lets Encrypt [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf).
|
||||
- `ACME_DIRECTORY`: **https**: Directory that the certificate manager will use to cache information such as certs and private keys.
|
||||
- `ACME_DIRECTORY`: **https**: Directory that the certificate manager will use to cache information such as certs and private keys. A relative path is resolved against the working directory of the Gitea process, which is not necessarily a directory that survives a restart, see the note in [HTTPS setup](https-support.md#using-acme-default-lets-encrypt).
|
||||
- `ACME_EMAIL`: **_empty_**: Email used for the ACME registration. Usually it is to notify about problems with issued certificates.
|
||||
- `ACME_CA_ROOT`: **_empty_**: The CA's root certificate. If left empty, it defaults to using the system's trust chain.
|
||||
- `ALLOW_GRACEFUL_RESTARTS`: **true**: Perform a graceful restart on SIGHUP
|
||||
|
||||
@@ -78,6 +78,28 @@ [email protected]
|
||||
|
||||
To learn more about the config values, please checkout the [Config Cheat Sheet](./config-cheat-sheet.md#server-server).
|
||||
|
||||
:::warning
|
||||
`ACME_DIRECTORY` is where the account key and the issued certificates are
|
||||
cached, and the default `https` is a relative path, resolved against the working
|
||||
directory of the Gitea process. In the official Docker image that working
|
||||
directory is `/app/gitea`, which is part of the container and not of the `/data`
|
||||
volume, so every recreated container starts without an account and without
|
||||
certificates and asks the CA for new ones. Let's Encrypt allows
|
||||
[5 certificates per week](https://letsencrypt.org/docs/rate-limits/) for the
|
||||
same set of domains, after which the instance is left without a working
|
||||
certificate until the limit expires.
|
||||
|
||||
Point the setting at a path inside the volume when running in a container:
|
||||
|
||||
```ini title="app.ini"
|
||||
[server]
|
||||
ACME_DIRECTORY=/data/gitea/https
|
||||
```
|
||||
|
||||
The rootless image keeps its working directory (`/var/lib/gitea`) in a volume,
|
||||
so it is only affected when that volume is not persisted.
|
||||
:::
|
||||
|
||||
## Using a reverse proxy
|
||||
|
||||
Setup up your reverse proxy as shown in the [reverse proxy guide](../administration/reverse-proxies.md).
|
||||
|
||||
@@ -305,6 +305,7 @@ If you wish to run Gitea with IIS. You will need to setup IIS with URL Rewrite a
|
||||
- In the Inbound Rules section, set the server name to be the host that Gitea is running on with its port. e.g. if you are running Gitea on the localhost with port 3000, the following should work: `127.0.0.1:3000`
|
||||
- Enable SSL Offloading
|
||||
- In the Outbound Rules, ensure `Rewrite the domain names of the links in HTTP response` is set and set the `From:` field as above and the `To:` to your external hostname, say: `git.example.com`
|
||||
- Turn `Reverse rewrite host in response headers` off, in the `Server Proxy Settings` of Application Request Routing (select the server node in the IIS Manager, open `Application Request Routing Cache`, then `Server Proxy Settings` in the right pane). While it is on, ARR rewrites the host of the `Location` header back to the internal one, so the redirects Gitea sends after a sign-in or a form submission send the browser to `127.0.0.1:3000` instead of `git.example.com`.
|
||||
- Now edit the `web.config` for your website to match the following: (changing `127.0.0.1:3000` and `git.example.com` as appropriate)
|
||||
|
||||
```xml
|
||||
|
||||
@@ -171,6 +171,13 @@ Supported values for `<shell>` are `bash`, `fish`, `pwsh` and `zsh`. Details on
|
||||
|
||||
After you complete the above steps, you can run Gitea two ways:
|
||||
|
||||
:::note
|
||||
On a distribution with SELinux in enforcing mode (Fedora, RHEL, CentOS Stream,
|
||||
Rocky Linux, AlmaLinux and others), the binary and the data directory need
|
||||
labels the default policy does not give them, and binding to a port below 1024
|
||||
takes an extra step. See [running Gitea with SELinux](selinux.md).
|
||||
:::
|
||||
|
||||
### 1. Creating a service file to start Gitea automatically (recommended)
|
||||
|
||||
See how to create [Linux service](installation/run-as-service-in-ubuntu.md)
|
||||
|
||||
@@ -127,6 +127,12 @@ launched manually from command line, it can be killed by pressing `Ctrl + C`.
|
||||
./gitea web
|
||||
```
|
||||
|
||||
:::note
|
||||
A binary built this way carries no SELinux label of its own. On a distribution
|
||||
with SELinux in enforcing mode, see
|
||||
[running Gitea with SELinux](selinux.md) before installing it as a service.
|
||||
:::
|
||||
|
||||
## Changing default paths
|
||||
|
||||
Gitea will search for a number of things from the _`CustomPath`_. By default this is
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
date: "2026-08-13T00:00:00+00:00"
|
||||
slug: "selinux"
|
||||
sidebar_position: 45
|
||||
---
|
||||
|
||||
# Running Gitea with SELinux
|
||||
|
||||
Distributions such as Fedora, RHEL, CentOS Stream, Rocky Linux and AlmaLinux
|
||||
ship SELinux in enforcing mode. Packages from a distribution repository come
|
||||
with a policy that fits them, but an installation
|
||||
[from binary](from-binary.md) or [from source](from-source.md) puts the binary
|
||||
and the data in paths the policy knows nothing about, so the labels have to be
|
||||
set by hand. The same applies to any other distribution where SELinux is
|
||||
enabled.
|
||||
|
||||
Do not turn SELinux off to work around the problems below. `setenforce 0` is
|
||||
useful to confirm that a failure really comes from SELinux, but switch it back
|
||||
on with `setenforce 1` afterwards.
|
||||
|
||||
## Binding to a port below 1024
|
||||
|
||||
Gitea should not run as root, and an unprivileged process may not bind to a
|
||||
port below 1024. Granting the capability to the binary with
|
||||
`setcap 'cap_net_bind_service=+ep' /usr/local/bin/gitea` is often suggested,
|
||||
but it is the least robust option:
|
||||
|
||||
- file capabilities are stored in an extended attribute of the binary, so they
|
||||
are lost every time the binary is replaced, which happens on every upgrade.
|
||||
- the SELinux policy has to allow the capability for the label of the binary,
|
||||
and a binary in a path such as `/opt` usually does not carry a label that
|
||||
allows it.
|
||||
|
||||
Let systemd grant the capability to the process instead. It works with SELinux
|
||||
in enforcing mode and survives upgrades, the sample unit file has the two lines
|
||||
commented out:
|
||||
|
||||
```ini title="/etc/systemd/system/gitea.service"
|
||||
[Service]
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
```
|
||||
|
||||
Reload and restart the service afterwards:
|
||||
|
||||
```sh
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart gitea
|
||||
```
|
||||
|
||||
If the capability still does not reach the process, add `PrivateUsers=false` to
|
||||
the unit: the sandboxing runs the service in a user namespace where the
|
||||
capability does not apply to the host.
|
||||
|
||||
Two alternatives avoid the privileged port altogether, and are what most
|
||||
installations end up doing:
|
||||
|
||||
- put a [reverse proxy](../administration/reverse-proxies.md) in front of Gitea
|
||||
and let it own ports `80` and `443`.
|
||||
- redirect the port in the firewall, for example with
|
||||
`firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=3000`.
|
||||
|
||||
## Labelling the binary and the data directory
|
||||
|
||||
If Gitea starts but cannot read its own files, or fails in ways that are not
|
||||
explained by the file permissions, the labels are usually wrong. The tools come
|
||||
from the `policycoreutils-python-utils` package.
|
||||
|
||||
Label the binary as an executable and the data directory as application state:
|
||||
|
||||
```sh
|
||||
sudo semanage fcontext -a -t bin_t '/usr/local/bin/gitea'
|
||||
sudo restorecon -v /usr/local/bin/gitea
|
||||
|
||||
sudo semanage fcontext -a -t var_lib_t '/var/lib/gitea(/.*)?'
|
||||
sudo restorecon -Rv /var/lib/gitea
|
||||
```
|
||||
|
||||
`semanage fcontext` records the rule, `restorecon` applies it to the files that
|
||||
are already there. Use the two together rather than `chcon`, whose labels are
|
||||
reverted by the next relabel of the file system.
|
||||
|
||||
Adjust the paths if the installation does not follow
|
||||
[installation from binary](from-binary.md); the configuration in `/etc/gitea`
|
||||
is read with the label distributions give to `/etc`, so it normally needs
|
||||
nothing.
|
||||
|
||||
## Finding out what was denied
|
||||
|
||||
SELinux denials are written to the audit log, not to the Gitea log, so a
|
||||
failure often looks like a permission problem without any further explanation:
|
||||
|
||||
```sh
|
||||
sudo ausearch -m AVC -c gitea --start recent
|
||||
```
|
||||
|
||||
If a denial shows up that the rules above do not cover, turn it into a local
|
||||
policy module. Read what it allows before installing it, `audit2allow` writes
|
||||
down whatever was denied, including the things that were denied for a good
|
||||
reason:
|
||||
|
||||
```sh
|
||||
sudo ausearch -c gitea --raw | audit2allow -M gitea-local
|
||||
cat gitea-local.te
|
||||
sudo semodule -i gitea-local.pp
|
||||
```
|
||||
|
||||
If the denials point at a path Gitea should not be using at all, fix the path
|
||||
instead of allowing the access.
|
||||
@@ -144,6 +144,13 @@ services:
|
||||
To start Gitea in combination with a PostgreSQL database, apply these changes to
|
||||
the `docker-compose.yml` file created above.
|
||||
|
||||
:::note
|
||||
The example pins a major version on purpose: PostgreSQL does not upgrade its data
|
||||
directory on its own, moving to a newer major version later requires `pg_upgrade`
|
||||
or a dump and restore. Start a new instance on the newest version Gitea supports,
|
||||
see [database preparation](database-preparation.md) for the supported versions.
|
||||
:::
|
||||
|
||||
```diff
|
||||
networks:
|
||||
gitea:
|
||||
@@ -175,7 +182,7 @@ services:
|
||||
+ - db
|
||||
+
|
||||
+ db:
|
||||
+ image: docker.io/library/postgres:14
|
||||
+ image: docker.io/library/postgres:18
|
||||
+ restart: always
|
||||
+ environment:
|
||||
+ - POSTGRES_USER=gitea
|
||||
|
||||
Reference in New Issue
Block a user