Merge branch 'main' into lunny/add_project_workflow

This commit is contained in:
Lunny Xiao committed 2026-10-22 23:22:15 +00:00
commit c902fe9253
2340 files changed
+379885 -36853

No files matched your search

+27 -22
View File
@@ -1,5 +1,5 @@
name: Build and Publish Docs site
run-name: docusaurus build docs site
run-name: astro build docs site
on:
push:
@@ -9,35 +9,40 @@ on:
jobs:
build-docs:
runs-on: ubuntu-24.04
env:
NODE_OPTIONS: --max-old-space-size=8192
# search only appears once the credentials are set, the build falls back
# to pagefind otherwise
PUBLIC_DOCSEARCH_APP_ID: ${{ secrets.DOCSEARCH_APP_ID }}
PUBLIC_DOCSEARCH_API_KEY: ${{ secrets.DOCSEARCH_API_KEY }}
PUBLIC_DOCSEARCH_INDEX_NAME: ${{ secrets.DOCSEARCH_INDEX_NAME }}
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: 24
cache: pnpm
- name: install necessary tools
run: |
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
- name: prepare awesome list
run: |
make prepare-awesome-latest prepare-awesome\#25 prepare-awesome\#24 prepare-awesome\#23 prepare-awesome\#22
make prepare-awesome-latest prepare-awesome\#27 prepare-awesome\#26 prepare-awesome\#25 prepare-awesome\#24 prepare-awesome\#23 prepare-awesome\#22 prepare-awesome-v28
- name: Install dependencies
run: pnpm install --frozen-lockfile
#- uses: tats-u/docuactions-cache@v1
- name: build site
run: make build
- name: Copy files to Cloudflare Pages
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
run: |
make build
- name: aws credential configure
uses: aws-actions/configure-aws-credentials@v6
with:
aws-access-key-id: ${{ secrets.AWS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
aws-region: ${{ secrets.AWS_REGION}}
- name: Copy files to the production website with the AWS CLI
run: |
aws s3 sync build/ s3://docs-gitea-com
aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_DISTRIBUTION}} --paths '/*'
# cloudflare/_headers and cloudflare/_redirects are only meaningful for
# the Cloudflare Pages deployment, so they are copied into the build
# right before the deploy.
cp cloudflare/_headers sites/docs/dist/_headers
cp cloudflare/_redirects sites/docs/dist/_redirects
test -f sites/docs/dist/_headers -a -f sites/docs/dist/_redirects || exit 1
pnpm dlx wrangler@4 pages deploy sites/docs/dist \
--project-name docs-gitea-com \
--branch main
+68
View File
@@ -0,0 +1,68 @@
name: cleanup preview
on:
pull_request:
types:
- closed
# make sure two closing events for the same pull request do not delete the same
# deployment twice
concurrency:
group: cleanup-preview-${{ github.event.pull_request.number }}
jobs:
cleanup-preview:
runs-on: ubuntu-latest
steps:
- name: delete the Cloudflare Pages preview deployments
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
# pull requests from forks do not get the secrets, nothing was
# deployed for them either
if [ -z "${CLOUDFLARE_API_TOKEN:-}" ] || [ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ]; then
echo "no Cloudflare credentials available, skipping the preview cleanup"
exit 0
fi
project=docs-gitea-com
branch="pr-$PR_NUMBER"
api="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$project/deployments"
page=1
ids=""
while true; do
curl --silent --show-error --fail --output deployments.json \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"$api?per_page=100&page=$page"
found="$(jq -r --arg branch "$branch" \
'.result[] | select(.deployment_trigger.metadata.branch == $branch) | .id' deployments.json)"
if [ -n "$found" ]; then
ids="$ids$found"$'\n'
fi
# the API returns an empty result once the last page is passed
[ "$(jq -r '.result | length' deployments.json)" -eq 100 ] || break
page=$((page + 1))
done
if [ -z "$(printf '%s' "$ids" | tr -d '[:space:]')" ]; then
echo "no preview deployment found for $branch"
exit 0
fi
# force=true also removes the deployment the branch alias points at
printf '%s' "$ids" | while read -r id; do
[ -n "$id" ] || continue
echo "deleting the deployment $id of $branch"
curl --silent --show-error --fail --output /dev/null \
-X DELETE "$api/$id?force=true" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
done
echo "the preview of $branch is gone"
+85 -7
View File
@@ -3,23 +3,101 @@ name: checks
on:
- pull_request
# a new push to the same pull request replaces the running preview build
concurrency:
group: checks-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
build-docs:
runs-on: ubuntu-latest
env:
NODE_OPTIONS: --max-old-space-size=8192
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: 24
cache: pnpm
- name: prepare awesome list
run: |
make prepare-awesome-latest prepare-awesome\#25 prepare-awesome\#24 prepare-awesome\#23 prepare-awesome\#22
- name: Install dependencies
make prepare-awesome-latest prepare-awesome\#27 prepare-awesome\#26 prepare-awesome\#25 prepare-awesome\#24 prepare-awesome\#23 prepare-awesome\#22 prepare-awesome-v28
- name: install dependencies
run: pnpm install --frozen-lockfile
#- uses: tats-u/docuactions-cache@v1
- name: build site
run: make build
- name: type check
run: make check
- name: deploy the preview to Cloudflare Pages
id: preview
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
make build
set -euo pipefail
# pull requests from forks do not get the secrets, the build above is
# then the only check and the preview is silently skipped
if [ -z "${CLOUDFLARE_API_TOKEN:-}" ] || [ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ]; then
echo "::notice::no Cloudflare credentials available (pull request from a fork?), skipping the preview deployment"
exit 0
fi
# same as the production deployment: _headers and _redirects only
# belong to the Cloudflare Pages output, so they are copied in right
# before uploading
cp cloudflare/_headers sites/docs/dist/_headers
cp cloudflare/_redirects sites/docs/dist/_redirects
pnpm dlx wrangler@4 pages deploy sites/docs/dist \
--project-name docs-gitea-com \
--branch "pr-$PR_NUMBER" | tee wrangler.log
url="$(grep -Eo 'https://[A-Za-z0-9.-]+\.pages\.dev' wrangler.log | tail -n 1)"
if [ -z "$url" ]; then
echo "could not read the preview URL from the wrangler output"
exit 1
fi
echo "url=$url" >> "$GITHUB_OUTPUT"
- name: update the pull request with the preview URL
if: steps.preview.outputs.url != ''
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
PREVIEW_URL: ${{ steps.preview.outputs.url }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
if [ -z "${DEPLOY_TOKEN:-}" ]; then
echo "secrets.DEPLOY_TOKEN is missing, the preview is at $PREVIEW_URL"
exit 0
fi
api="${GITHUB_API_URL:-$GITHUB_SERVER_URL/api/v1}/repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER"
curl --silent --show-error --fail --output pull.json \
-H "Authorization: token $DEPLOY_TOKEN" "$api"
marker='<!-- cloudflare-preview -->'
# drop the line written by an earlier run, so the URL is updated in
# place instead of piling up at the end of the description
body="$(jq -r '.body // ""' pull.json | grep -vF "$marker" || true)"
body="$(printf '%s\n' "$body" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}')"
if [ -n "$body" ]; then
body="$(printf '%s\n\n%s Preview: %s\n' "$body" "$marker" "$PREVIEW_URL")"
else
body="$(printf '%s Preview: %s\n' "$marker" "$PREVIEW_URL")"
fi
printf '%s' "$body" | jq -Rs '{body: .}' > patch.json
curl --silent --show-error --fail --output /dev/null \
-X PATCH "$api" \
-H "Authorization: token $DEPLOY_TOKEN" \
-H 'Content-Type: application/json' \
--data @patch.json
echo "the pull request now points at $PREVIEW_URL"
@@ -0,0 +1,109 @@
name: update runner reference
on:
schedule:
- cron: '30 3 * * 1' # every Monday at 03:30
workflow_dispatch:
env:
# main is protected, so the update is proposed as a pull request from this branch
BOT_BRANCH: bot/update-runner-reference
BASE_BRANCH: main
# the develop runner docs follow the main branch of gitea/runner, every
# documented release series follows its newest stable tag. The value is used
# unquoted, so the glob is expanded by the shell of each step.
TARGET_DIRS: runner-docs/reference runner-docs_versioned_docs/version-*/reference
jobs:
update-runner-reference:
if: github.repository == 'gitea/docs'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: main
# pushing uses DEPLOY_TOKEN, keep the ephemeral job token out of .git/config
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: 'stable'
cache: false
- name: regenerate the runner reference pages
run: |
set -euo pipefail
./update_runner_docs.sh main runner-docs/reference
./update_runner_docs.sh --released
- name: verify the generated files
run: |
set -euo pipefail
# the pages are built from `--help` and `generate-config`, so a truncated
# build would silently produce an almost empty page
for dir in $TARGET_DIRS; do
echo "checking $dir"
grep -q 'gitea-runner \[command\]' "$dir/cli.md"
grep -q 'gitea-runner exec \[flags\]' "$dir/cli.md"
grep -q '^runner:' "$dir/config-example.md"
done
- name: push bot branch
id: bot_branch
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
set -euo pipefail
if git diff --quiet -- $TARGET_DIRS; then
echo "the runner reference is already up to date"
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ -z "$DEPLOY_TOKEN" ]; then
echo "secrets.DEPLOY_TOKEN is missing, cannot push the update"
exit 1
fi
remote="https://x-access-token:$DEPLOY_TOKEN@${GITHUB_SERVER_URL#*://}/$GITHUB_REPOSITORY.git"
# skip if an open bot branch already carries exactly these files
if git fetch --quiet --depth=1 "$remote" "refs/heads/$BOT_BRANCH" 2>/dev/null; then
if git diff --quiet FETCH_HEAD -- $TARGET_DIRS; then
echo "$BOT_BRANCH already proposes this runner reference"
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
fi
git config user.name "Gitea Bot"
git config user.email "[email protected]"
git switch --create "$BOT_BRANCH"
git add $TARGET_DIRS
git commit -m "Update the runner reference pages"
# force push: the branch is always rebuilt on top of the current main
git push --force "$remote" "HEAD:refs/heads/$BOT_BRANCH"
echo "changed=true" >> "$GITHUB_OUTPUT"
- name: create pull request
if: steps.bot_branch.outputs.changed == 'true'
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
set -euo pipefail
cat > pull.json <<EOF
{
"base": "$BASE_BRANCH",
"head": "$BOT_BRANCH",
"title": "Update the runner reference pages",
"body": "Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the \"update runner reference\" scheduled workflow."
}
EOF
code="$(curl --silent --show-error --output pull-response.json --write-out '%{http_code}' \
-X POST "${GITHUB_API_URL:-$GITHUB_SERVER_URL/api/v1}/repos/$GITHUB_REPOSITORY/pulls" \
-H "Authorization: token $DEPLOY_TOKEN" \
-H 'Content-Type: application/json' \
--data @pull.json)"
case "$code" in
201) echo "pull request created" ;;
409) echo "an open pull request for $BOT_BRANCH already exists, it now points at the new commit" ;;
*) echo "unexpected response $code:"; cat pull-response.json; exit 1 ;;
esac
+98 -16
View File
@@ -1,28 +1,110 @@
name: update swagger files
name: update api spec files
on:
schedule:
- cron: '0 */12 * * *' # every 12 hours on the hour
- cron: '0 3 * * 1' # every Monday at 03:00
workflow_dispatch:
env:
# main is protected, so the update is proposed as a pull request from this branch
BOT_BRANCH: bot/update-swagger-latest
BASE_BRANCH: main
# the documents of the gitea main branch, refreshed by this job
LATEST_FILES: static/swagger-latest.json static/openapi3-latest.json
jobs:
update-swagger:
if: github.repository == 'gitea/docs'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- run: |
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: main
# pushing uses DEPLOY_TOKEN, keep the ephemeral job token out of .git/config
persist-credentials: false
- name: regenerate the latest api documents
run: make update-api-docs-latest
- name: verify the generated file
run: |
set -euo pipefail
for file in $LATEST_FILES; do
# placeholders must have been replaced, otherwise upstream changed them again
if grep -q -e 'GITEA-API-APP' -e '{{' "$file"; then
echo "$file still contains template placeholders"
exit 1
fi
if command -v python3 >/dev/null 2>&1; then
python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$file"
fi
done
- name: push bot branch
id: bot_branch
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
set -euo pipefail
make update-api-docs
git config --global user.name "Gitea Bot"
git config --global user.email "[email protected]"
git remote set-url origin https://x-access-token:${{ secrets.DEPLOY_TOKEN }}@gitea.com/gitea/docs.git
if git status --porcelain | grep -q .; then
git add --all
git commit -m "[skip ci] Updated swagger files"
git push
else
echo "No API doc changes detected; skipping commit"
if git diff --quiet -- $LATEST_FILES; then
echo "the api documents are already up to date"
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ -z "$DEPLOY_TOKEN" ]; then
echo "secrets.DEPLOY_TOKEN is missing, cannot push the update"
exit 1
fi
remote="https://x-access-token:$DEPLOY_TOKEN@${GITHUB_SERVER_URL#*://}/$GITHUB_REPOSITORY.git"
# skip if an open bot branch already carries exactly this file
if git fetch --quiet --depth=1 "$remote" "refs/heads/$BOT_BRANCH" 2>/dev/null; then
same=true
for file in $LATEST_FILES; do
old_blob="$(git rev-parse --quiet --verify "FETCH_HEAD:$file" || true)"
if [ "$old_blob" != "$(git hash-object "$file")" ]; then
same=false
break
fi
done
if [ "$same" = true ]; then
echo "$BOT_BRANCH already proposes these api documents"
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
fi
git config user.name "Gitea Bot"
git config user.email "[email protected]"
git switch --create "$BOT_BRANCH"
git add $LATEST_FILES
git commit -m "Update the latest api documents"
# force push: the branch is always rebuilt on top of the current main
git push --force "$remote" "HEAD:refs/heads/$BOT_BRANCH"
echo "changed=true" >> "$GITHUB_OUTPUT"
- name: create pull request
if: steps.bot_branch.outputs.changed == 'true'
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
set -euo pipefail
cat > pull.json <<EOF
{
"base": "$BASE_BRANCH",
"head": "$BOT_BRANCH",
"title": "Update the latest api documents",
"body": "Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the \"update api spec files\" scheduled workflow."
}
EOF
code="$(curl --silent --show-error --output pull-response.json --write-out '%{http_code}' \
-X POST "${GITHUB_API_URL:-$GITHUB_SERVER_URL/api/v1}/repos/$GITHUB_REPOSITORY/pulls" \
-H "Authorization: token $DEPLOY_TOKEN" \
-H 'Content-Type: application/json' \
--data @pull.json)"
case "$code" in
201) echo "pull request created" ;;
409) echo "an open pull request for $BOT_BRANCH already exists, it now points at the new commit" ;;
*) echo "unexpected response $code:"; cat pull-response.json; exit 1 ;;
esac
+6 -7
View File
@@ -1,12 +1,11 @@
# Dependencies
/node_modules
node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Build output
sites/*/dist
sites/*/.astro
sites/*/.cache
build/
# Misc
.DS_Store
-5
View File
@@ -1,5 +0,0 @@
audit=false
fund=false
update-notifier=false
package-lock=true
lockfile-version=3
+59 -17
View File
@@ -1,5 +1,3 @@
export NODE_OPTIONS := "--max-old-space-size=8192"
GITEA_AWESOME_REMOTE := https://gitea.com/gitea/awesome-gitea.git
GITEA_AWESOME_BRANCH := main
@@ -14,45 +12,89 @@ create_dir:
clone_awesome: create_dir
git clone --branch=$(GITEA_AWESOME_BRANCH) $(GITEA_AWESOME_REMOTE) .tmp/upstream-awesome || true
# the contributing guide moved to the gitea repository, the readme of
# awesome-gitea still links to it with a relative path
AWESOME_CONTRIBUTING_URL := https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md
FIX_AWESOME_LINKS := sed 's|](contributing.md)|]($(AWESOME_CONTRIBUTING_URL))|'
.PHONY: prepare-awesome-latest
prepare-awesome-latest: clone_awesome
cp .tmp/upstream-awesome/README.md docs/awesome.md
$(FIX_AWESOME_LINKS) .tmp/upstream-awesome/README.md > docs/awesome.md
.PHONY: prepare-awesome\#%
prepare-awesome\#%:
cp .tmp/upstream-awesome/README.md versioned_docs/version-1.$*/awesome.md
$(FIX_AWESOME_LINKS) .tmp/upstream-awesome/README.md > versioned_docs/version-1.$*/awesome.md
# versions numbered without the 1. prefix, like 28
.PHONY: prepare-awesome-v%
prepare-awesome-v%:
$(FIX_AWESOME_LINKS) .tmp/upstream-awesome/README.md > versioned_docs/version-$*/awesome.md
.PHONY: install
install:
pnpm install
.PHONY: prepare-docs
prepare-docs: install prepare-awesome-latest prepare-awesome\#19 prepare-awesome\#20 prepare-awesome\#21 prepare-awesome\#22 prepare-awesome\#23 prepare-awesome\#24
prepare-docs: install prepare-awesome-latest prepare-awesome\#22 prepare-awesome\#23 prepare-awesome\#24 prepare-awesome\#25 prepare-awesome\#26 prepare-awesome\#27 prepare-awesome-v28
.PHONY: build
build:
pnpm run build
# type checks the astro site and its components
.PHONY: check
check:
pnpm run check
.PHONY: serve
serve: prepare-docs
pnpm run start
pnpm run dev
.PHONY: serve-zh
serve-zh: prepare-docs
pnpm run start -- --locale zh-cn
# only the english docs of the version served at the root, plus the runner:
# starts in a few seconds instead of loading the whole matrix
.PHONY: serve-fast
serve-fast:
pnpm run dev:en-latest
# search is built by pagefind at build time, so it is only available on the
# built site; this serves it locally
.PHONY: serve-built
serve-built: build
pnpm run preview
.PHONY: clean
clean:
rm -rf .tmp
rm -rf static/_*
rm -rf static/swagger-latest.json
rm -rf static/swagger-19.json
rm -rf static/swagger-20.json
rm -rf static/swagger-21.json
rm -rf static/swagger-22.json
rm -rf static/swagger-23.json
rm -rf static/swagger-24.json
rm -rf sites/docs/dist
rm -rf sites/docs/.cache
rm -rf sites/docs/node_modules/.astro
# static/swagger-*.json and static/openapi3-*.json are committed files, use
# update-api-docs to refresh them
.PHONY: update-api-docs
update-api-docs:
./update_api_docs.sh
# only refresh the documents of the gitea main branch (used by the cron job)
.PHONY: update-api-docs-latest
update-api-docs-latest:
./update_api_docs.sh --latest-only
# regenerate the generated runner reference pages of the develop docs from the
# main branch of gitea/runner (used by the update runner reference cron job)
.PHONY: update-runner-docs
update-runner-docs:
./update_runner_docs.sh main runner-docs/reference
# same, for every documented release series: the tags are looked up through the
# Gitea API, so a runner release needs no change here
.PHONY: update-runner-docs-released
update-runner-docs-released:
./update_runner_docs.sh --released
# freezes the current docs or runner tree as a new version, see
# scripts/cut-version.mjs
.PHONY: cut-version
cut-version:
@test -n "$(PRODUCT)" -a -n "$(VERSION)" || { echo 'usage: make cut-version PRODUCT=docs VERSION=1.28'; exit 1; }
node scripts/cut-version.mjs $(PRODUCT) $(VERSION)
+115 -11
View File
@@ -1,23 +1,127 @@
# Gitea Docs ![badge](https://gitea.com/gitea/docs/actions/workflows/build-and-publish.yaml/badge.svg)
## How to build
The sources of [docs.gitea.com](https://docs.gitea.com), built with
[Astro](https://astro.build) and [Starlight](https://starlight.astro.build).
```shell
make clean
make prepare-docs
make build
```
The site covers three products, all served from this repository:
| Product | Content | Versions | Languages |
| --- | --- | --- | --- |
| Docs | `docs/`, `versioned_docs/`, `i18n/` | next, 28, 1.27 … 1.22 | English, 简体中文, 繁體中文 |
| API | `static/swagger-*.json`, `static/openapi3-*.json` | next, 28, 1.27 … 1.22 | English |
| Runner | `runner-docs/`, `runner-docs_versioned_docs/` | develop, 5 … 0 | English |
The enterprise documentation is built and deployed from its own repository and
reached through `/enterprise/`, which a Cloudflare worker maintained elsewhere
routes to that deployment.
## Development
```shell
make clean
make prepare-docs
make serve
make install # pnpm install
make serve-fast # english, the version served at the root, starts in seconds
make serve # the whole matrix, every version and language
make build # production build into sites/docs/dist
make check # type checks the site and its components
```
## Test en version
Search is built by Pagefind while the site is built, so it only answers on the
built site: use `make serve-built` to try it. With the Algolia credentials
(`PUBLIC_DOCSEARCH_APP_ID`, `PUBLIC_DOCSEARCH_API_KEY`) set, DocSearch is used
instead and works in `make serve` too.
`GITEA_DOCS_PRODUCTS`, `GITEA_DOCS_VERSIONS` and `GITEA_DOCS_LOCALES` (comma
separated) restrict what is built, which is what `make serve-fast` uses.
`GITEA_DOCS_STRICT_LINKS=true` turns the warnings about unresolved relative
markdown links into a build error.
`sites/docs/README.md` documents how the sources are mapped onto the site.
## Writing
Pages are plain markdown with the same frontmatter and admonitions as before:
frontmatter `slug`, `sidebar_position` and `sidebar_label` keep working, and so
do the `:::note` style admonitions and the `@version@` style release variables.
Relative `*.md` links are rewritten to urls while the site is built.
The order of the top level sidebar groups comes from `sidebars.js` (and
`versioned_sidebars/` for released versions), the label and order of every other
group from the `_category_.json` of its directory.
## Cutting a version
```shell
pnpm run start
make cut-version PRODUCT=docs VERSION=1.28
make cut-version PRODUCT=runner VERSION=6
```
This freezes the current tree, its translations and its sidebar. The label of
the version, its release variables (`@version@`, `@dockerVersion@`, ...) and
which version is served at the root live in
`packages/content-loader/src/products.ts` and are edited by hand afterwards.
That file is the single source of truth for the product, version and language
matrix.
## API docs
The definitions rendered under `/api/` live in `static/`:
`swagger-latest.json` (gitea main) and `swagger-<minor>.json` (released
versions) hold the swagger 2.0 document every gitea version ships,
`openapi3-latest.json` and `openapi3-<minor>.json` the openapi 3.0 document
gitea generates since 1.27. The openapi 3.0 document is what gets rendered
where it exists, and both are offered for download on the overview page of the
version, since code generators cannot read the rendered pages (and several of
them reject swagger 2.0).
```shell
make update-api-docs # refresh latest + every released version
make update-api-docs-latest # refresh only the documents of gitea main
```
The documents of gitea main are refreshed automatically: the `update api spec
files` workflow runs weekly and opens a pull request whenever gitea main
changed. Released versions are updated by hand when a new gitea version is
documented.
## Runner docs
| Version | Content | URL |
| --- | --- | --- |
| develop | `runner-docs/` | `/runner/develop/` |
| current series | `runner-docs_versioned_docs/version-5/` | `/runner/` |
| older series | `runner-docs_versioned_docs/version-4/` | `/runner/4/` |
A version directory covers a whole release series (`version-3` documents every
`3.x` release), so a patch release only needs a content update, not a new
folder. Use floating image tags (`gitea/runner:3`) and links to the runner's
`main` branch in those pages to keep them valid across patch releases.
Its sidebar is written by hand: `runner-sidebars.js` for develop, and
`runner-docs_versioned_sidebars/version-<version>-sidebars.json` per documented
version.
The pages under `reference/` are generated from the runner sources — the command
line reference from `--help`, the example configuration from `config generate`
(`generate-config` before 3.1):
```shell
make update-runner-docs # develop docs, from the main branch of gitea/runner
make update-runner-docs-released # every series, from its newest stable tag
./update_runner_docs.sh v3.0.2 runner-docs_versioned_docs/version-3/reference
```
These are refreshed automatically as well: the `update runner reference`
workflow runs weekly and opens a pull request whenever the runner's CLI or
example configuration changed. Generating them needs Go, since the script builds
the runner binary.
## Deployment
`main` is built and published by the `Build and Publish Docs site` workflow, to
S3/CloudFront and to Cloudflare Pages. `cloudflare/_headers` sets the cache
policy and `cloudflare/_redirects` keeps the urls the site used to serve; both
are copied next to the build output by that workflow.
`cloudflare/docsearch-crawler.json` is the Algolia crawler configuration.
`/enterprise/` is served by another deployment and routed to it by a Cloudflare
worker that lives outside this repository.
+24
View File
@@ -0,0 +1,24 @@
# Cloudflare Pages reads this file from the root of the deployed directory. It
# is copied into the build output by the publish workflow, so that it is not
# uploaded to S3/CloudFront where it would be publicly readable at /_headers.
#
# The build emits a single content hashed asset directory shared by every
# language, so no per locale rules are needed.
# Content hashed build output (js, css, fonts). The file name changes with the
# content, so these can be cached forever.
/_astro/*
Cache-Control: public, max-age=31536000, immutable
# Files under public/img and public/images keep stable names and are replaced in
# place, so they get a short, conservative max-age instead.
/img/*
Cache-Control: public, max-age=86400
/images/*
Cache-Control: public, max-age=86400
# The pagefind index, only present when the site is built without algolia
# docsearch. Content hashed as well.
/pagefind/*
Cache-Control: public, max-age=31536000, immutable
+458
View File
@@ -0,0 +1,458 @@
# Redirects for legacy URLs and routes the site no longer serves directly.
# The api reference and the runner docs are separate products, published in
# english only, so they have no localized copy.
/zh-cn/api/* /api/:splat 301
/zh-tw/api/* /api/:splat 301
/zh-cn/runner/* /runner/:splat 301
/zh-tw/runner/* /runner/:splat 301
# The version served at the root of a product is also reachable under its
# number, which is what the release notes and old links use.
/api/28/* /api/:splat 301
/runner/3/* /runner/:splat 301
/28/* /:splat 301
# The local search plugin had a results page of its own, algolia docsearch is a
# modal opened from any page.
/search / 301
/zh-cn/search /zh-cn/ 301
/zh-tw/search /zh-tw/ 301
# Pages that moved when the docs were reorganized: the flat `/usage/webhooks`,
# `/advanced/...` and `/developers/...` layout of 1.19 and 1.20, and
# `/help/seek-help`. Those urls kept working until the site moved to Cloudflare
# because it was published with `aws s3 sync` without `--delete`, so the pages
# built before the move were never removed from the bucket. Only what the build
# emits is served now, and gitea itself and blog.gitea.com still link to some of
# them, so they are redirected here.
/actions /usage/actions/ 301
/actions/ /usage/actions/ 301
/administration /category/administration/ 301
/administration/ /category/administration/ 301
/administration/logging-configuration /administration/logging-config/ 301
/advanced/adding-legal-pages /administration/adding-legal-pages/ 301
/advanced/clone-filters /usage/repository/clone-filters/ 301
/advanced/cmd-embedded /administration/cmd-embedded/ 301
/advanced/config-cheat-sheet /administration/config-cheat-sheet/ 301
/advanced/customizing-gitea /administration/customizing-gitea/ 301
/advanced/environment-variables /administration/environment-variables/ 301
/advanced/external-renderers /administration/external-renderers/ 301
/advanced/logging-configuration /administration/logging-config/ 301
/advanced/mail-templates /administration/mail-templates/ 301
/advanced/protected-tags /usage/access-control/protected-tags/ 301
/advanced/repo-indexer /administration/repo-indexer/ 301
/advanced/repo-mirror /usage/repository/repo-mirror/ 301
/advanced/search-engines-indexation /administration/search-engines-indexation/ 301
/advanced/signing /administration/signing/ 301
/developers/api-usage /development/api-usage/ 301
/developers/integrations /development/integrations/ 301
/developers/migrations-interfaces /development/migrations-interfaces/ 301
/developers/oauth2-provider /development/oauth2-provider/ 301
/development /category/development/ 301
/development/ /category/development/ 301
/features/authentication /administration/authentication/ 301
/features/comparison /installation/comparison/ 301
/features/webhooks /usage/repository/webhooks/ 301
/help /category/help/ 301
/help/ /category/help/ 301
/help/seek-help /help/support/ 301
/installation /category/installation/ 301
/installation/ /category/installation/ 301
/installation/upgrade-from-gogs /category/installation/ 301
/upgrade/upgrade-from-gitea /installation/upgrade-from-gitea/ 301
/upgrade/upgrade-from-gogs /category/installation/ 301
/usage /category/usage/ 301
/usage/ /category/usage/ 301
/usage/actions/act-runner /runner/ 301
/usage/agit /usage/issues-prs/agit/ 301
/usage/agit-setup /usage/issues-prs/agit/ 301
/usage/authentication /administration/authentication/ 301
/usage/automatically-linked-references /usage/issues-prs/automatically-linked-references/ 301
/usage/badge /usage/actions/badge/ 301
/usage/blame /usage/repository/blame/ 301
/usage/blocking-user /usage/access-control/blocking-user/ 301
/usage/clone-filters /usage/repository/clone-filters/ 301
/usage/code-owners /usage/repository/code-owners/ 301
/usage/command-line /administration/command-line/ 301
/usage/email-setup /administration/email-setup/ 301
/usage/git-lfs-setup /administration/git-lfs-setup/ 301
/usage/https-setup /administration/https-setup/ 301
/usage/incoming-email /usage/repository/incoming-email/ 301
/usage/issue-pull-request-templates /usage/issues-prs/issue-pull-request-templates/ 301
/usage/labels /usage/issues-prs/labels/ 301
/usage/markdown /usage/repository/markdown/ 301
/usage/merge-message-templates /usage/issues-prs/merge-message-templates/ 301
/usage/migration /usage/repository/migration/ 301
/usage/multi-factor-authentication /usage/user-setting/multi-factor-authentication/ 301
/usage/permissions /usage/access-control/permissions/ 301
/usage/profile-readme /usage/repository/profile-readme/ 301
/usage/protected-tags /usage/access-control/protected-tags/ 301
/usage/pull-request /usage/issues-prs/pull-request/ 301
/usage/push /usage/repository/push/ 301
/usage/push-options /usage/repository/push/ 301
/usage/push-to-create /usage/repository/push/ 301
/usage/repo-mirror /usage/repository/repo-mirror/ 301
/usage/secrets /usage/actions/secrets/ 301
/usage/template-repositories /usage/repository/template-repositories/ 301
/usage/webhooks /usage/repository/webhooks/ 301
# ... and under simplified chinese.
/zh-cn/actions /zh-cn/usage/actions/ 301
/zh-cn/actions/ /zh-cn/usage/actions/ 301
/zh-cn/administration /zh-cn/category/administration/ 301
/zh-cn/administration/ /zh-cn/category/administration/ 301
/zh-cn/administration/logging-configuration /zh-cn/administration/logging-config/ 301
/zh-cn/advanced/adding-legal-pages /zh-cn/administration/adding-legal-pages/ 301
/zh-cn/advanced/clone-filters /zh-cn/usage/repository/clone-filters/ 301
/zh-cn/advanced/cmd-embedded /zh-cn/administration/cmd-embedded/ 301
/zh-cn/advanced/config-cheat-sheet /zh-cn/administration/config-cheat-sheet/ 301
/zh-cn/advanced/customizing-gitea /zh-cn/administration/customizing-gitea/ 301
/zh-cn/advanced/environment-variables /zh-cn/administration/environment-variables/ 301
/zh-cn/advanced/external-renderers /zh-cn/administration/external-renderers/ 301
/zh-cn/advanced/logging-configuration /zh-cn/administration/logging-config/ 301
/zh-cn/advanced/mail-templates /zh-cn/administration/mail-templates/ 301
/zh-cn/advanced/protected-tags /zh-cn/usage/access-control/protected-tags/ 301
/zh-cn/advanced/repo-indexer /zh-cn/administration/repo-indexer/ 301
/zh-cn/advanced/repo-mirror /zh-cn/usage/repository/repo-mirror/ 301
/zh-cn/advanced/search-engines-indexation /zh-cn/administration/search-engines-indexation/ 301
/zh-cn/advanced/signing /zh-cn/administration/signing/ 301
/zh-cn/developers/api-usage /zh-cn/development/api-usage/ 301
/zh-cn/developers/integrations /zh-cn/development/integrations/ 301
/zh-cn/developers/migrations-interfaces /zh-cn/development/migrations-interfaces/ 301
/zh-cn/developers/oauth2-provider /zh-cn/development/oauth2-provider/ 301
/zh-cn/development /zh-cn/category/development/ 301
/zh-cn/development/ /zh-cn/category/development/ 301
/zh-cn/features/authentication /zh-cn/administration/authentication/ 301
/zh-cn/features/comparison /zh-cn/installation/comparison/ 301
/zh-cn/features/webhooks /zh-cn/usage/repository/webhooks/ 301
/zh-cn/help /zh-cn/category/help/ 301
/zh-cn/help/ /zh-cn/category/help/ 301
/zh-cn/help/seek-help /zh-cn/help/support/ 301
/zh-cn/installation /zh-cn/category/installation/ 301
/zh-cn/installation/ /zh-cn/category/installation/ 301
/zh-cn/installation/upgrade-from-gogs /zh-cn/category/installation/ 301
/zh-cn/upgrade/upgrade-from-gitea /zh-cn/installation/upgrade-from-gitea/ 301
/zh-cn/upgrade/upgrade-from-gogs /zh-cn/category/installation/ 301
/zh-cn/usage /zh-cn/category/usage/ 301
/zh-cn/usage/ /zh-cn/category/usage/ 301
/zh-cn/usage/actions/act-runner /runner/ 301
/zh-cn/usage/agit-setup /zh-cn/usage/issues-prs/agit/ 301
/zh-cn/usage/authentication /zh-cn/administration/authentication/ 301
/zh-cn/usage/automatically-linked-references /zh-cn/usage/issues-prs/automatically-linked-references/ 301
/zh-cn/usage/badge /zh-cn/usage/actions/badge/ 301
/zh-cn/usage/blame /zh-cn/usage/repository/blame/ 301
/zh-cn/usage/blocking-user /zh-cn/usage/access-control/blocking-user/ 301
/zh-cn/usage/clone-filters /zh-cn/usage/repository/clone-filters/ 301
/zh-cn/usage/code-owners /zh-cn/usage/repository/code-owners/ 301
/zh-cn/usage/command-line /zh-cn/administration/command-line/ 301
/zh-cn/usage/email-setup /zh-cn/administration/email-setup/ 301
/zh-cn/usage/git-lfs-setup /zh-cn/administration/git-lfs-setup/ 301
/zh-cn/usage/https-setup /zh-cn/administration/https-setup/ 301
/zh-cn/usage/incoming-email /zh-cn/usage/repository/incoming-email/ 301
/zh-cn/usage/issue-pull-request-templates /zh-cn/usage/issues-prs/issue-pull-request-templates/ 301
/zh-cn/usage/labels /zh-cn/usage/issues-prs/labels/ 301
/zh-cn/usage/markdown /zh-cn/usage/repository/markdown/ 301
/zh-cn/usage/merge-message-templates /zh-cn/usage/issues-prs/merge-message-templates/ 301
/zh-cn/usage/migration /zh-cn/usage/repository/migration/ 301
/zh-cn/usage/multi-factor-authentication /zh-cn/usage/user-setting/multi-factor-authentication/ 301
/zh-cn/usage/permissions /zh-cn/usage/access-control/permissions/ 301
/zh-cn/usage/profile-readme /zh-cn/usage/repository/profile-readme/ 301
/zh-cn/usage/protected-tags /zh-cn/usage/access-control/protected-tags/ 301
/zh-cn/usage/pull-request /zh-cn/usage/issues-prs/pull-request/ 301
/zh-cn/usage/push /zh-cn/usage/repository/push/ 301
/zh-cn/usage/push-options /zh-cn/usage/repository/push/ 301
/zh-cn/usage/push-to-create /zh-cn/usage/repository/push/ 301
/zh-cn/usage/repo-mirror /zh-cn/usage/repository/repo-mirror/ 301
/zh-cn/usage/secrets /zh-cn/usage/actions/secrets/ 301
/zh-cn/usage/template-repositories /zh-cn/usage/repository/template-repositories/ 301
/zh-cn/usage/webhooks /zh-cn/usage/repository/webhooks/ 301
# ... and under traditional chinese.
/zh-tw/actions /zh-tw/usage/actions/ 301
/zh-tw/actions/ /zh-tw/usage/actions/ 301
/zh-tw/administration /zh-tw/category/administration/ 301
/zh-tw/administration/ /zh-tw/category/administration/ 301
/zh-tw/administration/logging-configuration /zh-tw/administration/logging-config/ 301
/zh-tw/advanced/adding-legal-pages /zh-tw/administration/adding-legal-pages/ 301
/zh-tw/advanced/clone-filters /zh-tw/usage/repository/clone-filters/ 301
/zh-tw/advanced/cmd-embedded /zh-tw/administration/cmd-embedded/ 301
/zh-tw/advanced/config-cheat-sheet /zh-tw/administration/config-cheat-sheet/ 301
/zh-tw/advanced/customizing-gitea /zh-tw/administration/customizing-gitea/ 301
/zh-tw/advanced/environment-variables /zh-tw/administration/environment-variables/ 301
/zh-tw/advanced/external-renderers /zh-tw/administration/external-renderers/ 301
/zh-tw/advanced/logging-configuration /zh-tw/administration/logging-config/ 301
/zh-tw/advanced/mail-templates /zh-tw/administration/mail-templates/ 301
/zh-tw/advanced/protected-tags /zh-tw/usage/access-control/protected-tags/ 301
/zh-tw/advanced/repo-indexer /zh-tw/administration/repo-indexer/ 301
/zh-tw/advanced/repo-mirror /zh-tw/usage/repository/repo-mirror/ 301
/zh-tw/advanced/search-engines-indexation /zh-tw/administration/search-engines-indexation/ 301
/zh-tw/advanced/signing /zh-tw/administration/signing/ 301
/zh-tw/developers/api-usage /zh-tw/development/api-usage/ 301
/zh-tw/developers/integrations /zh-tw/development/integrations/ 301
/zh-tw/developers/migrations-interfaces /zh-tw/development/migrations-interfaces/ 301
/zh-tw/developers/oauth2-provider /zh-tw/development/oauth2-provider/ 301
/zh-tw/development /zh-tw/category/development/ 301
/zh-tw/development/ /zh-tw/category/development/ 301
/zh-tw/features/authentication /zh-tw/administration/authentication/ 301
/zh-tw/features/comparison /zh-tw/installation/comparison/ 301
/zh-tw/features/webhooks /zh-tw/usage/repository/webhooks/ 301
/zh-tw/help /zh-tw/category/help/ 301
/zh-tw/help/ /zh-tw/category/help/ 301
/zh-tw/help/seek-help /zh-tw/help/support/ 301
/zh-tw/installation /zh-tw/category/installation/ 301
/zh-tw/installation/ /zh-tw/category/installation/ 301
/zh-tw/installation/upgrade-from-gogs /zh-tw/category/installation/ 301
/zh-tw/upgrade/upgrade-from-gitea /zh-tw/installation/upgrade-from-gitea/ 301
/zh-tw/upgrade/upgrade-from-gogs /zh-tw/category/installation/ 301
/zh-tw/usage /zh-tw/category/usage/ 301
/zh-tw/usage/ /zh-tw/category/usage/ 301
/zh-tw/usage/actions/act-runner /runner/ 301
/zh-tw/usage/agit-setup /zh-tw/usage/issues-prs/agit/ 301
/zh-tw/usage/authentication /zh-tw/administration/authentication/ 301
/zh-tw/usage/automatically-linked-references /zh-tw/usage/issues-prs/automatically-linked-references/ 301
/zh-tw/usage/badge /zh-tw/usage/actions/badge/ 301
/zh-tw/usage/blame /zh-tw/usage/repository/blame/ 301
/zh-tw/usage/blocking-user /zh-tw/usage/access-control/blocking-user/ 301
/zh-tw/usage/clone-filters /zh-tw/usage/repository/clone-filters/ 301
/zh-tw/usage/code-owners /zh-tw/usage/repository/code-owners/ 301
/zh-tw/usage/command-line /zh-tw/administration/command-line/ 301
/zh-tw/usage/email-setup /zh-tw/administration/email-setup/ 301
/zh-tw/usage/git-lfs-setup /zh-tw/administration/git-lfs-setup/ 301
/zh-tw/usage/https-setup /zh-tw/administration/https-setup/ 301
/zh-tw/usage/incoming-email /zh-tw/usage/repository/incoming-email/ 301
/zh-tw/usage/issue-pull-request-templates /zh-tw/usage/issues-prs/issue-pull-request-templates/ 301
/zh-tw/usage/labels /zh-tw/usage/issues-prs/labels/ 301
/zh-tw/usage/markdown /zh-tw/usage/repository/markdown/ 301
/zh-tw/usage/merge-message-templates /zh-tw/usage/issues-prs/merge-message-templates/ 301
/zh-tw/usage/migration /zh-tw/usage/repository/migration/ 301
/zh-tw/usage/multi-factor-authentication /zh-tw/usage/user-setting/multi-factor-authentication/ 301
/zh-tw/usage/permissions /zh-tw/usage/access-control/permissions/ 301
/zh-tw/usage/protected-tags /zh-tw/usage/access-control/protected-tags/ 301
/zh-tw/usage/pull-request /zh-tw/usage/issues-prs/pull-request/ 301
/zh-tw/usage/push /zh-tw/usage/repository/push/ 301
/zh-tw/usage/push-options /zh-tw/usage/repository/push/ 301
/zh-tw/usage/push-to-create /zh-tw/usage/repository/push/ 301
/zh-tw/usage/repo-mirror /zh-tw/usage/repository/repo-mirror/ 301
/zh-tw/usage/secrets /zh-tw/usage/actions/secrets/ 301
/zh-tw/usage/template-repositories /zh-tw/usage/repository/template-repositories/ 301
/zh-tw/usage/webhooks /zh-tw/usage/repository/webhooks/ 301
# ... and under the develop version.
/next/actions /next/usage/actions/ 301
/next/actions/ /next/usage/actions/ 301
/next/administration /next/category/administration/ 301
/next/administration/ /next/category/administration/ 301
/next/administration/logging-configuration /next/administration/logging-config/ 301
/next/advanced/adding-legal-pages /next/administration/adding-legal-pages/ 301
/next/advanced/clone-filters /next/usage/repository/clone-filters/ 301
/next/advanced/cmd-embedded /next/administration/cmd-embedded/ 301
/next/advanced/config-cheat-sheet /next/administration/config-cheat-sheet/ 301
/next/advanced/customizing-gitea /next/administration/customizing-gitea/ 301
/next/advanced/environment-variables /next/administration/environment-variables/ 301
/next/advanced/external-renderers /next/administration/external-renderers/ 301
/next/advanced/logging-configuration /next/administration/logging-config/ 301
/next/advanced/mail-templates /next/administration/mail-templates/ 301
/next/advanced/protected-tags /next/usage/access-control/protected-tags/ 301
/next/advanced/repo-indexer /next/administration/repo-indexer/ 301
/next/advanced/repo-mirror /next/usage/repository/repo-mirror/ 301
/next/advanced/search-engines-indexation /next/administration/search-engines-indexation/ 301
/next/advanced/signing /next/administration/signing/ 301
/next/developers/api-usage /next/development/api-usage/ 301
/next/developers/integrations /next/development/integrations/ 301
/next/developers/migrations-interfaces /next/development/migrations-interfaces/ 301
/next/developers/oauth2-provider /next/development/oauth2-provider/ 301
/next/development /next/category/development/ 301
/next/development/ /next/category/development/ 301
/next/features/authentication /next/administration/authentication/ 301
/next/features/comparison /next/installation/comparison/ 301
/next/features/webhooks /next/usage/repository/webhooks/ 301
/next/help /next/category/help/ 301
/next/help/ /next/category/help/ 301
/next/help/seek-help /next/help/support/ 301
/next/installation /next/category/installation/ 301
/next/installation/ /next/category/installation/ 301
/next/installation/upgrade-from-gogs /next/category/installation/ 301
/next/upgrade/upgrade-from-gitea /next/installation/upgrade-from-gitea/ 301
/next/upgrade/upgrade-from-gogs /next/category/installation/ 301
/next/usage /next/category/usage/ 301
/next/usage/ /next/category/usage/ 301
/next/usage/actions/act-runner /runner/ 301
/next/usage/agit /next/usage/issues-prs/agit/ 301
/next/usage/agit-setup /next/usage/issues-prs/agit/ 301
/next/usage/authentication /next/administration/authentication/ 301
/next/usage/automatically-linked-references /next/usage/issues-prs/automatically-linked-references/ 301
/next/usage/badge /next/usage/actions/badge/ 301
/next/usage/blame /next/usage/repository/blame/ 301
/next/usage/blocking-user /next/usage/access-control/blocking-user/ 301
/next/usage/clone-filters /next/usage/repository/clone-filters/ 301
/next/usage/code-owners /next/usage/repository/code-owners/ 301
/next/usage/command-line /next/administration/command-line/ 301
/next/usage/email-setup /next/administration/email-setup/ 301
/next/usage/git-lfs-setup /next/administration/git-lfs-setup/ 301
/next/usage/https-setup /next/administration/https-setup/ 301
/next/usage/incoming-email /next/usage/repository/incoming-email/ 301
/next/usage/issue-pull-request-templates /next/usage/issues-prs/issue-pull-request-templates/ 301
/next/usage/labels /next/usage/issues-prs/labels/ 301
/next/usage/markdown /next/usage/repository/markdown/ 301
/next/usage/merge-message-templates /next/usage/issues-prs/merge-message-templates/ 301
/next/usage/migration /next/usage/repository/migration/ 301
/next/usage/multi-factor-authentication /next/usage/user-setting/multi-factor-authentication/ 301
/next/usage/permissions /next/usage/access-control/permissions/ 301
/next/usage/profile-readme /next/usage/repository/profile-readme/ 301
/next/usage/protected-tags /next/usage/access-control/protected-tags/ 301
/next/usage/pull-request /next/usage/issues-prs/pull-request/ 301
/next/usage/push /next/usage/repository/push/ 301
/next/usage/push-options /next/usage/repository/push/ 301
/next/usage/push-to-create /next/usage/repository/push/ 301
/next/usage/repo-mirror /next/usage/repository/repo-mirror/ 301
/next/usage/secrets /next/usage/actions/secrets/ 301
/next/usage/template-repositories /next/usage/repository/template-repositories/ 301
/next/usage/webhooks /next/usage/repository/webhooks/ 301
# ... and under simplified chinese, develop.
/zh-cn/next/actions /zh-cn/next/usage/actions/ 301
/zh-cn/next/actions/ /zh-cn/next/usage/actions/ 301
/zh-cn/next/administration /zh-cn/next/category/administration/ 301
/zh-cn/next/administration/ /zh-cn/next/category/administration/ 301
/zh-cn/next/administration/logging-configuration /zh-cn/next/administration/logging-config/ 301
/zh-cn/next/advanced/adding-legal-pages /zh-cn/next/administration/adding-legal-pages/ 301
/zh-cn/next/advanced/clone-filters /zh-cn/next/usage/repository/clone-filters/ 301
/zh-cn/next/advanced/cmd-embedded /zh-cn/next/administration/cmd-embedded/ 301
/zh-cn/next/advanced/config-cheat-sheet /zh-cn/next/administration/config-cheat-sheet/ 301
/zh-cn/next/advanced/customizing-gitea /zh-cn/next/administration/customizing-gitea/ 301
/zh-cn/next/advanced/environment-variables /zh-cn/next/administration/environment-variables/ 301
/zh-cn/next/advanced/external-renderers /zh-cn/next/administration/external-renderers/ 301
/zh-cn/next/advanced/logging-configuration /zh-cn/next/administration/logging-config/ 301
/zh-cn/next/advanced/mail-templates /zh-cn/next/administration/mail-templates/ 301
/zh-cn/next/advanced/protected-tags /zh-cn/next/usage/access-control/protected-tags/ 301
/zh-cn/next/advanced/repo-indexer /zh-cn/next/administration/repo-indexer/ 301
/zh-cn/next/advanced/repo-mirror /zh-cn/next/usage/repository/repo-mirror/ 301
/zh-cn/next/advanced/search-engines-indexation /zh-cn/next/administration/search-engines-indexation/ 301
/zh-cn/next/advanced/signing /zh-cn/next/administration/signing/ 301
/zh-cn/next/developers/api-usage /zh-cn/next/development/api-usage/ 301
/zh-cn/next/developers/integrations /zh-cn/next/development/integrations/ 301
/zh-cn/next/developers/migrations-interfaces /zh-cn/next/development/migrations-interfaces/ 301
/zh-cn/next/developers/oauth2-provider /zh-cn/next/development/oauth2-provider/ 301
/zh-cn/next/development /zh-cn/next/category/development/ 301
/zh-cn/next/development/ /zh-cn/next/category/development/ 301
/zh-cn/next/features/authentication /zh-cn/next/administration/authentication/ 301
/zh-cn/next/features/comparison /zh-cn/next/installation/comparison/ 301
/zh-cn/next/features/webhooks /zh-cn/next/usage/repository/webhooks/ 301
/zh-cn/next/help /zh-cn/next/category/help/ 301
/zh-cn/next/help/ /zh-cn/next/category/help/ 301
/zh-cn/next/help/seek-help /zh-cn/next/help/support/ 301
/zh-cn/next/installation /zh-cn/next/category/installation/ 301
/zh-cn/next/installation/ /zh-cn/next/category/installation/ 301
/zh-cn/next/installation/upgrade-from-gogs /zh-cn/next/category/installation/ 301
/zh-cn/next/upgrade/upgrade-from-gitea /zh-cn/next/installation/upgrade-from-gitea/ 301
/zh-cn/next/upgrade/upgrade-from-gogs /zh-cn/next/category/installation/ 301
/zh-cn/next/usage /zh-cn/next/category/usage/ 301
/zh-cn/next/usage/ /zh-cn/next/category/usage/ 301
/zh-cn/next/usage/actions/act-runner /runner/ 301
/zh-cn/next/usage/agit-setup /zh-cn/next/usage/issues-prs/agit/ 301
/zh-cn/next/usage/authentication /zh-cn/next/administration/authentication/ 301
/zh-cn/next/usage/automatically-linked-references /zh-cn/next/usage/issues-prs/automatically-linked-references/ 301
/zh-cn/next/usage/badge /zh-cn/next/usage/actions/badge/ 301
/zh-cn/next/usage/blame /zh-cn/next/usage/repository/blame/ 301
/zh-cn/next/usage/blocking-user /zh-cn/next/usage/access-control/blocking-user/ 301
/zh-cn/next/usage/clone-filters /zh-cn/next/usage/repository/clone-filters/ 301
/zh-cn/next/usage/code-owners /zh-cn/next/usage/repository/code-owners/ 301
/zh-cn/next/usage/command-line /zh-cn/next/administration/command-line/ 301
/zh-cn/next/usage/email-setup /zh-cn/next/administration/email-setup/ 301
/zh-cn/next/usage/git-lfs-setup /zh-cn/next/administration/git-lfs-setup/ 301
/zh-cn/next/usage/https-setup /zh-cn/next/administration/https-setup/ 301
/zh-cn/next/usage/incoming-email /zh-cn/next/usage/repository/incoming-email/ 301
/zh-cn/next/usage/issue-pull-request-templates /zh-cn/next/usage/issues-prs/issue-pull-request-templates/ 301
/zh-cn/next/usage/labels /zh-cn/next/usage/issues-prs/labels/ 301
/zh-cn/next/usage/markdown /zh-cn/next/usage/repository/markdown/ 301
/zh-cn/next/usage/merge-message-templates /zh-cn/next/usage/issues-prs/merge-message-templates/ 301
/zh-cn/next/usage/migration /zh-cn/next/usage/repository/migration/ 301
/zh-cn/next/usage/multi-factor-authentication /zh-cn/next/usage/user-setting/multi-factor-authentication/ 301
/zh-cn/next/usage/permissions /zh-cn/next/usage/access-control/permissions/ 301
/zh-cn/next/usage/profile-readme /zh-cn/next/usage/repository/profile-readme/ 301
/zh-cn/next/usage/protected-tags /zh-cn/next/usage/access-control/protected-tags/ 301
/zh-cn/next/usage/pull-request /zh-cn/next/usage/issues-prs/pull-request/ 301
/zh-cn/next/usage/push /zh-cn/next/usage/repository/push/ 301
/zh-cn/next/usage/push-options /zh-cn/next/usage/repository/push/ 301
/zh-cn/next/usage/push-to-create /zh-cn/next/usage/repository/push/ 301
/zh-cn/next/usage/repo-mirror /zh-cn/next/usage/repository/repo-mirror/ 301
/zh-cn/next/usage/secrets /zh-cn/next/usage/actions/secrets/ 301
/zh-cn/next/usage/template-repositories /zh-cn/next/usage/repository/template-repositories/ 301
/zh-cn/next/usage/webhooks /zh-cn/next/usage/repository/webhooks/ 301
# ... and under traditional chinese, develop.
/zh-tw/next/actions /zh-tw/next/usage/actions/ 301
/zh-tw/next/actions/ /zh-tw/next/usage/actions/ 301
/zh-tw/next/administration /zh-tw/next/category/administration/ 301
/zh-tw/next/administration/ /zh-tw/next/category/administration/ 301
/zh-tw/next/administration/logging-configuration /zh-tw/next/administration/logging-config/ 301
/zh-tw/next/advanced/adding-legal-pages /zh-tw/next/administration/adding-legal-pages/ 301
/zh-tw/next/advanced/clone-filters /zh-tw/next/usage/repository/clone-filters/ 301
/zh-tw/next/advanced/cmd-embedded /zh-tw/next/administration/cmd-embedded/ 301
/zh-tw/next/advanced/config-cheat-sheet /zh-tw/next/administration/config-cheat-sheet/ 301
/zh-tw/next/advanced/customizing-gitea /zh-tw/next/administration/customizing-gitea/ 301
/zh-tw/next/advanced/environment-variables /zh-tw/next/administration/environment-variables/ 301
/zh-tw/next/advanced/external-renderers /zh-tw/next/administration/external-renderers/ 301
/zh-tw/next/advanced/logging-configuration /zh-tw/next/administration/logging-config/ 301
/zh-tw/next/advanced/mail-templates /zh-tw/next/administration/mail-templates/ 301
/zh-tw/next/advanced/protected-tags /zh-tw/next/usage/access-control/protected-tags/ 301
/zh-tw/next/advanced/repo-indexer /zh-tw/next/administration/repo-indexer/ 301
/zh-tw/next/advanced/repo-mirror /zh-tw/next/usage/repository/repo-mirror/ 301
/zh-tw/next/advanced/search-engines-indexation /zh-tw/next/administration/search-engines-indexation/ 301
/zh-tw/next/advanced/signing /zh-tw/next/administration/signing/ 301
/zh-tw/next/developers/api-usage /zh-tw/next/development/api-usage/ 301
/zh-tw/next/developers/integrations /zh-tw/next/development/integrations/ 301
/zh-tw/next/developers/migrations-interfaces /zh-tw/next/development/migrations-interfaces/ 301
/zh-tw/next/developers/oauth2-provider /zh-tw/next/development/oauth2-provider/ 301
/zh-tw/next/development /zh-tw/next/category/development/ 301
/zh-tw/next/development/ /zh-tw/next/category/development/ 301
/zh-tw/next/features/authentication /zh-tw/next/administration/authentication/ 301
/zh-tw/next/features/comparison /zh-tw/next/installation/comparison/ 301
/zh-tw/next/features/webhooks /zh-tw/next/usage/repository/webhooks/ 301
/zh-tw/next/help /zh-tw/next/category/help/ 301
/zh-tw/next/help/ /zh-tw/next/category/help/ 301
/zh-tw/next/help/seek-help /zh-tw/next/help/support/ 301
/zh-tw/next/installation /zh-tw/next/category/installation/ 301
/zh-tw/next/installation/ /zh-tw/next/category/installation/ 301
/zh-tw/next/installation/upgrade-from-gogs /zh-tw/next/category/installation/ 301
/zh-tw/next/upgrade/upgrade-from-gitea /zh-tw/next/installation/upgrade-from-gitea/ 301
/zh-tw/next/upgrade/upgrade-from-gogs /zh-tw/next/category/installation/ 301
/zh-tw/next/usage /zh-tw/next/category/usage/ 301
/zh-tw/next/usage/ /zh-tw/next/category/usage/ 301
/zh-tw/next/usage/actions/act-runner /runner/ 301
/zh-tw/next/usage/agit-setup /zh-tw/next/usage/issues-prs/agit/ 301
/zh-tw/next/usage/authentication /zh-tw/next/administration/authentication/ 301
/zh-tw/next/usage/automatically-linked-references /zh-tw/next/usage/issues-prs/automatically-linked-references/ 301
/zh-tw/next/usage/badge /zh-tw/next/usage/actions/badge/ 301
/zh-tw/next/usage/blame /zh-tw/next/usage/repository/blame/ 301
/zh-tw/next/usage/blocking-user /zh-tw/next/usage/access-control/blocking-user/ 301
/zh-tw/next/usage/clone-filters /zh-tw/next/usage/repository/clone-filters/ 301
/zh-tw/next/usage/code-owners /zh-tw/next/usage/repository/code-owners/ 301
/zh-tw/next/usage/command-line /zh-tw/next/administration/command-line/ 301
/zh-tw/next/usage/email-setup /zh-tw/next/administration/email-setup/ 301
/zh-tw/next/usage/git-lfs-setup /zh-tw/next/administration/git-lfs-setup/ 301
/zh-tw/next/usage/https-setup /zh-tw/next/administration/https-setup/ 301
/zh-tw/next/usage/incoming-email /zh-tw/next/usage/repository/incoming-email/ 301
/zh-tw/next/usage/issue-pull-request-templates /zh-tw/next/usage/issues-prs/issue-pull-request-templates/ 301
/zh-tw/next/usage/labels /zh-tw/next/usage/issues-prs/labels/ 301
/zh-tw/next/usage/markdown /zh-tw/next/usage/repository/markdown/ 301
/zh-tw/next/usage/merge-message-templates /zh-tw/next/usage/issues-prs/merge-message-templates/ 301
/zh-tw/next/usage/migration /zh-tw/next/usage/repository/migration/ 301
/zh-tw/next/usage/multi-factor-authentication /zh-tw/next/usage/user-setting/multi-factor-authentication/ 301
/zh-tw/next/usage/permissions /zh-tw/next/usage/access-control/permissions/ 301
/zh-tw/next/usage/protected-tags /zh-tw/next/usage/access-control/protected-tags/ 301
/zh-tw/next/usage/pull-request /zh-tw/next/usage/issues-prs/pull-request/ 301
/zh-tw/next/usage/push /zh-tw/next/usage/repository/push/ 301
/zh-tw/next/usage/push-options /zh-tw/next/usage/repository/push/ 301
/zh-tw/next/usage/push-to-create /zh-tw/next/usage/repository/push/ 301
/zh-tw/next/usage/repo-mirror /zh-tw/next/usage/repository/repo-mirror/ 301
/zh-tw/next/usage/secrets /zh-tw/next/usage/actions/secrets/ 301
/zh-tw/next/usage/template-repositories /zh-tw/next/usage/repository/template-repositories/ 301
/zh-tw/next/usage/webhooks /zh-tw/next/usage/repository/webhooks/ 301
# Runner versions that were published under their full number, and the develop
# runner docs, which used to be `next`.
/runner/0.2.11/* /runner/0/:splat 301
/runner/1.0.8/* /runner/1/:splat 301
/runner/next/* /runner/develop/:splat 301
+32
View File
@@ -0,0 +1,32 @@
{
"_comment": "Algolia DocSearch crawler configuration. The three facets come from the docsearch:* meta tags every page carries; only the versions people read are indexed, the older ones stay reachable through the version picker.",
"index_name": "gitea",
"start_urls": [
"https://docs.gitea.com/",
"https://docs.gitea.com/next/",
"https://docs.gitea.com/zh-cn/",
"https://docs.gitea.com/zh-tw/",
"https://docs.gitea.com/runner/",
"https://docs.gitea.com/api/",
"https://docs.gitea.com/enterprise/"
],
"sitemap_urls": ["https://docs.gitea.com/sitemap-index.xml"],
"exclusion_patterns": [
"https://docs.gitea.com/1.2*/**",
"https://docs.gitea.com/*/1.2*/**",
"https://docs.gitea.com/api/1.2*/**",
"https://docs.gitea.com/runner/[0-9]/**"
],
"selectors": {
"lvl0": { "selector": "//nav[contains(@aria-labelledby,'starlight__sidebar')]//a[@aria-current='page']/ancestor::details//summary//span", "type": "xpath", "global": true, "default_value": "Documentation" },
"lvl1": ".sl-markdown-content h1, h1",
"lvl2": ".sl-markdown-content h2",
"lvl3": ".sl-markdown-content h3",
"lvl4": ".sl-markdown-content h4",
"text": ".sl-markdown-content p, .sl-markdown-content li, .sl-markdown-content td"
},
"custom_settings": {
"attributesForFaceting": ["product", "version", "language"]
},
"conversation_id": []
}
+2 -2
View File
@@ -12,10 +12,10 @@ Some jurisdictions (such as EU), requires certain legal pages (e.g. Privacy Poli
## Getting Pages
Gitea source code ships with sample pages, available in `contrib/legal` directory. Copy them to `custom/public/assets/`. For example, to add Privacy Policy:
Gitea source code ships with sample pages, available in `contrib/service/sample-page` directory. Copy them to `custom/public/assets/`. For example, to add Privacy Policy:
```bash
wget -O /path/to/custom/public/assets/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
wget -O /path/to/custom/public/assets/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/service/sample-page/privacy.html.sample
```
Now you need to edit the page to meet your requirements. In particular you must change the email addresses, web addresses and references to "Your Gitea Instance" to match your situation.
+153
View File
@@ -0,0 +1,153 @@
---
date: "2026-09-12T00:00:00+00:00"
slug: "audit-logging"
sidebar_position: 41
aliases:
- /en-us/audit-logging
---
# Audit Logging
Gitea can record security-relevant events as structured audit records: each
event has an `action`, `actor`, `scope`, `origin`, `message` and a JSON
`metadata` blob. Recording is **off by default** and does not change request
behavior when it is disabled.
This is separate from the application, router and access logs described in
[Logging Configuration](logging-config.md). Those logs are for operations and
debugging. The audit log is a durable trail of who changed what.
## Enable recording
Set `[audit].RECORD_OUTPUT` to `database` in `app.ini` and restart Gitea:
```ini
[audit]
RECORD_OUTPUT = database
RETENTION_DAYS = 30
```
Invalid values of `RECORD_OUTPUT` fall back to `disabled`. See the
[configuration cheat sheet](config-cheat-sheet.md#audit-audit) for every option.
With Docker, the same settings can be applied as
`GITEA__audit__RECORD_OUTPUT=database` and `GITEA__audit__RETENTION_DAYS=30`
before Gitea writes them into `app.ini`.
## View events
The Audit Log pages are always available and still list any events that were
stored earlier. When recording is disabled, the site administration page also
shows a warning.
| Audience | Location | Events shown |
| --- | --- | --- |
| Site administrators | Site administration → Monitoring → Audit Log (`/-/admin/monitor/audit_logs`) | Every event |
| Signed-in users | User settings → Audit Log (`/user/settings/audit_logs`) | Events scoped to that user |
| Organization owners | Organization settings → Audit Log (`/<org>/settings/audit_logs`) | Events scoped to that organization |
| Repository administrators | Repository settings → Audit Log (`/<owner>/<repo>/settings/audit_logs`) | Events scoped to that repository |
Each listing can be filtered by actor (username), action and origin, and sorted
by timestamp. The actor filter does not match the
[system actors](#actors-and-origins). Action filters accept an exact action or
a family prefix such as `user:impersonation` or `repository:webhook`.
Site administrators can download the current filtered result as JSONL
(newline-delimited JSON) from **Export JSONL**. The file name is
`gitea-audit-log-<timestamp>.jsonl`.
## Event shape
A recorded event contains:
- **Action**: a stable, colon-separated identifier such as `repository:archive`
or `user:accesstoken:add`.
- **Actor**: the user who performed the action. Actions taken while impersonating
a user record both the impersonator and the impersonated user.
- **Actor credential**: when the request authenticated with a named credential,
the event stores its kind and id, never the secret. Typical values:
`access-token:<id>`, `oauth2-grant:<id>`, `gitea-actions:<task id>`,
`deploy-key:<key id>`.
- **Scope**: the affected unit — `user`, `organization`, `repository` or
`system` (instance-wide).
- **Origin**: how the action was initiated — `ui`, `api`, `cli` or `system`.
- **Message**: a human-readable sentence rendered from a per-action template.
- **Metadata**: extra fields that fill the message template (token name, new
visibility, and so on). Secrets and token values are not stored.
- **IP address**: the client address of the request, when one exists. Events
triggered by a git push record the SSH client address for SSH pushes and
`127.0.0.1` for HTTP pushes.
- **Timestamp**: when the event was recorded.
An exported JSONL line looks like:
```json
{"action":"repository:archive","actor":{"type":"user","id":1,"name":"alice"},"scope":{"type":"repository","id":42,"name":"org/repo"},"message":"Archived repository org/repo.","time":"2026-09-12T11:00:00Z","ip_address":"203.0.113.10","origin":"ui"}
```
The `system:startup` message is kept stable across Gitea versions so operators
can parse it: `System started [Gitea {version}]`.
## Actors and origins
Most web and API requests pick up the signed-in user automatically.
Other entry points record a system actor:
- `gitea:cli` for `gitea admin` commands and the `system:startup` and
`system:shutdown` events
- `gitea:auth-source` for authentication-source syncs and for users an
authentication source creates or updates at sign-in
- `gitea-actions` for Gitea Actions tasks
- `gitea:deploy-key` for pushes with a deploy key
- `(Cron)` for scheduled cron tasks
- `Unknown` when no actor can be resolved
Events of the `gitea:cli` actor use origin `cli`. Cron tasks, git hooks and
other background work use origin `system`.
## What is recorded
Events cover security-relevant changes, grouped by action family:
- **User**: create and delete, admin, restricted and active status, name,
password and password reset requests, visibility, emails, authentication
source, 2FA, WebAuthn, OpenID, external logins, access tokens, OAuth2
applications and grants, SSH/GPG/principal keys, secrets, webhooks,
impersonation, failed two-factor authentication
- **Organization**: create and delete, name, visibility, members, teams,
OAuth2 applications, secrets, webhooks
- **Repository**: create, fork, archive, delete, rename, visibility, transfer,
mirrors, signing verification, collaborators and teams, default branch,
branch and tag protection, deploy keys, webhooks, secrets
- **Issues and pull requests**: create, delete, comments and merges
- **Projects and wiki pages**: create, update and delete
- **Actions**: enable, disable and dispatch a workflow
- **System**: startup and shutdown, instance-wide webhooks, authentication
sources, instance-wide OAuth2 applications
Recording never fails the request that triggered it. A write error is logged
and the original operation continues.
## What is not recorded
- Read-only access such as browsing, clone, fetch or API GET requests
- Logins, successful or failed, other than failed two-factor authentication
(use the [access log](logging-config.md) and
[Fail2ban Setup](fail2ban-setup.md) for authentication traffic)
- Edits to issues and pull requests
- Token or secret values
- Which SSH key a real user pushed with (deploy keys are named; ordinary SSH
user pushes are not)
## Retention
`RETENTION_DAYS` (default **30**) is the age after which recorded events are
eligible for deletion. Set it to `0` to keep events forever.
Cleanup is performed by the `cron.delete_old_audit_events` task (`SCHEDULE`
defaults to `@every 24h`, `OLDER_THAN` defaults to `[audit].RETENTION_DAYS`).
The task is registered only while `RECORD_OUTPUT` records events **and**
`RETENTION_DAYS` is greater than `0`. Turning recording off therefore also
stops pruning; existing rows stay until you delete them or turn recording back
on.
+89 -2
View File
@@ -337,9 +337,13 @@ The default login user email is `X-WEBAUTH-EMAIL`, you can change it via changin
If set `ENABLE_REVERSE_PROXY_FULL_NAME=true`, a user full name expected in `X-WEBAUTH-FULLNAME` will be assigned to the user when auto creating the user. You can also change the header name with `REVERSE_PROXY_AUTHENTICATION_FULL_NAME`.
You can also limit the reverse proxy's IP address range with `REVERSE_PROXY_TRUSTED_PROXIES` which default value is `127.0.0.0/8,::1/128`. By `REVERSE_PROXY_LIMIT`, you can limit trusted proxies level.
It applies to the web interface, Git over HTTP, Git LFS and the package registry.
You can enable the this authentication method for the API with
:::warning
Gitea trusts these headers on every request it receives. Make sure Gitea is only reachable through your authenticating proxy, and that the proxy sets or removes these headers on every request, including on paths you exempt from authentication, for example for Git or package clients. `REVERSE_PROXY_TRUSTED_PROXIES` does not restrict them.
:::
To also accept them on the REST API under `/api/v1`, enable:
```ini
[service]
@@ -349,3 +353,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.
:::
+1 -1
View File
@@ -83,7 +83,7 @@ cd gitea-dump-1610949662
mv app.ini /etc/gitea/conf/app.ini
mv data/* /var/lib/gitea/data/
mv log/* /var/lib/gitea/log/
mv repos/* /var/lib/gitea/data/repositories/
mv repos/* /var/lib/gitea/data/gitea-repositories/
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea
# mysql
+3
View File
@@ -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
+251 -137
View File
@@ -34,8 +34,39 @@ A full restart is required for Gitea configuration changes to take effect.
## Use environment variables to setup Gitea
There is [environment-to-ini](https://github.com/go-gitea/gitea/blob/main/docker/root/usr/local/bin/environment-to-ini) to help to
generate Gitea's `app.ini` from environment variables.
Gitea supports setting `app.ini` values via environment variables of the form `GITEA__<section>__<KEY>`. These require running `gitea config edit-ini --in-place --apply-env` before starting Gitea to write them into `app.ini`. The official Docker images do this automatically on container startup.
:::info
If `<section>` or `<KEY>` contains a `.`, replace that with `_0X2E_`; if it contains a `-`, replace it with `_0X2C_`
:::
For example, to configure the database connection via environment variables:
```
GITEA__database__DB_TYPE=postgres
GITEA__database__HOST=127.0.0.1:5432
GITEA__database__NAME=gitea
GITEA__database__USER=gitea
GITEA__database__PASSWD=secret
```
This is equivalent to the following `app.ini` configuration:
```ini
[database]
DB_TYPE = postgres
HOST = 127.0.0.1:5432
NAME = gitea
USER = gitea
PASSWD = secret
```
You can also load values from files by appending `__FILE` to the variable name. This is useful for Docker secrets:
```
GITEA__database__PASSWD__FILE=/run/secrets/db_password
```
## Default Internal Variables (non-`app.ini` configuration)
@@ -80,21 +111,27 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
A relative path is interpreted as **`{AppWorkPath}/{ROOT}`**.
- `SCRIPT_TYPE`: **bash**: The script type this server supports. Usually this is `bash`,
but some users report that only `sh` is available.
- `DEFAULT_OBJECT_FORMAT`: **sha1**: The default object format for new repositories. Valid values are `sha1` and `sha256`.
- `DETECTED_CHARSETS_ORDER`: **UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, ISO-8859, windows-1252, ISO-8859, windows-1250, ISO-8859, ISO-8859, ISO-8859, windows-1253, ISO-8859, windows-1255, ISO-8859, windows-1251, windows-1256, KOI8-R, ISO-8859, windows-1254, Shift_JIS, GB18030, EUC-JP, EUC-KR, Big5, ISO-2022, ISO-2022, ISO-2022, IBM424_rtl, IBM424_ltr, IBM420_rtl, IBM420_ltr**: Tie-break order of detected charsets - if the detected charsets have equal confidence, charsets earlier in the list will be chosen in preference to those later. Adding `defaults` will place the unnamed charsets at that point.
- `ANSI_CHARSET`: **_empty_**: Default ANSI charset to override non-UTF-8 charsets to.
- `FORCE_PRIVATE`: **false**: Force every new repository to be private.
- `DEFAULT_PRIVATE`: **last**: Default private when creating a new repository: `last`, `private`, `public`
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: Default private when creating a new repository with push-to-create.
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user,
`-1` means no limit.
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user/org,
`-1` means no limit. Acts as a shortcut: sets the default value for both
`USER_MAX_CREATION_LIMIT` and `ORG_MAX_CREATION_LIMIT` when those are not configured.
- `USER_MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user,
applied at creation time. `-1` means no limit. Takes precedence over `MAX_CREATION_LIMIT` when set.
- `ORG_MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per organization,
applied at creation time. `-1` means no limit. Takes precedence over `MAX_CREATION_LIMIT` when set.
- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: Preferred Licenses to place at
the top of the list. Name must match file name in options/license or custom/options/license.
- `DISABLE_HTTP_GIT`: **false**: Disable the ability to interact with repositories over the
HTTP protocol.
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when
default SSH port is used.
- `GO_GET_CLONE_URL_PROTOCOL`: **https**: Value for the "go get" request returns the repository url as https or ssh
default is https.
- `GO_GET_CLONE_URL_PROTOCOL`: **_empty_**: Scheme of the returned URL for the "go get" response.
Default is "https" if DISABLE_HTTP_GIT=false or SSH is disabled, otherwise "ssh".
- `ACCESS_CONTROL_ALLOW_ORIGIN`: **_empty_**: Value for Access-Control-Allow-Origin header,
default is not to present.
@@ -118,7 +155,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
- `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to delete unadopted repositories
- `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: Don't allow download source archive files from UI
- `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT`: **true**: Allow to fork repositories without maximum number limit
- `ALLOW_FORK_INTO_SAME_OWNER`: **false**: Allow to fork repositories into the same owner (user or organization). This feature is experimental, not fully tested, and may be changed in the future
- `ALLOW_FORK_INTO_SAME_OWNER`: **false**: Allow to fork repositories into the same owner (user or organization).
### Repository - Editor (`repository.editor`)
@@ -141,8 +178,12 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
- `DEFAULT_MERGE_MESSAGE_OFFICIAL_APPROVERS_ONLY`: **true**: In default merge messages only include approvers who are officially allowed to review.
- `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`: **false**: In default squash-merge messages include the commit message of all commits comprising the pull request.
- `ADD_CO_COMMITTER_TRAILERS`: **true**: Add co-authored-by and co-committed-by trailers to merge commit messages if committer does not match author.
- `TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY`: **false**: PR patches are tested using a three-way merge method to discover if there are conflicts. If this setting is set to **true**, conflicting patches will be retested using `git apply` - This was the previous behaviour in 1.18 (and earlier) but is somewhat inefficient. Please report if you find that this setting is required.
- `RETARGET_CHILDREN_ON_MERGE`: **true**: Retarget child pull requests to the parent pull request branch target on merge of parent pull request. It only works on merged PRs where the head and base branch target the same repo.
- `DEFAULT_DELETE_BRANCH_AFTER_MERGE`: **false**: Set the default value for "Delete pull request branch after merge by default" for new repositories.
- `DEFAULT_TITLE_SOURCE`: **auto**: Default source for the pull request title when opening a new PR. Valid options:
- `first-commit`: Uses the oldest commit's summary as the title. If there are multiple commits, still uses the first commit's message.
- `auto`: Uses the commit's summary when the PR contains a single commit; when there are multiple commits, converts the branch name into a human-readable title by normalizing separators and casing.
- `branch-name`: Always uses the PR's branch name.
### Repository - Issue (`repository.issue`)
@@ -159,9 +200,11 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
### Repository - Release (`repository.release`)
- `ALLOWED_TYPES`: **_empty_**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
- `ALLOWED_TYPES`: **_empty_**: Comma-separated list of allowed release attachment file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
- `DEFAULT_PAGING_NUM`: **10**: The default paging number of releases user interface
- For settings related to file attachments on releases, see the `attachment` section.
- `FILE_MAX_SIZE`: **2048**: Max filesize limit for release attachments (MB)
- `MAX_FILES`: **5**: Maximum number of release attachments that can be uploaded at once for a release.
- For other settings related to file attachments on releases, see the `attachment` section.
### Repository - Signing (`repository.signing`)
@@ -209,7 +252,6 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `MAX_AGE`: **10m**: max time to cache response
- `ALLOW_CREDENTIALS`: **false**: allow request with credentials
- `HEADERS`: **Content-Type,User-Agent**: additional headers that are permitted in requests
- `X_FRAME_OPTIONS`: **SAMEORIGIN**: Set the `X-Frame-Options` header value.
## UI (`ui`)
@@ -228,9 +270,10 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `FOLDER_ICON_THEME`: **basic**: The icon theme for folders (basic/material).
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
- `AMBIGUOUS_UNICODE_DETECTION`: **true**: Detect ambiguous unicode characters in file contents and show warnings on the UI
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
- `REACTIONS`: All available reactions users can choose on issues, pull requests and comments.
Values can be emoji alias (:smile:) or a unicode emoji.
For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
- `RELEASE_REACTIONS`: **+1, laugh, hooray, heart, rocket, eyes**: Reactions available for releases, in the same format as `REACTIONS`.
- `REACTION_MAX_USER_NUM`: **10**: Change the number of users that are displayed in reactions tooltip (triggered by mouse hover).
- `CUSTOM_EMOJIS`: **gitea, codeberg, gitlab, git, github, gogs**: Additional Emojis not defined in the utf8 standard.
By default, we support Gitea (:gitea:), to add more copy them to public/assets/img/emoji/emoji_name.png and
@@ -306,15 +349,14 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `PROXY_PROTOCOL_TLS_BRIDGING`: **false**: When protocol is https, expect PROXY protocol headers after TLS negotiation.
- `PROXY_PROTOCOL_HEADER_TIMEOUT`: **5s**: Timeout to wait for PROXY protocol header (set to 0 to have no timeout)
- `PROXY_PROTOCOL_ACCEPT_UNKNOWN`: **false**: Accept PROXY protocol headers with Unknown type.
- `DOMAIN`: **localhost**: Domain name of this server.
- `ROOT_URL`: **`{PROTOCOL}://{DOMAIN}:{HTTP_PORT}/`**:
- `ROOT_URL`: **`{PROTOCOL}://localhost:{HTTP_PORT}/`**:
Overwrite the automatically generated public URL.
This is useful if the internal and the external URL don't match (e.g. behind a reverse proxy).
- `PUBLIC_URL_DETECTION`: **`legacy`**: Controls how to generate the public URL.
Although it defaults to "legacy" (to avoid breaking existing users), most instances should use the "auto" behavior,
- `PUBLIC_URL_DETECTION`: **`auto`**: Controls how to generate the public URL. Most instances should use the "auto" behavior,
especially when the Gitea instance needs to be accessed in a container network.
- "legacy": generate the public URL by "Host" header if "X-Forwarded-Proto" header exists, otherwise use "ROOT_URL".
- "auto": always use "Host" header, and also use "X-Forwarded-Proto" header if it exists. If no "Host" header, use "ROOT_URL".
- "never": always use "ROOT_URL", never detect from request headers.
- `STATIC_URL_PREFIX`: **_empty_**:
Overwrite this option to request static resources from a different URL.
This includes CSS files, images, JS files and web fonts.
@@ -362,23 +404,23 @@ The following configuration set `Content-Type: application/vnd.android.package-a
If it is set to `(DOER_USERNAME)`, it will use current signed-in user's username.
This option is only for some advanced users who have configured their SSH reverse-proxy and need to use different usernames for git SSH clone.
Most users should just leave it blank and/or modify the `BUILTIN_SSH_SERVER_USER`.
- `SSH_DOMAIN`: **`{DOMAIN}`**: Domain name of this server, used for displayed clone URL.
- `SSH_PORT`: **22**: SSH port displayed in clone URL.
- `SSH_DOMAIN`: **_empty_**: Domain name to be exposed in clone URL, defaults to the domain part of ROOT_URL
- `SSH_PORT`: **22**: SSH port displayed in clone URL. If you need a different "SSH clone port" from the real "SSH listen port", set the SSH_LISTEN_PORT separately.
- `SSH_LISTEN_HOST`: **0.0.0.0**: Listen address for the built-in SSH server.
- `SSH_LISTEN_PORT`: **`{SSH_PORT}`**: Port for the built-in SSH server.
- `SSH_ROOT_PATH`: **~/.ssh**: Root path of SSH directory.
- `SSH_CREATE_AUTHORIZED_KEYS_FILE`: **true**: Gitea will create a authorized_keys file by default when it is not using the internal ssh server. If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
- `SSH_ROOT_PATH`: **_empty_**: Root path of SSH user directory for the system's standalone SSH server if Gitea is not using its builtin SSH server. Default is the '.ssh' directory in the run user's home directory.
- `SSH_CREATE_AUTHORIZED_KEYS_FILE`: **true**: Gitea will create an authorized_keys file by default when it is not using the builtin SSH server. If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
- `SSH_AUTHORIZED_KEYS_BACKUP`: **false**: Enable SSH Authorized Key Backup when rewriting all keys, default is false.
- `SSH_TRUSTED_USER_CA_KEYS`: **_empty_**: Specifies the public keys of certificate authorities that are trusted to sign user certificates for authentication. Multiple keys should be comma separated. E.g.`ssh-<algorithm> <key>` or `ssh-<algorithm> <key1>, ssh-<algorithm> <key2>`. For more information see `TrustedUserCAKeys` in the sshd config man pages. When empty no file will be created and `SSH_AUTHORIZED_PRINCIPALS_ALLOW` will default to `off`.
- `SSH_TRUSTED_USER_CA_KEYS_FILENAME`: **`RUN_USER`/.ssh/gitea-trusted-user-ca-keys.pem**: Absolute path of the `TrustedUserCaKeys` file Gitea will manage. If you're running your own ssh server and you want to use the Gitea managed file you'll also need to modify your sshd_config to point to this file. The official docker image will automatically work without further configuration.
- `SSH_AUTHORIZED_PRINCIPALS_ALLOW`: **off** or **username, email**: \[off, username, email, anything\]: Specify the principals values that users are allowed to use as principal. When set to `anything` no checks are done on the principal string. When set to `off` authorized principal are not allowed to be set.
- `SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE`: **false/true**: Gitea will create a authorized_principals file by default when it is not using the internal ssh server and `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
- `SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE`: **false/true**: Gitea will create an authorized_principals file by default when it is not using the builtin SSH server and `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
- `SSH_AUTHORIZED_PRINCIPALS_BACKUP`: **false/true**: Enable SSH Authorized Principals Backup when rewriting all keys, default is true if `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
- `SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE`: **`{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}`**: Set the template for the command to passed on authorized keys. Possible keys are: AppPath, AppWorkPath, CustomConf, CustomPath, Key - where Key is a `models/asymkey.PublicKey` and the others are strings which are shellquoted.
- `SSH_SERVER_CIPHERS`: **`chacha20-poly1305@openssh.com`, `aes128-ctr`, `aes192-ctr`, `aes256-ctr`, `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`**: For the built-in SSH server, choose the ciphers to support for SSH connections, for system SSH this setting has no effect.
- `SSH_SERVER_KEY_EXCHANGES`: **curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1**: For the built-in SSH server, choose the key exchange algorithms to support for SSH connections, for system SSH this setting has no effect.
- `SSH_SERVER_MACS`: **`hmac-sha2-256-etm@openssh.com`, `hmac-sha2-256`, `hmac-sha1`**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect
- `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gogs.rsa**: For the built-in SSH server, choose the keypairs to offer as the host key. The private key should be at `SSH_SERVER_HOST_KEY` and the public `SSH_SERVER_HOST_KEY.pub`. Relative paths are made absolute relative to the `APP_DATA_PATH`. If no key exists a 4096 bit RSA key will be created for you.
- `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gitea.ed25519, ssh/gitea.ecdsa, ssh/gogs.rsa**: For the built-in SSH server, choose the keypairs to offer as the host key. The private key should be at `SSH_SERVER_HOST_KEY` and the public `SSH_SERVER_HOST_KEY.pub`. Relative paths are made absolute relative to the `APP_DATA_PATH`. If none of the keys exist, a 4096 bit RSA, a 256 bit ECDSA and an ED25519 key will be created for you.
- `SSH_KEY_TEST_PATH`: **/tmp**: Directory to create temporary files in when testing public keys using ssh-keygen, default is the system temporary directory.
- `SSH_KEYGEN_PATH`: **_empty_**: Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
- `SSH_EXPOSE_ANONYMOUS`: **false**: Enable exposure of SSH clone URL to anonymous visitors, default is false.
@@ -410,46 +452,14 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, allows redirecting http requests on `PORT_TO_REDIRECT` to the https port Gitea listens on.
- `REDIRECTOR_USE_PROXY_PROTOCOL`: **`{USE_PROXY_PROTOCOL}`**: expect PROXY protocol header on connections to https redirector.
- `PORT_TO_REDIRECT`: **80**: Port for the http redirection service to listen on. Used when `REDIRECT_OTHER_PORT` is true.
- `SSL_MIN_VERSION`: **TLSv1.2**: Set the minimum version of ssl support.
- `SSL_MAX_VERSION`: **_empty_**: Set the maximum version of ssl support.
- `SSL_CURVE_PREFERENCES`: **X25519,P256**: Set the preferred curves,
- `SSL_CIPHER_SUITES`: **ecdhe_ecdsa_with_aes_256_gcm_sha384,ecdhe_rsa_with_aes_256_gcm_sha384,ecdhe_ecdsa_with_aes_128_gcm_sha256,ecdhe_rsa_with_aes_128_gcm_sha256,ecdhe_ecdsa_with_chacha20_poly1305,ecdhe_rsa_with_chacha20_poly1305**: Set the preferred cipher suites.
- If there is no hardware support for AES suites, by default the ChaCha suites will be preferred over the AES suites.
- supported suites as of Go 1.18 are:
- TLS 1.0 - 1.2 cipher suites
- "rsa_with_rc4_128_sha"
- "rsa_with_3des_ede_cbc_sha"
- "rsa_with_aes_128_cbc_sha"
- "rsa_with_aes_256_cbc_sha"
- "rsa_with_aes_128_cbc_sha256"
- "rsa_with_aes_128_gcm_sha256"
- "rsa_with_aes_256_gcm_sha384"
- "ecdhe_ecdsa_with_rc4_128_sha"
- "ecdhe_ecdsa_with_aes_128_cbc_sha"
- "ecdhe_ecdsa_with_aes_256_cbc_sha"
- "ecdhe_rsa_with_rc4_128_sha"
- "ecdhe_rsa_with_3des_ede_cbc_sha"
- "ecdhe_rsa_with_aes_128_cbc_sha"
- "ecdhe_rsa_with_aes_256_cbc_sha"
- "ecdhe_ecdsa_with_aes_128_cbc_sha256"
- "ecdhe_rsa_with_aes_128_cbc_sha256"
- "ecdhe_rsa_with_aes_128_gcm_sha256"
- "ecdhe_ecdsa_with_aes_128_gcm_sha256"
- "ecdhe_rsa_with_aes_256_gcm_sha384"
- "ecdhe_ecdsa_with_aes_256_gcm_sha384"
- "ecdhe_rsa_with_chacha20_poly1305_sha256"
- "ecdhe_ecdsa_with_chacha20_poly1305_sha256"
- TLS 1.3 cipher suites
- "aes_128_gcm_sha256"
- "aes_256_gcm_sha384"
- "chacha20_poly1305_sha256"
- Aliased names
- "ecdhe_rsa_with_chacha20_poly1305" is an alias for "ecdhe_rsa_with_chacha20_poly1305_sha256"
- "ecdhe_ecdsa_with_chacha20_poly1305" is alias for "ecdhe_ecdsa_with_chacha20_poly1305_sha256"
- `SSL_MIN_VERSION`: **_empty_**: Minimum supported TLS version, one of TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3. Unset uses Go's default.
- `SSL_MAX_VERSION`: **_empty_**: Maximum supported TLS version, one of TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3. Unset uses Go's default.
- `SSL_CURVE_PREFERENCES`: **_empty_**: Comma-separated list of SSL curve preferences. Unset uses Go's default.
- `SSL_CIPHER_SUITES`: **_empty_**: Comma-separated list of SSL cipher suites. Unset uses Go's default.
- `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
@@ -479,7 +489,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `require`: Enable TLS without any verifications.
- `verify-ca`: Enable TLS with verification of the database server certificate against its root certificate.
- `verify-full`: Enable TLS and verify the database server name matches the given certificate in either the `Common Name` or `Subject Alternative Name` fields.
- `SQLITE_TIMEOUT`: **500**: Query timeout for SQLite3 only.
- `SQLITE_TIMEOUT`: **20000**: Query timeout in milliseconds, for SQLite3 only.
- `SQLITE_JOURNAL_MODE`: **""**: Change journal mode for SQlite3. Can be used to enable [WAL mode](https://www.sqlite.org/wal.html) when high load causes write congestion. See [SQlite3 docs](https://www.sqlite.org/pragma.html#pragma_journal_mode) for possible values. Defaults to the default for the database file, often DELETE.
- `ITERATE_BUFFER_SIZE`: **50**: Internal buffer size for iterating.
- `PATH`: **data/gitea.db**: For SQLite3 only, the database file path.
@@ -499,14 +509,14 @@ relation to port exhaustion.
## Indexer (`indexer`)
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db`, `elasticsearch` or `meilisearch`.
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db`, `elasticsearch` (also compatible with OpenSearch) or `meilisearch`.
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch (e.g. `http://elastic:password@localhost:9200`) or meilisearch (e.g. `http://:apikey@localhost:7700`)
- `ISSUE_INDEXER_NAME`: **gitea_issues**: Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch or meilisearch.
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch. Relative paths will be made absolute against _`AppWorkPath`_.
- `REPO_INDEXER_ENABLED`: **false**: Enables code search (uses a lot of disk space, about 6 times more than the repository size).
- `REPO_INDEXER_REPO_TYPES`: **sources,forks,mirrors,templates**: Repo indexer units. The items to index could be `sources`, `forks`, `mirrors`, `templates` or any combination of them separated by a comma. If empty then it defaults to `sources` only, as if you'd like to disable fully please see `REPO_INDEXER_ENABLED`.
- `REPO_INDEXER_TYPE`: **bleve**: Code search engine type, could be `bleve` or `elasticsearch`.
- `REPO_INDEXER_TYPE`: **bleve**: Code search engine type, could be `bleve` or `elasticsearch` (also compatible with OpenSearch).
- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: Index file used for code search.
- `REPO_INDEXER_CONN_STR`: ****: Code indexer connection string, available when `REPO_INDEXER_TYPE` is elasticsearch. i.e. `http://elastic:password@localhost:9200`
- `REPO_INDEXER_NAME`: **gitea_codes**: Code indexer name, available when `REPO_INDEXER_TYPE` is elasticsearch
@@ -517,6 +527,10 @@ relation to port exhaustion.
- `MAX_FILE_SIZE`: **1048576**: Maximum size in bytes of files to be indexed.
- `STARTUP_TIMEOUT`: **30s**: If the indexer takes longer than this timeout to start - fail. (This timeout will be added to the hammer time above for child processes - as bleve will not start until the previous parent is shutdown.) Set to -1 to never timeout.
## Redis (`redis`)
- `CONN_STR`: **_empty_**: Shared default Redis connection string. When a redis-backed subsystem (`[cache]`, `[session]`, `[queue]`, `[global_lock]`) is configured to use Redis but its own connection string is empty, it falls back to this value. A subsystem's own connection string always takes precedence, so different subsystems can still use different Redis instances.
## Queue (`queue` and `queue.*`)
Configuration at `[queue]` will set defaults for queues with overrides for individual queues at `[queue.*]`. (However see below.)
@@ -525,7 +539,7 @@ Configuration at `[queue]` will set defaults for queues with overrides for indiv
- `DATADIR`: **queues/common**: Base DataDir for storing level queues. `DATADIR` for individual queues can be set in `queue.name` sections. Relative paths will be made absolute against `{APP_DATA_PATH}`.
- `LENGTH`: **100000**: Maximal queue size before channel queues block
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. Several redis connections schemes are supported. To see all available `uri.Scheme` types, see [here](https://github.com/go-gitea/gitea/blob/main/modules/nosql/manager_redis.go#L98-L123). For example, if you're running a Redis cluster, use `redis+cluster://127.0.0.1:6379/0`. Options can be set using query params. Similarly, LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. If left empty while `TYPE` is `redis`, it falls back to [redis/CONN_STR](#redis-redis) when that is set. Several redis connections schemes are supported. To see all available `uri.Scheme` types, see [here](https://github.com/go-gitea/gitea/blob/main/modules/nosql/manager_redis.go#L98-L123). For example, if you're running a Redis cluster, use `redis+cluster://127.0.0.1:6379/0`. Options can be set using query params. Similarly, LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
- `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section.
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to **`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden in the specific `queue.name` section.
- `MAX_WORKERS`: **(dynamic)**: Maximum number of worker go-routines for the queue. Default value is "CpuNum/2" clipped to between 1 and 10.
@@ -573,8 +587,8 @@ And the following unique queues:
- `SECRET_KEY`: **\<random at every install\>**: Global secret key. This key is VERY IMPORTANT, if you lost it, the data encrypted by it (like 2FA secret) can't be decrypted anymore.
- `SECRET_KEY_URI`: **_empty_**: Instead of defining SECRET_KEY, this option can be used to use the key stored in a file (example value: `file:/etc/gitea/secret_key`). It shouldn't be lost like SECRET_KEY.
- `LOGIN_REMEMBER_DAYS`: **31**: How long to remember that a user is logged in before requiring relogin (in days).
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication
information.
- `COOKIE_REMEMBER_NAME`: **gitea\_remember**: Name of cookie used to store authentication information.
- `REVERSE_PROXY_LOGOUT_REDIRECT`: **_empty_**: URL or relative path to redirect users to after logout when authentication is handled by a reverse proxy or SSO. For example: `/my-sso/logout?return=/my-sso/home`.
- `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**: Header name for reverse proxy
authentication.
- `REVERSE_PROXY_AUTHENTICATION_EMAIL`: **X-WEBAUTH-EMAIL**: Header name for reverse proxy
@@ -584,6 +598,9 @@ And the following unique queues:
- `REVERSE_PROXY_LIMIT`: **1**: Interpret X-Forwarded-For header or the X-Real-IP header and set this as the remote IP for the request.
Number of trusted proxy count. Set to zero to not use these headers.
- `REVERSE_PROXY_TRUSTED_PROXIES`: **127.0.0.0/8,::1/128**: List of IP addresses and networks separated by comma of trusted proxy servers. Use `*` to trust all.
- `X_FRAME_OPTIONS`: **SAMEORIGIN**: Set the `X-Frame-Options` header value for all HTTP responses. Set to `unset` to not send the header. Previously located in `[cors]`.
- `X_CONTENT_TYPE_OPTIONS`: **nosniff**: Set the `X-Content-Type-Options` header value for all HTTP responses. Set to `unset` to not send the header.
- `CONTENT_SECURITY_POLICY_GENERAL`: **_empty_**: The value of the general Content-Security-Policy for most web pages. Leave it empty to apply the default policy, or set it to "unset" to disable Content-Security-Polic.
- `DISABLE_GIT_HOOKS`: **true**: Set to `false` to enable users with Git Hook privilege to create custom Git Hooks.
:::warning
@@ -629,6 +646,30 @@ And the following unique queues:
- `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.
- `EGRESS_MODE`: **lax**: Egress mode toggles between strictness of outgoing requests:
- `lax` non-public targets (private, loopback, link-local, CGNAT and special-use ranges) to be allowed, it allows all public ones
- `strict` requires an explicit allow of all addresses
- `ALLOWED_HOST_LIST`: **_empty_**: Webhook and oauth2 clients can only call allowed hosts for security reasons. Comma separated list, eg: `192.168.1.0/24:3000`, `[2001:db8::/32]:9090`, `*.mydomain.com:[80|443]`
- 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), RFC 4193 (FC00::/7) and RFC 6598 CGNAT (100.64.0.0/10). Also called LAN/Intranet.
- CIDR list: `1.2.3.0/8`, `2001:db8::/32`, and with a port `[2001:db8::/32]:9090` (IPv6 addresses and CIDRs need brackets when a port is given)
- Host matching: `example.com` matches the host and any subdomain, dot-anchored so `notexample.com` never matches. `*.example.com` and `.example.com` match only subdomains, the apex itself is excluded. IDN names must be given as punycode.
- All addresses can have ports specified. Accepted port specs:
- a single port: `192.168.1.0/24:3000`
- a range, both bounds inclusive: `*.mydomain.com:3000-3010`
- a bracketed set of ports and ranges, `|` separated: `*.mydomain.com:[80|443|3000-3010]`
- all ports: `*.mydomain.com:*`
- A portless entry covers all ports in `lax` mode, only 80 and 443 in `strict` mode
- Port specs apply only where the list is consulted: in `lax` mode that is non-public targets alone, public targets are allowed on every port whatever the list says. In `strict` mode every target is checked, so ports restrict public hosts too.
- Non-public targets need an IP or built-in entry, a host name entry alone never covers them.
- Reserved addresses (the IPv4-embedding NAT64, Teredo and 6to4 ranges, this-network, multicast and broadcast) are denied whatever the list says. To reach them configure an HTTP proxy
- This list is enforced on direct connections only. When an HTTP proxy is configured, restricting the proxied target is the proxy server's responsibility.
## Audit (`audit`)
- `RECORD_OUTPUT`: **disabled**: Where security-relevant events are recorded. `disabled` records nothing. `database` writes events to the `audit_event` table and shows them in the admin, organization, repository and user settings. Invalid values fall back to `disabled`. See [Audit Logging](audit-logging.md).
- `RETENTION_DAYS`: **30**: Days to keep recorded events. `0` keeps them forever. Pruning is done by `cron.delete_old_audit_events`. That task is only registered while `RECORD_OUTPUT` records events and `RETENTION_DAYS` is greater than `0`.
## Camo (`camo`)
@@ -639,8 +680,8 @@ And the following unique queues:
## OpenID (`openid`)
- `ENABLE_OPENID_SIGNIN`: **true**: Allow authentication in via OpenID.
- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**: Allow registering via OpenID.
- `ENABLE_OPENID_SIGNIN`: **false**: Allow authentication in via OpenID.
- `ENABLE_OPENID_SIGNUP`: **false**: 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
@@ -675,7 +716,7 @@ And the following unique queues:
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
- `DISABLE_REGISTRATION`: **true**: 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.
@@ -699,8 +740,8 @@ And the following unique queues:
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_AUTHENTICATION`: **false**: Enable reverse proxy authentication for the web interface, Git over HTTP, Git LFS and the package registry. Gitea must only be reachable through the proxy, see [Reverse Proxy](authentication.md#reverse-proxy).
- `ENABLE_REVERSE_PROXY_AUTHENTICATION_API`: **false**: Enable reverse proxy authentication for the REST API under `/api/v1`.
- `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
@@ -734,7 +775,7 @@ And the following unique queues:
- `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_REGISTRATION_BUTTON`: **false**: Show Registration button, defaults to true only if both DISABLE_REGISTRATION and ALLOW_ONLY_EXTERNAL_REGISTRATION are false
- `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
@@ -744,8 +785,7 @@ And the following unique queues:
- `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.
- `NO_REPLY_ADDRESS`: **_empty_**: Value for the domain part of the user's email address in the git log if user has set KeepEmailPrivate to true. The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS. Default value is "noreply." + the domain part of ROOT_URL
- `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
@@ -776,19 +816,13 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
- `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_URL`: **_empty_**: Proxy server URL, support http://, https://, socks5://, 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.
When a proxy is configured, Gitea does not enforce `[security]` `ALLOWED_HOST_LIST` on the proxied target, the proxy server is expected to restrict it.
## Mailer (`mailer`)
:::warning
@@ -863,27 +897,27 @@ In-Reply-To =
## 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.
- `ADAPTER`: **memory**: Either `memory`, `redis`, `memcache`, or `twoqueue`.
- `INTERVAL`: **60**: For `memory` and `twoqueue`, GC interval in seconds.
- `HOST`: **_empty_**: For `redis` and `memcache`, connection host address. For `twoqueue` sets configuration for the queue. If left empty while `ADAPTER` is `redis`, it falls back to [redis/CONN_STR](#redis-redis) when that is set.
- Redis: `redis://:[email protected]: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://:[email protected]: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`
- Memcache: `127.0.0.1:11211`
- 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.
- `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.
- `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`_.
- `PROVIDER`: **file**: Either "memory", "file", "redis" or "db", default is "file". "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`_. For the `redis` provider, if left empty it falls back to [redis/CONN_STR](#redis-redis) when that is set.
- `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.
- `COOKIE_NAME`: **gitea\_session**: Session cookie name
- `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
@@ -891,8 +925,7 @@ In-Reply-To =
## Picture (`picture`)
- `GRAVATAR_SOURCE`: **gravatar**: Can be `gravatar`, `duoshuo` or anything like
`http://cn.gravatar.com/avatar/`.
- `GRAVATAR_SOURCE`: **gravatar**: Can be `gravatar`, `libravatar` or any other Gravatar-compatible source, like `https://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.
@@ -911,7 +944,7 @@ In-Reply-To =
- 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)
- `REPOSITORY_AVATAR_FALLBACK_IMAGE`: **_empty_**: Image used as default repository avatar (if `REPOSITORY_AVATAR_FALLBACK` is set to image and none was uploaded). The value is used as-is, without prepending the sub-path of `ROOT_URL`. Empty uses Gitea's builtin repository avatar.
## Project (`project`)
@@ -920,12 +953,15 @@ 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`)
## Issue, pull-request and release 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.
ALLOWED_TYPES/MAX_SIZE/MAX_FILES in this section only affect issue and pull-request attachments, not release attachments.
Release attachment has its own config options in `[repository.release]` section.
- `ENABLED`: **true**: Whether issue, pull-request and release 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 issue/pull-request attachment file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
- `MAX_SIZE`: **100**: Max size of each issue/pull-request attachment file in MB.
- `MAX_FILES`: **5**: Maximum number of issue/pull-request attachments that can be uploaded at once.
- `STORAGE_TYPE`: **local**: Storage type for attachments, it could be `<blank>`, `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.
@@ -934,7 +970,7 @@ Default templates for project board view:
- `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.
For `STORAGE_TYPE = minio`, the configurations can be found at [Storage Minio](#minio-storage-configuration-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`
@@ -1027,30 +1063,31 @@ Default templates for project board view:
- `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
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `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.
- `ENABLED`: **true**: Enable running repository health check 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
- `RUN_AT_START`: **false**: Run repository health check task when Gitea starts.
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `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
- `ENABLED`: **true**: Enable running repository statistics check task periodically.
- `RUN_AT_START`: **true**: Run repository statistics check task when Gitea starts.
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
#### 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).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `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.
@@ -1070,7 +1107,7 @@ Update migrated repositories' issues and comments' posterid, it will always atte
- `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
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `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`)
@@ -1079,7 +1116,7 @@ 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
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `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.
@@ -1087,8 +1124,16 @@ Synchronize external user data (only LDAP user synchronization is supported)
- `ENABLED`: **true**: Enable cleanup expired actions assets job.
- `RUN_AT_START`: **true**: Run job at start time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@midnight** : Cron syntax for the job.
#### Cron - Delete Old Action Runs (`cron.cleanup_action_runs`)
- `ENABLED`: **true**: Enable the job deleting action runs older than `RUN_RETENTION_DAYS`. Deletes nothing while that is 0.
- `RUN_AT_START`: **false**: Run job at start time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@midnight**: Cron syntax for the job.
#### Cron - Cleanup Deleted Branches (`cron.deleted_branches_cleanup`)
- `ENABLED`: **true**: Enable deleted branches cleanup.
@@ -1097,6 +1142,13 @@ Synchronize external user data (only LDAP user synchronization is supported)
- `SCHEDULE`: **@midnight**: Cron syntax for scheduling deleted branches cleanup.
- `OLDER_THAN`: **24h**: Branches deleted OLDER_THAN ago will be cleaned up.
#### Cron - Synchronize repository licenses (`cron.sync_repo_licenses`)
- `ENABLED`: **false**: Enable deleted branches cleanup.
- `RUN_AT_START`: **false**: Run job at start time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to log a success message.
- `SCHEDULE`: **@annually*: Cron syntax for scheduling synchronization of repository licenses
### Extended cron tasks
#### Cron - Delete all repository archives (`cron.delete_repo_archives`)
@@ -1120,7 +1172,14 @@ Synchronize external user data (only LDAP user synchronization is supported)
- `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`.
- `SCHEDULE`: **@every 72h**: Cron syntax for scheduling synchronization of gitea ssh keys, e.g. `@every 1h`.
#### Cron - Update the '.ssh/authorized_principals' file (`cron.resync_all_sshprincipals`)
- `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 update of authorized_principals, e.g. `@every 1h`.
#### Cron - Resynchronize pre-receive, update and post-receive hooks of all repositories (`cron.resync_all_hooks`)
@@ -1158,11 +1217,21 @@ Synchronize external user data (only LDAP user synchronization is supported)
- `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 - Delete old audit events (`cron.delete_old_audit_events`)
Deletes audit events older than the retention period. The task is only registered when `[audit].RECORD_OUTPUT` records events and `[audit].RETENTION_DAYS` is greater than `0`. See [Audit Logging](audit-logging.md).
- `ENABLED`: **true**: Enable service.
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@every 24h**: Cron syntax to set how often to check.
- `OLDER_THAN`: **720h**: any audit event older than this expression will be deleted from the database. Defaults to `[audit].RETENTION_DAYS`.
#### Cron - Check for new Gitea versions (`cron.update_checker`)
- `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.
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on 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
@@ -1170,7 +1239,7 @@ Synchronize external user data (only LDAP user synchronization is supported)
- `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.
- `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 system notice older than this expression will be deleted from database.
@@ -1178,12 +1247,50 @@ Synchronize external user data (only LDAP user synchronization is supported)
- `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 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.)
### Actions cron tasks
#### Cron - Rebuild issue index (`cron.rebuild_issue_indexer`)
- `ENABLED`: **true**: Enable service.
- `RUN_AT_START`: **true**: Run tasks at start up time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@annually**: Cron syntax to set how often to rebuild
#### Cron - Stop running tasks which haven't been updated for a long time (`cron.stop_zombie_tasks`)
- `ENABLED`: **true**: Enable service.
- `RUN_AT_START`: **true**: Run tasks at start up time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@every 5m**: Cron syntax to set how often tasks to run the check
#### Cron - Stop running tasks which have running status and continuous updates but don't end for a long time (`cron.stop_endless_tasks`)
- `ENABLED`: **true**: Enable service.
- `RUN_AT_START`: **true**: Run tasks at start up time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@every 30m**: Cron syntax to set how often to run the check.
#### Cron - Cancel jobs which haven't been picked up for a long time (`cron.cancel_abandoned_jobs`)
- `ENABLED`: **true**: Enable service.
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@every 6h**: Cron syntax to set how often to run the check.
#### Cron - Start cron based actions (`cron.start_schedule_tasks`)
- `ENABLED`: **true**: Enable service.
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
- `SCHEDULE`: **@every 1m**: Cron syntax to set how often to schedule tasks
## Git (`git`)
- `PATH`: **""**: The path of Git executable. If empty, Gitea searches through the PATH environment.
@@ -1214,12 +1321,13 @@ Synchronize external user data (only LDAP user synchronization is supported)
### 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`.
The key/value pairs in this section will be used as git config. The format is `some.configKey = value`.
These options are written into the gitconfig file under `[git] HOME_PATH` when Gitea starts, and are applied **after** Gitea's built-in defaults — so values set here take precedence over the defaults listed below.
**Note:** This section only does "set" config; a removed config key from this section won't be removed from git config automatically. Some config options might affect the behavior of git and cause Gitea's git operations to fail — make sure you know what you are doing before making changes.
- `diff.algorithm`: **histogram**
- `core.logAllRefUpdates`: **true**
- `gc.reflogExpire`: **90**
## Metrics (`metrics`)
@@ -1247,7 +1355,10 @@ This section only does "set" config, a removed config key from this section won'
- `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.
- `DEFAULT_APPLICATIONS`: **git-credential-oauth, git-credential-manager, tea, gitea-app**: Pre-register OAuth applications for some services on startup. See the [OAuth2 documentation](/development/oauth2-provider.md) for the list of available options.
- `CUSTOM_SCHEMES`: **_empty_**: By default, OAuth2 applications can only use "http" and "https" as their redirect URI schemes.
If you need to use other schemes (e.g. for desktop applications), you can specify them here as a comma-separated list.
For example: set "my-scheme, com.example.app" to support "my-scheme://..." and "com.example.app://..." redirect URIs.
## i18n (`i18n`)
@@ -1328,11 +1439,13 @@ in this mapping or the filetype using heuristics.
- `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.
- `EGRESS_MODE`: **lax**: Mode toggles between strictness of scanning outgoing requests, same format as `EGRESS_MODE` in [`security`](#security-security).
- `ALLOWED_HOST_LIST`: **_empty_**: Hosts migrations and mirrors may call, same format as `ALLOWED_HOST_LIST` in [`security`](#security-security). Private, loopback and link-local addresses need a builtin or CIDR entry. When unset, the deprecated `ALLOWED_DOMAINS` entries apply on every port with `strict` as the default mode, and the deprecated `ALLOW_LOCALNETWORKS` adds `private, loopback`.
- `BLOCKED_HOST_LIST`: **_empty_**: Hosts migrations and mirrors may never call, portless entries cover all ports.
- `SKIP_TLS_VERIFY`: **false**: Allow skip tls verify
These lists are enforced on direct connections only. When a proxy is configured (`[proxy]`, `[git.config]` `http.proxy` or the environment), restricting the proxied target is the proxy server's responsibility.
## Federation (`federation`)
- `ENABLED`: **false**: Enable/Disable federation capabilities
@@ -1375,6 +1488,7 @@ in this mapping or the filetype using heuristics.
- `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`)
- `LIMIT_SIZE_TERRAFORM_STATE``: **-1**: Maximum size of a Terraform state upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
## Mirror (`mirror`)
@@ -1398,7 +1512,7 @@ is `data/lfs` and the default of `MINIO_BASE_PATH` is `lfs/`.
- `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.
For `STORAGE_TYPE = minio`, the configurations can be found at [Storage Minio](#minio-storage-configuration-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`
@@ -1549,7 +1663,7 @@ is `data/repo-archive` and the default of `MINIO_BASE_PATH` is `repo-archive/`.
- `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.
For `STORAGE_TYPE = minio`, the configurations can be found at [Storage Minio](#minio-storage-configuration-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`
@@ -1566,14 +1680,16 @@ is `data/repo-archive` and the default of `MINIO_BASE_PATH` is `repo-archive/`.
## 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_URL`: **_empty_**: Proxy server URL, support http://, https://, socks5://, 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.
When a proxy is configured, Gitea does not enforce the egress lists (`[security]`, `[migrations]`) on the proxied target, the proxy server is expected to restrict it.
i.e.
```ini
PROXY_ENABLED = true
PROXY_URL = socks://127.0.0.1:1080
PROXY_URL = socks5://127.0.0.1:1080
PROXY_HOSTS = *.github.com
```
@@ -1583,30 +1699,28 @@ PROXY_HOSTS = *.github.com
- `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_RETENTION_DAYS`: **365**: Days to keep logs. Old logs will be deleted after this period. 0 means keep forever.
- `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.
- `ARTIFACT_RETENTION_DAYS`: **90**: Days to keep artifacts. Old artifacts will be deleted after this period. 0 means keep forever.
Changes only apply to newly uploaded artifacts, existing ones keep the expiry stored when they were uploaded.
Workflows can request a shorter retention period, down to 1 day.
- `ARTIFACT_PREVIEW_MAX_SIZE`: **10485760**: Maximum total artifact size in bytes that can be browsed or previewed in the web UI. Set to `0` to disable artifact previews or `-1` for no limit. Individual files are also limited by [`MAX_DISPLAY_FILE_SIZE`](#ui-ui).
- `RUN_RETENTION_DAYS`: **400**: Days to keep completed runs. Old runs and everything under them will be deleted after this period. 0 means keep forever.
- `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
- `WORKFLOW_DIRS`: **.gitea/workflows,.github/workflows**: Comma-separated list of workflow directories, the first one to exist in a repo is used to find Actions workflow files.
- `SCOPED_WORKFLOW_DIRS`: **.gitea/scoped_workflows**: Comma-separated list of directories holding [scoped workflows](usage/actions/scoped-workflows.md) (workflows defined in a central source repository that run on other repositories). Must not overlap with `WORKFLOW_DIRS`. Leave empty so no directory is scanned for scoped workflows; none are found or run.
- `MAX_RERUN_ATTEMPTS`: **50**: Maximum number of attempts a single workflow run can have (initial run + reruns). Defaults value is 50. Set any positive value that fits your workflow needs.
`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`.
`DEFAULT_ACTIONS_URL` sets where runners download actions without a host.
With `github`, `uses: actions/checkout@v4` resolves to `https://github.com/actions/checkout@v4`, with `self` to `<ROOT_URL>/actions/checkout@v4`.
`self` requires mirroring every action you use to your instance, so prefer naming the host per action instead: `uses: self:owner/repo@ref` for your instance, or a full URL like `uses: https://gitea.com/actions/checkout@v4` for any other host.
## Other (`other`)
+15 -12
View File
@@ -85,6 +85,8 @@ To obtain any embedded file (including templates), the [`gitea embedded` tool](.
Be aware that any statement contained inside `{{` and `}}` are Gitea's template syntax and
shouldn't be touched without fully understanding these components.
Gitea pages are protected by Content-Security-Policy, use `<script nonce="{{ctx.CspScriptNonce}}">...</script>` for script tags.
### 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`.
@@ -136,10 +138,10 @@ The data is encoded and sent to the PlantUML server which generates the picture.
demo server at http://www.plantuml.com/plantuml, but if you (or your users) have sensitive data you
can set up your own [PlantUML server](https://plantuml.com/server) instead. To set up PlantUML rendering,
copy JavaScript files from https://gitea.com/davidsvantesson/plantuml-code-highlight and put them in your
`$GITEA_CUSTOM/public/assets/` folder. Then add the following to `custom/footer.tmpl`:
`$GITEA_CUSTOM/public/assets/` folder. Then add the following to `$GITEA_CUSTOM/templates/custom/footer.tmpl`:
```html
<script>
<script nonce="{{ctx.CspScriptNonce}}">
$(async () => {
if (!$('.language-plantuml').length) return;
await Promise.all([
@@ -185,18 +187,18 @@ nano $GITEA_CUSTOM/templates/custom/footer.tmpl
```
```html
<script>
<script nonce="{{ctx.CspScriptNonce}}">
function onPageChange() {
// Supported 3D file types
const fileTypes = ['3dm', '3ds', '3mf', 'amf', 'bim', 'brep', 'dae', 'fbx', 'fcstd', 'glb', 'gltf', 'ifc', 'igs', 'iges', 'stp', 'step', 'stl', 'obj', 'off', 'ply', 'wrl'];
// Select matching link
const links = Array.from(document.querySelectorAll('a.ui.mini.basic.button'));
const link3D = links.find(link => {
const href = link.href.toLowerCase();
return href.includes('/raw/') && fileTypes.some(ext => href.endsWith(`.${ext}`));
});
if (link3D) {
const existingScript = document.querySelector('script[src="/assets/o3dv/o3dv.min.js"]');
@@ -226,11 +228,11 @@ nano $GITEA_CUSTOM/templates/custom/footer.tmpl
newView3D.style.flexGrow = '1';
newView3D.style.minHeight = '0';
newView3D.style.width = '100%';
const header = document.querySelector('header');
const headerHeight = header ? header.offsetHeight : 0;
newView3D.style.height = `calc(100vh - ${headerHeight}px)`;
newView3D.style.height = `calc(100vh - ${headerHeight}px)`;
// Append the new container inside fileView
fileView.appendChild(newView3D);
@@ -273,7 +275,7 @@ nano $GITEA_CUSTOM/templates/custom/footer.tmpl
};
// Run when the page is fully loaded
document.addEventListener('DOMContentLoaded', onPageChange);
document.addEventListener('DOMContentLoaded', onPageChange);
const targetSelector = 'a.ui.mini.basic.button[href*="/raw/"]';
let lastHref = null;
@@ -289,7 +291,7 @@ nano $GITEA_CUSTOM/templates/custom/footer.tmpl
const fileName = currentHref.split('/').pop();
console.log('New Raw file link detected after delay:', fileName);
onPageChange();
}
};
@@ -394,15 +396,16 @@ Starting with Gitea 1.20, you can customize the git configuration via the `git.c
### Enabling signed git pushes
To enable signed git pushes, set these two options:
[Signed pushes](https://git-scm.com/docs/git-push#Documentation/git-push.txt---signedtruefalseif-asked) allow clients to cryptographically sign the push operation itself (not just individual commits). To enable signed pushes, add the following to `app.ini`:
```ini
[git.config]
receive.advertisePushOptions = true
receive.certNonceSeed = <randomstring>
```
`certNonceSeed` should be set to a random string and be kept secret.
`certNonceSeed` should be set to a random string and be kept secret. It is used to generate anti-replay nonces. Gitea already sets `receive.advertisePushOptions = true` by default, so no additional configuration is needed. Note that Gitea does not read `/etc/gitconfig`, so this option must be set via `app.ini` as shown above.
On the client side, pushes can be signed via `git push --signed` or enabled permanently using `git config --global push.gpgSign if-asked`.
### Labels
+15
View File
@@ -86,6 +86,21 @@ PROTOCOL = smtps
Note that you'll need to create and use an [App password](https://support.google.com/accounts/answer/185833?hl=en) by enabling 2FA on your Google
account. You won't be able to use your Google account password directly.
An app password is the only option: Google
[turned off access for apps that sign in with a password alone](https://workspaceupdates.googleblog.com/2023/09/winding-down-google-sync-and-less-secure-apps-support.html)
in 2024 and asks applications to use OAuth instead, which Gitea's mailer does
not implement — it authenticates with `CRAM-MD5`, `PLAIN` or `LOGIN`.
Two things to keep in mind:
- app passwords require 2-step verification on the account, and a Google
Workspace administrator can switch them off for the whole domain. If they are
not available, send through the
[Workspace SMTP relay service](https://support.google.com/a/answer/2956491)
or through another mail provider.
- port `587` works as well, with `SMTP_PORT = 587` and
`PROTOCOL = smtp+starttls`.
### ProtonMail
This feature is currently only available for select Proton for Business customers and those with Visionary and Family plans with custom domain addresses. See [ProtonMail's SMTP documentation](https://proton.me/support/smtp-submission) for more information. This limitation can be circumvented by using the ProtonMail Bridge application.
+21
View File
@@ -41,3 +41,24 @@ client that causes SSH transfers to hang: https://github.com/git-lfs/git-lfs/pul
This can be worked around on all the client machines by setting the git config:
`git config --global lfs.ssh.automultiplex false`
:::
# Changing LFS files through the API
The [contents API](https://docs.gitea.com/api/operations/repo-change-files/)
works on LFS tracked files as well: send the file content as usual and Gitea
stores it as an LFS object and commits a pointer file, as long as the path is
matched by a `filter=lfs` rule in `.gitattributes`.
What is easy to get wrong is the `sha` of the file being changed, which
`PUT`/`DELETE /repos/{owner}/{repo}/contents/{filepath}` and
`POST /repos/{owner}/{repo}/contents` require for an existing file. Gitea
compares it with the ID of the blob the commit has at that path, and for an LFS
tracked file that blob is the **pointer file**, not the content:
- use the `sha` returned by
[`GET /repos/{owner}/{repo}/contents/{filepath}`](https://docs.gitea.com/api/operations/repo-get-contents/)
- do not use `lfs_oid` from the same response, which identifies the LFS object,
and do not use a checksum of the file itself
Sending anything else fails with `sha does not match`, even though the request
looks correct.
+22
View File
@@ -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).
+2
View File
@@ -16,6 +16,8 @@ The logging configuration of Gitea mainly consists of 3 types of components:
There is a fully functional log output by default, so it is not necessary to define one.
Security-relevant events (repository transfers, token changes, impersonation, and similar) are recorded separately. See [Audit Logging](audit-logging.md).
## Collecting Logs for Help
To collect logs for help and issue report, see [Support Options](help/support.md).
+1 -1
View File
@@ -32,7 +32,7 @@ Please bear in mind that indexing the contents can consume a lot of system resou
### Choosing the files for indexing by size
The `MAX_FILE_SIZE` option will make the indexer skip all files larger than the specified value.
The `MAX_FILE_SIZE` option will make the indexer skip all files larger than the specified value in bytes.
### Choosing the files for indexing by path
+22 -9
View File
@@ -13,8 +13,9 @@ aliases:
1. Set `[server] ROOT_URL = https://git.example.com/` in your `app.ini` file.
2. Make the reverse-proxy pass `https://git.example.com/foo` to `http://gitea:3000/foo`.
3. Make sure the reverse-proxy does not decode the URI. The request `https://git.example.com/a%2Fb` should be passed as `http://gitea:3000/a%2Fb`.
4. Make sure `Host` and `X-Fowarded-Proto` headers are correctly passed to Gitea to make Gitea see the real URL being visited.
5. Make sure your webserver has a certificate, including all intermediate and RootCA certificates, for `git clone` and `git pull` to work.
4. Make sure `Host` and `X-Forwarded-Proto` headers are correctly passed to Gitea to make Gitea see the real URL being visited.
5. Make sure your webserver has a certificate, including all intermediate and RootCA certificates, for `git clone` and `git pull` to work.
6. Gitea uses a WebSocket connection at `/-/ws` for real-time updates like the notification counter. Make sure the reverse-proxy talks HTTP/1.1 and forwards the `Upgrade` and `Connection` headers, see the examples below. Without it, Gitea falls back to periodic polling.
### Use a sub-path
@@ -41,6 +42,7 @@ server {
location / {
client_max_body_size 512M;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
@@ -67,6 +69,7 @@ server {
rewrite ^ $request_uri;
rewrite ^/(gitea($|/))?(.*) /$3 break;
proxy_pass http://127.0.0.1:3000$uri;
proxy_http_version 1.1;
# other common HTTP headers, see the "Nginx" config section above
proxy_set_header Connection $http_connection;
@@ -113,6 +116,7 @@ server {
}
location / {
# other directives, see the "Nginx" config section above
proxy_pass http://localhost:3000;
}
}
@@ -129,6 +133,7 @@ server {
server_name git.example.com;
location / {
# other directives, see the "Nginx" config section above
proxy_pass http://localhost:3000;
}
}
@@ -156,14 +161,14 @@ If you are using Nginx Proxy Manager to serve your Gitea instance it differs sli
It is [adding some directives](https://github.com/NginxProxyManager/nginx-proxy-manager/blob/master/docker/rootfs/etc/nginx/conf.d/include/proxy.conf) for a custom location by default, so you have to skip these from the above mentioned Nginx config. Otherwise Nginx will produce `400 bad request` error due to duplicated directives (`proxy_set_header Host $host` is the particularly problematic one).
So while creating the `/` Custom location, just add the following lines to it's configuration:
So while creating the `/` Custom location, just add the following line to it's configuration:
```nginx
client_max_body_size 512M;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
```
Enable `Websockets Support` on the proxy host, Nginx Proxy Manager then adds the WebSocket directives itself. Adding `proxy_http_version` on top of that makes Nginx refuse to start.
## Apache HTTPD
If you want Apache HTTPD to serve your Gitea instance, you can add the following to your Apache HTTPD configuration (usually located at `/etc/apache2/httpd.conf` in Ubuntu):
@@ -174,13 +179,15 @@ If you want Apache HTTPD to serve your Gitea instance, you can add the following
ProxyPreserveHost On
ProxyRequests off
AllowEncodedSlashes NoDecode
ProxyPass / http://localhost:3000/ nocanon
ProxyPass / http://localhost:3000/ nocanon upgrade=websocket
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
```
:::note
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`.
`upgrade=websocket` requires Apache HTTPD 2.4.48 or later. On older versions you **MUST** remove it, otherwise Apache HTTPD will not start.
:::
If you wish to use Let's Encrypt with webroot validation, add the line `ProxyPass /.well-known !` before `ProxyPass` to disable proxying these requests to Gitea.
@@ -198,7 +205,7 @@ In case you already have a site, and you want Gitea to share the domain name, yo
</Proxy>
AllowEncodedSlashes NoDecode
# Note: no trailing slash after either /git or port
ProxyPass /git http://localhost:3000 nocanon
ProxyPass /git http://localhost:3000 nocanon upgrade=websocket
ProxyPreserveHost On
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
@@ -207,7 +214,7 @@ In case you already have a site, and you want Gitea to share the domain name, yo
Then you **MUST** set something like `[server] ROOT_URL = http://git.example.com/git/` correctly in your configuration.
:::note
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`.
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`. `upgrade=websocket` requires Apache HTTPD 2.4.48 or later, remove it on older versions.
:::
## Apache HTTPD and serve static resources directly
@@ -248,12 +255,16 @@ Set `[server] STATIC_URL_PREFIX = /_/static` in your configuration.
AllowEncodedSlashes NoDecode
# Note: no trailing slash after either /git or port
ProxyPass / http://localhost:3000/ nocanon
ProxyPass / http://localhost:3000/ nocanon upgrade=websocket
ProxyPreserveHost On
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
```
:::note
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`. `upgrade=websocket` requires Apache HTTPD 2.4.48 or later, remove it on older versions.
:::
## Caddy
If you want Caddy to serve your Gitea instance, you can add the following server block to your Caddyfile:
@@ -288,11 +299,13 @@ If you wish to run Gitea with IIS. You will need to setup IIS with URL Rewrite a
- Install Application Request Routing (ARR for short) either by using the Microsoft Web Platform Installer 5.1 (WebPI) or downloading the extension from [IIS.net](https://www.iis.net/downloads/microsoft/application-request-routing)
- Once the module is installed in IIS, you will see a new Icon in the IIS Administration Console called URL Rewrite.
- Install the `WebSocket Protocol` Windows feature, otherwise ARR cannot proxy Gitea's WebSocket endpoint.
- Open the IIS Manager Console and click on the `Gitea Proxy` Website from the tree view on the left. Select and double click the URL Rewrite Icon from the middle pane to load the URL Rewrite interface.
- Choose the `Add Rule` action from the right pane of the management console and select the `Reverse Proxy Rule` from the `Inbound and Outbound Rules` category.
- 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
+1 -1
View File
@@ -33,7 +33,7 @@ then the config file (app.ini) should exists in the "custom/conf" directory of y
Some package vendors might use "/etc/gitea" to store the config file, while some others don't.
You could manually find the config file (app.ini) by checking Gitea's startup logs
or reading the Gitea Web's Site Administrator -> Confugiraton Summary.
or reading the Gitea Web's Site Administrator -> Configuration Summary.
If you are using some isolated enviroments like container (docker),
the path you see usually is not what it is in the host's filesystem.
+1 -1
View File
@@ -43,7 +43,7 @@ You can try it out using [the online demo](https://demo.gitea.com).
- **Security**
Gitea places a strong emphasis on security, offering features such as user permission management, access control lists, and more to ensure the security of code and data.
Gitea places a strong emphasis on security, offering features such as user permission management, access control lists, [audit logging](administration/audit-logging.md), and more to ensure the security of code and data.
- **Code Review**
+1
View File
@@ -34,6 +34,7 @@ _Symbols used in table:_
| Telemetry | **✘** | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
| Third-party render tool support | ✓ | ✘ | ✘ | ✘ | ✓ | ✘ | ✘ |
| WebAuthn (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✓ |
| Audit log | ✓ | ✓ | ⁄ | ✓ | ✓ | ? | ? |
| Extensive API | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Built-in Package/Container Registry | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ |
| Sync commits to an external repo (push mirror) | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ | ✓ |
+27 -4
View File
@@ -40,7 +40,24 @@ chmod +x gitea
Note that the above command will download Gitea @version@ for 64-bit Linux.
## Verify GPG signature
## Verify signature
### Sigstore
Starting with v1.27 Gitea signs all binaries using [sigstore](https://sigstore.dev/) to prevent against unwanted modification of binaries.
To validate the binary, download the bundle file which ends in `sigstore.json` for the binary you downloaded and use the [cosign](https://docs.sigstore.dev/cosign/system_config/installation/) command line tool.
```sh
cosign verify-blob gitea-@version@-linux-amd64 --bundle gitea-@version@-linux-amd64.sigstore.json --certificate-oidc-issuer=https://token.actions.githubusercontent.com --certificate-identity-regexp="https://github.com/go-gitea/gitea/.github/workflows/release-.*"
```
If the command outputs `Verified OK`, binary was not modified.
:::note
The above command will match any release workflow. You may choose to restrict the identity further by requiring a specific branch or workflow to be matched. For example this url will match only nightly builds made on main branch: `https://github.com/go-gitea/gitea/.github/workflows/release-nightly.yml@refs/heads/main`
:::
### GPG
Gitea signs all binaries with a [GPG key](https://keys.openpgp.org/search?q=teabot%40gitea.io) to prevent against unwanted modification of binaries.
To validate the binary, download the signature file which ends in `.asc` for the binary you downloaded and use the GPG command line tool.
@@ -53,6 +70,7 @@ gpg --verify gitea-@[email protected] gitea-@version@-linux-amd64
Look for the text `Good signature from "Teabot <[email protected]>"` to assert a good binary,
despite warnings like `This key is not certified with a trusted signature!`.
## Recommended server configuration
:::note
@@ -153,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)
@@ -214,9 +239,7 @@ As of v1.8, there is a problem with the arm7 version of Gitea, and it doesn't ru
It is recommended to switch to the arm6 version, which has been tested and shown to work on Raspberry Pis and similar devices.
<!---
please remove after fixing the arm7 bug
--->
{/* please remove after fixing the arm7 bug */}
### Git error after updating to a new version of Gitea
If during the update, the binary file name has been changed to a new version of Gitea,
+10 -2
View File
@@ -6,6 +6,8 @@ aliases:
- /en-us/install-from-source
---
:::warning This document is outdated, pleaes refer to [build-source.md](https://github.com/go-gitea/gitea/tree/main/docs/build-source.md):::
# Installation from source
You should [install go](https://go.dev/doc/install) and set up your go
@@ -21,7 +23,7 @@ version is @minNodeVersion@ and the latest LTS version is recommended.
:::note
Go version @minGoVersion@ or higher is required. However, it is recommended to
obtain the same version as our continuous integration, see the advice given in
[Hacking on Gitea](development/hacking-on-gitea.md)
[Hacking on Gitea](https://github.com/go-gitea/gitea/blob/main/docs/build-setup.md)
:::
## Download
@@ -71,7 +73,7 @@ To build from source, the following programs must be present on the system:
- `go` @minGoVersion@ or higher, see [here](https://go.dev/dl/)
- `node` @minNodeVersion@ or higher with `npm`, see [here](https://nodejs.org/en/download/)
- `make`, see [here](development/hacking-on-gitea.md#installing-make)
- `make`, see [here](https://github.com/go-gitea/gitea/blob/main/docs/build-setup.md#make)
Various [make tasks](https://github.com/go-gitea/gitea/blob/main/Makefile)
are provided to keep the build process as simple as possible.
@@ -125,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
-43
View File
@@ -1,43 +0,0 @@
---
date: "2016-12-01T16:00:00+02:00"
slug: "install-on-cloud-provider"
sidebar_position: 90
aliases:
- /en-us/install-on-cloud-provider
---
# Installation on Cloud Provider
## Cloudron
Gitea is available as a 1-click install on [Cloudron](https://cloudron.io).
Cloudron makes it easy to run apps like Gitea on your server and keep them up-to-date and secure.
[![Install](/cloudron.svg)](https://cloudron.io/button.html?app=io.gitea.cloudronapp)
The Gitea package is maintained [here](https://git.cloudron.io/cloudron/gitea-app).
There is a [demo instance](https://my.demo.cloudron.io) (username: cloudron password: cloudron) where
you can experiment with running Gitea.
## Linode
[Linode](https://www.linode.com/) has Gitea as an app in their marketplace.
To deploy Gitea to Linode, have a look at the [Linode Marketplace](https://www.linode.com/marketplace/apps/linode/gitea/).
## alwaysdata
[alwaysdata](https://www.alwaysdata.com/) has Gitea as an app in their marketplace.
To deploy Gitea to alwaysdata, have a look at the [alwaysdata Marketplace](https://www.alwaysdata.com/en/marketplace/gitea/).
## Exoscale
[Exoscale](https://www.exoscale.com/) provides Gitea managed by [Glasskube](https://glasskube.eu/) in their marketplace.
Exoscale is a European cloud service provider.
The package is maintained and update via the open source [Glasskube Kubernetes Operator](https://github.com/glasskube/operator).
To deploy Gitea to Exoscale, have a look at the [Exoscale Marketplace](https://www.exoscale.com/marketplace/listing/glasskube-gitea/).
@@ -12,7 +12,7 @@ You can run Gitea as a Linux service, using either systemd or supervisor. The st
## Using systemd
Copy the sample [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/systemd/gitea.service) to `/etc/systemd/system/gitea.service`, then edit the file with your favorite editor.
Copy the sample [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/service/systemd/gitea.service) to `/etc/systemd/system/gitea.service`, then edit the file with your favorite editor.
Uncomment any service that needs to be enabled on this host, such as MySQL.
@@ -48,7 +48,7 @@ mkdir /home/git/gitea/log/supervisor
```
Append the configuration from the sample
[supervisord config](https://github.com/go-gitea/gitea/blob/main/contrib/supervisor/gitea) to `/etc/supervisor/supervisord.conf`.
[supervisord config](https://github.com/go-gitea/gitea/blob/main/contrib/service/supervisor/gitea) to `/etc/supervisor/supervisord.conf`.
Using your favorite editor, change the user (`git`) and home
(`/home/git`) settings to match the deployment environment. Change the PORT
+109
View File
@@ -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.
+17 -211
View File
@@ -8,15 +8,19 @@ aliases:
# Installation with Docker (rootless)
Gitea provides automatically updated Docker images within its Docker Hub organization. It is
possible to always use the latest stable tag or to use another service that handles updating
Docker images.
## Relation to rootful image
The rootless image uses Gitea internal SSH to provide Git protocol and doesn't support OpenSSH.
* Rootless image doesn't require "root" privilege on the host, while it may have stricter UID/GID requirement.
* Rootless image must use its bulitin SSH server, while the rootful one must its managed standalone OpenSSH server.
* The volume mapping and directory layout is different between them.
This reference setup guides users through the setup based on `docker-compose`, but the installation
of `docker-compose` is out of scope of this documentation. To install `docker-compose` itself, follow
the official [install instructions](https://docs.docker.com/compose/install/).
Except the differences above, the rootless image shares the same mechanism with rootful image,
including: port mapping, custimzation, upgrading, environment variables, etc.
Read more in "[Installation with Docker (rootful)](./with-docker.md)"
ATTENTION: the rootful/rootless images are not compatible with the other.
If you have chosen one, you should always use the same one,
don't switch to the other one by changing the compose file's `image` value.
## Basics
@@ -34,8 +38,6 @@ touch docker-compose.yml
Then paste the following content into a file named `docker-compose.yml`:
```yaml
version: "2"
services:
server:
image: docker.gitea.com/gitea:@dockerVersion@-rootless
@@ -56,115 +58,15 @@ Note that the volume should be owned by the user/group with the UID/GID specifie
sudo chown 1000:1000 config/ data/
```
> If you don't give the volume correct permissions, the container may not start.
> If you don't give the volume correct permissions, the container may present the following errors in the logs:
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:@dockerVersion@-rootless`, but if you'd like to use the latest development version then `:nightly-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.16-nightly-rootless`)
## Custom port
To bind the integrated ssh and the webserver on a different port, adjust
the port section. It's common to just change the host port and keep the ports within
the container like they are.
```diff
version: "2"
services:
server:
image: docker.gitea.com/gitea:@dockerVersion@-rootless
restart: always
volumes:
- ./data:/var/lib/gitea
- ./config:/etc/gitea
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- - "3000:3000"
- - "2222:2222"
+ - "80:3000"
+ - "22:2222"
```sh
server-1 | 2026-03-11T12:57:50.794102045Z mkdir: can't create directory '/var/lib/gitea/git': Permission denied
server-1 | 2026-03-11T12:57:50.796198843Z /var/lib/gitea/git is not writable
server-1 | 2026-03-11T12:57:50.796235667Z docker setup failed
```
## MySQL database
To start Gitea in combination with a MySQL database, apply these changes to the
`docker-compose.yml` file created above.
```diff
version: "2"
services:
server:
image: docker.gitea.com/gitea:@dockerVersion@-rootless
+ environment:
+ - GITEA__database__DB_TYPE=mysql
+ - GITEA__database__HOST=db:3306
+ - GITEA__database__NAME=gitea
+ - GITEA__database__USER=gitea
+ - GITEA__database__PASSWD=gitea
restart: always
volumes:
- ./data:/var/lib/gitea
- ./config:/etc/gitea
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:2222"
+ depends_on:
+ - db
+
+ db:
+ image: docker.io/library/mysql:8
+ restart: always
+ environment:
+ - MYSQL_ROOT_PASSWORD=gitea
+ - MYSQL_USER=gitea
+ - MYSQL_PASSWORD=gitea
+ - MYSQL_DATABASE=gitea
+ volumes:
+ - ./mysql:/var/lib/mysql
```
## PostgreSQL database
To start Gitea in combination with a PostgreSQL database, apply these changes to
the `docker-compose.yml` file created above.
```diff
version: "2"
services:
server:
image: docker.gitea.com/gitea:@dockerVersion@-rootless
environment:
+ - GITEA__database__DB_TYPE=postgres
+ - GITEA__database__HOST=db:5432
+ - GITEA__database__NAME=gitea
+ - GITEA__database__USER=gitea
+ - GITEA__database__PASSWD=gitea
restart: always
volumes:
- ./data:/var/lib/gitea
- ./config:/etc/gitea
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:2222"
+ depends_on:
+ - db
+
+ db:
+ image: docker.io/library/postgres:14
+ restart: always
+ environment:
+ - POSTGRES_USER=gitea
+ - POSTGRES_PASSWORD=gitea
+ - POSTGRES_DB=gitea
+ volumes:
+ - ./postgres:/var/lib/postgresql/data
```
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:@dockerVersion@-rootless`, but if you'd like to use the latest development version then `:main-nightly-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.27-nightly-rootless`)
## Named volumes
@@ -174,8 +76,6 @@ create the required volume. You don't need to worry about permissions with
named volumes; Docker will deal with that automatically.
```diff
version: "2"
+volumes:
+ gitea-data:
+ driver: local
@@ -207,8 +107,6 @@ As an example to clone the host user `git` definition use the command `id -u git
Please make sure that the mounted folders are writable by the user.
```diff
version: "2"
services:
server:
image: docker.gitea.com/gitea:@dockerVersion@-rootless
@@ -223,95 +121,3 @@ services:
- "3000:3000"
- "2222:2222"
```
## Startup
:::note
From July 2023 Compose V1 stopped receiving updates. It's also no longer available in new releases of Docker Desktop.
Compose V2 is included with all currently supported versions of Docker Desktop. Please use V2 to do below operations.
:::
To start this setup based on `docker-compose`, execute `docker-compose up -d`,
to launch Gitea in the background. Using `docker-compose ps` will show if Gitea
started properly. Logs can be viewed with `docker-compose logs`.
To shut down the setup, execute `docker-compose down`. This will stop
and kill the containers. The volumes will still exist.
:::note
If using a non-3000 port on http, change app.ini to match
`LOCAL_ROOT_URL = http://localhost:3000/`.
:::
## Install
After starting the Docker setup via `docker-compose`, Gitea should be available using a
favorite browser to finalize the installation. Visit http://server-ip:3000 and follow the
installation wizard. If the database was started with the `docker-compose` setup as
documented above, please note that `db` must be used as the database hostname.
## Customization
Customization files described [here](../administration/customizing-gitea.md) should
be placed in `/var/lib/gitea/custom` directory. If using host volumes, it's quite easy to access these
files; for named volumes, this is done through another container or by direct access at
`/var/lib/docker/volumes/gitea_gitea/_/var_lib_gitea`. The configuration file will be saved at
`/etc/gitea/app.ini` after the installation.
## Upgrading
:::warning
:exclamation::exclamation: **Make sure you have volumed data to somewhere outside Docker container** :exclamation::exclamation:
:::
To upgrade your installation to the latest release:
```bash
# Edit `docker-compose.yml` to update the version, if you have one specified
# Pull new images
docker-compose pull
# Start a new container, automatically removes old one
docker-compose up -d
```
## Upgrading from standard image
- Backup your setup
- Change volume mountpoint from /data to /var/lib/gitea
- If you used a custom app.ini move it to a new volume mounted to /etc/gitea
- Rename folder (inside volume) gitea to custom
- Edit app.ini if needed
- Set START_SSH_SERVER = true
- Use image docker.gitea.com/gitea:@dockerVersion@-rootless
## Managing Deployments With Environment Variables
In addition to the environment variables above, any settings in `app.ini` can be set
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
Full information [here](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini).
These environment variables can be passed to the docker container in `docker-compose.yml`.
The following example will enable a smtp mail server if the required env variables
`GITEA__mailer__FROM`, `GITEA__mailer__HOST`, `GITEA__mailer__PASSWD` are set on the host
or in a `.env` file in the same directory as `docker-compose.yml`.
The settings can be also set or overridden with the content of a file by defining an environment variable of the form:
`GITEA__section_name__KEY_NAME__FILE` that points to a file.
```bash
...
services:
server:
environment:
- GITEA__mailer__ENABLED=true
- GITEA__mailer__FROM=${GITEA__mailer__FROM:?GITEA__mailer__FROM not set}
- GITEA__mailer__PROTOCOL=smtp
- GITEA__mailer__HOST=${GITEA__mailer__HOST:?GITEA__mailer__HOST not set}
- GITEA__mailer__IS_TLS_ENABLED=true
- GITEA__mailer__USER=${GITEA__mailer__USER:-apikey}
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
```
To set required TOKEN and SECRET values, consider using Gitea's built-in [generate utility functions](../administration/command-line.md#generate).
+33 -33
View File
@@ -12,9 +12,16 @@ Gitea provides automatically updated Docker images within its Docker Hub organiz
possible to always use the latest stable tag or to use another service that handles updating
Docker images.
This reference setup guides users through the setup based on `docker-compose`, but the installation
of `docker-compose` is out of scope of this documentation. To install `docker-compose` itself, follow
the official [install instructions](https://docs.docker.com/compose/install/).
This reference setup guides users through the setup based on `docker compose`.
Docker compose has been included in the Docker Engine since the shift to Compose v2.
If, for some reason, compose is not available on your system, follow the official [install instructions](https://docs.docker.com/compose/install/).
This document targets for the default rootful image. For the rootless image,
see "[Installation with Docker (rootless)](./with-docker-rootless.md)"
ATTENTION: the rootful/rootless images are not compatible with the other.
If you have chosen one, you should always use the same one,
don't switch to the other one by changing the compose file's `image` value.
## Basics
@@ -23,11 +30,9 @@ image as a service. Since there is no database available, one can be initialized
Create a directory like `gitea` and paste the following content into a file named `docker-compose.yml`.
Note that the volume should be owned by the user/group with the UID/GID specified in the config file.
If you don't give the volume correct permissions, the container may not start.
For a stable release you can use `:latest`, `:1` or specify a certain release like `:@dockerVersion@`, but if you'd like to use the latest development version of Gitea then you could use the `:nightly` tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly` tag, where x is the minor version of Gitea. (e.g. `:1.16-nightly`)
For a stable release you can use `:latest`, `:1` or specify a certain release like `:@dockerVersion@`, but if you'd like to use the latest development version of Gitea then you could use the `:main-nightly` tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly` tag, where x is the minor version of Gitea. (e.g. `:1.27-nightly`)
```yaml
version: "3"
networks:
gitea:
external: false
@@ -58,8 +63,6 @@ the port section. It's common to just change the host port and keep the ports wi
the container like they are.
```diff
version: "3"
networks:
gitea:
external: false
@@ -93,8 +96,6 @@ To start Gitea in combination with a MySQL database, apply these changes to the
`docker-compose.yml` file created above.
```diff
version: "3"
networks:
gitea:
external: false
@@ -143,9 +144,14 @@ services:
To start Gitea in combination with a PostgreSQL database, apply these changes to
the `docker-compose.yml` file created above.
```diff
version: "3"
:::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:
external: false
@@ -176,7 +182,7 @@ services:
+ - db
+
+ db:
+ image: docker.io/library/postgres:14
+ image: docker.io/library/postgres:18
+ restart: always
+ environment:
+ - POSTGRES_USER=gitea
@@ -185,7 +191,7 @@ services:
+ networks:
+ - gitea
+ volumes:
+ - ./postgres:/var/lib/postgresql/data
+ - ./postgres:/var/lib/postgresql
```
## Named volumes
@@ -196,8 +202,6 @@ create the required volume. You don't need to worry about permissions with
named volumes; Docker will deal with that automatically.
```diff
version: "3"
networks:
gitea:
external: false
@@ -227,17 +231,11 @@ MySQL or PostgreSQL containers will need to be created separately.
## Startup
:::note
From July 2023 Compose V1 stopped receiving updates. It's also no longer available in new releases of Docker Desktop.
To start this setup based on `docker compose`, execute `docker compose up -d`,
to launch Gitea in the background. Using `docker compose ps` will show if Gitea
started properly. Logs can be viewed with `docker compose logs`.
Compose V2 is included with all currently supported versions of Docker Desktop. Please use V2 to do below operations.
:::
To start this setup based on `docker-compose`, execute `docker-compose up -d`,
to launch Gitea in the background. Using `docker-compose ps` will show if Gitea
started properly. Logs can be viewed with `docker-compose logs`.
To shut down the setup, execute `docker-compose down`. This will stop
To shut down the setup, execute `docker compose down`. This will stop
and kill the containers. The volumes will still exist.
:::note
@@ -247,9 +245,9 @@ If using a non-3000 port on http, change app.ini to match
## Installation
After starting the Docker setup via `docker-compose`, Gitea should be available using a
After starting the Docker setup via `docker compose`, Gitea should be available using a
favorite browser to finalize the installation. Visit http://server-ip:3000 and follow the
installation wizard. If the database was started with the `docker-compose` setup as
installation wizard. If the database was started with the `docker compose` setup as
documented above, please note that `db` must be used as the database hostname.
## Configure the user inside Gitea using environment variables
@@ -279,17 +277,18 @@ To upgrade your installation to the latest release:
```bash
# Edit `docker-compose.yml` to update the version, if you have one specified
# Pull new images
docker-compose pull
docker compose pull
# Start a new container, automatically removes old one
docker-compose up -d
docker compose up -d
```
## Managing Deployments With Environment Variables
In addition to the environment variables above, any settings in `app.ini` can be set
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
Full information [here](https://github.com/go-gitea/gitea/tree/master/contrib/environment-to-ini).
or overridden with an environment variable of the form: `GITEA__section_name__KEY_NAME=value`.
These settings are applied each time the docker container starts by `environment-to-ini` command
(a warpper of `gitea config edit-ini`), and won't be passed into Gitea's sub-processes.
See `./gitea config edit-ini --help` for more details.
These environment variables can be passed to the docker container in `docker-compose.yml`.
The following example will enable an smtp mail server if the required env variables
@@ -332,5 +331,6 @@ services:
```
### SSH with multiple IP addresses
This assumes that the host machine has more than one reachable IP address: `192.168.1.1` (host) `192.168.1.2` (gitea)
On the host machine, configure SSHD in `/etc/ssh/sshd_config` to listen on one IP address `ListenAddress 192.168.1.1`. In the compose file the SSH port forwarding then needs to be changed to `"192.168.1.2:22:22"`. The port forwarding needs to be adjusted similarily for all other forwarded ports to avoid problems with DNS.
+166
View File
@@ -0,0 +1,166 @@
---
date: "2026-09-03T20:00:00+02:00"
slug: "install-with-podman-quadlet"
sidebar_position: 65
aliases:
- /en-us/install-with-podman-quadlet
---
# Installation with Podman Quadlet
Similarly to [Docker](with-docker.md), [Podman](https://podman.io/) can be used to deploy Gitea.
This reference setup guides users through the setup based on Podman Quadlet.
Podman Quadlet is the native integration of Podman through systemd.
To learn more about Podman Quadlet, see [systemd units using Podman Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html).
This setup installs the quadlets in `~/.config/containers/systemd/`, the directory for rootless quadlets, and uses the rootless images.
If you install them in a rootful directory such as `/etc/containers/systemd/`, use the rootful images instead.
## Basics
Since Podman v6.0 a single `gitea.quadlets` file can hold multiple quadlets separated by the `---` delimiter.
Paste the following content into a file named `gitea.quadlets`
```ini
# FileName=gitea-data
[Volume]
VolumeName=gitea-data
---
# FileName=gitea-config
[Volume]
VolumeName=gitea-config
---
# FileName=gitea
[Container]
PublishPort=2222:2222
PublishPort=3000:3000
Image=docker.gitea.com/gitea:@dockerVersion@-rootless
ContainerName=gitea
Mount=type=volume,src=gitea-data.volume,destination=/var/lib/gitea
Mount=type=volume,src=gitea-config.volume,destination=/etc/gitea
[Service]
Restart=always
[Install]
# Start with the user session
WantedBy=default.target
```
You can run the installation command
```sh
$ podman quadlet install ./gitea.quadlets --application=gitea
/home/user/.config/containers/systemd/gitea/gitea-data.volume
/home/user/.config/containers/systemd/gitea/gitea-config.volume
/home/user/.config/containers/systemd/gitea/gitea.container
```
The `--application=gitea` flag allows us to tell podman to group the quadlets together, this can help for managing and organizing the quadlets files.
You can validate the quadlets are properly installed by looking at the list command
```sh
$ podman quadlet list
NAME UNIT NAME PATH ON DISK STATUS APPLICATION POD
gitea-config.volume gitea-config-volume.service /home/user/.config/containers/systemd/gitea/gitea-config.volume active/exited gitea
gitea-data.volume gitea-data-volume.service /home/user/.config/containers/systemd/gitea/gitea-data.volume active/exited gitea
gitea.container gitea.service /home/user/.config/containers/systemd/gitea/gitea.container failed/failed gitea
```
You can start the application by running `systemctl --user start gitea` command.
`WantedBy=default.target` starts the service when the user session starts.
Rootless user services do not run without a session, so to start Gitea at boot, enable lingering for the user with `loginctl enable-linger $USER`.
## Databases
### PostgreSQL database
To start Gitea in combination with a PostgreSQL database, apply these changes to the
`gitea.quadlets` file created above.
To start Gitea with a database, we need to create a network, so the database and Gitea container can communicate.
```diff
# FileName=gitea-data
[Volume]
VolumeName=gitea-data
---
# FileName=gitea-config
[Volume]
VolumeName=gitea-config
---
+ # FileName=gitea-postgres-data
+ [Volume]
+ VolumeName=gitea-postgres-data
+ ---
+ # FileName=gitea
+ [Network]
+ NetworkName=gitea
+ ---
+ # FileName=gitea-postgres
+ [Container]
+ Image=docker.io/library/postgres:18
+ ContainerName=gitea-postgres
+ Network=gitea.network
+ Mount=type=volume,src=gitea-postgres-data.volume,destination=/var/lib/postgresql
+ Environment=POSTGRES_USER=gitea
+ Environment=POSTGRES_PASSWORD=gitea
+ Environment=POSTGRES_DB=gitea
+
+ [Service]
+ Restart=always
+
+ [Install]
+ # Start with the user session
+ WantedBy=default.target
+ ---
# FileName=gitea
+ [Unit]
+ Requires=gitea-postgres.service
+ After=gitea-postgres.service
+
[Container]
PublishPort=2222:2222
PublishPort=3000:3000
Image=docker.gitea.com/gitea:@dockerVersion@-rootless
ContainerName=gitea
Mount=type=volume,src=gitea-data.volume,destination=/var/lib/gitea
Mount=type=volume,src=gitea-config.volume,destination=/etc/gitea
+ Network=gitea.network
+ Environment=GITEA__database__DB_TYPE=postgres
+ Environment=GITEA__database__HOST=gitea-postgres:5432
+ Environment=GITEA__database__NAME=gitea
+ Environment=GITEA__database__USER=gitea
+ Environment=GITEA__database__PASSWD=gitea
[Service]
Restart=always
[Install]
# Start with the user session
WantedBy=default.target
```
## Logs
As systemd manages the container we can use `journalctl` to access the logs
```sh
$ journalctl --user --follow --unit=gitea.service
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:263:runWeb() [I] Starting Gitea on PID: 2
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:115:showWebStartupMessage() [I] Gitea version: 1.27.3 built with go1.26.7-X:jsonv2 : bindata, timetzdata,
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:116:showWebStartupMessage() [I] * RunMode: prod
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:117:showWebStartupMessage() [I] * AppPath: /usr/local/bin/gitea
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:118:showWebStartupMessage() [I] * WorkPath: /var/lib/gitea
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:119:showWebStartupMessage() [I] * CustomPath: /var/lib/gitea/custom
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:120:showWebStartupMessage() [I] * ConfigFile: /etc/gitea/app.ini
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:121:showWebStartupMessage() [I] Prepare to run install page
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:329:listen() [I] Listen: http://0.0.0.0:3000
gitea[5967]: 2026/09/03 14:50:42 cmd/web.go:333:listen() [I] AppURL(ROOT_URL): http://localhost:3000/
gitea[5967]: 2026/09/03 14:50:42 modules/graceful/server.go:52:NewServer() [I] Starting new Web server: tcp:0.0.0.0:3000 on PID: 2
```
@@ -10,13 +10,13 @@ aliases:
# Protected branches
Protected branches prevent unwanted changes by enforcing push and merge policies on selected branches. The rules are enforced for every Git protocol (HTTP(S), SSH), the web editor, the API, and background jobs such as auto-merge. Only repository owners and administrators can manage the rules, and the Branches page is read-only while a repository is archived.
Protected branches prevent unwanted changes by enforcing push, deletion, and merge policies on selected branches. The rules are enforced for every Git protocol (HTTP(S), SSH), the web editor, the API, and background jobs such as auto-merge. Only repository owners and administrators can manage the rules, and the Branches page is read-only while a repository is archived.
## Creating or editing a rule
1. Open the repository and select **Settings → Branches** (repository admin permission required).
2. Select **Add new rule** or **Edit** next to an existing rule.
3. Fill in the **Protected branch name pattern** and optional file patterns, then configure the push, merge, and review options described below.
3. Fill in the **Protected branch name pattern** and optional file patterns, then configure the push, deletion, merge, and review options described below.
4. Select **Save rule**.
The rule immediately applies to all matching branches, even if the branches are created in the future.
@@ -48,7 +48,9 @@ The **Push** section controls direct pushes (including the web editor and API).
- **Disable push** makes the branch read-only. Any attempt to push directly fails, and changes must be merged through pull requests.
- **Enable push** allows anyone with [write access](./permissions.md) to push (force pushes are still blocked unless explicitly allowed).
- **Allowlist restricted push** requires being on the allowlist. Choose users and, for organization-owned repositories, teams. Deploy keys that already have write access can also be allowlisted.
- **Allowlist restricted push** requires being on the allowlist. Choose users and, for organization-owned repositories, teams.
The user allowlists for push, force-push and deletion can include the **Gitea Actions** and **Deploy Key** system users. They still require write access; **Deploy Key** also covers deploy tokens.
When a push is blocked, the server-side hook rejects the update with an explanation.
@@ -58,7 +60,17 @@ Force pushes have their own set of options:
- **Disable force push** completely forbids rewriting history on the branch.
- **Enable force push** allows anyone who can push to also force push.
- **Allowlist restricted force push** limits force pushes to a separate allowlist (users, teams, and optionally deploy keys) **and** requires the person to already have regular push access.
- **Allowlist restricted force push** limits force pushes to a separate allowlist of users or teams **and** requires regular push access.
## Branch deletion
The **Branch Deletion** section controls whether matching protected branches can be deleted:
- **Disable branch deletion** prevents deletion. This is the default.
- **Enable branch deletion** allows anyone who can push to delete the branch.
- **Allowlist restricted branch deletion** limits deletion to a separate allowlist of users or teams **and** requires regular push access.
These rules apply to Git (`git push --delete`), the API, the web interface and post-merge cleanup. The default branch and configured default pull request target branch cannot be deleted.
## Pull request merges and approvals
+31
View File
@@ -0,0 +1,31 @@
---
date: "2026-08-30T00:00:00+02:00"
slug: "artifacts"
sidebar_position: 70
---
# Artifacts
Workflow runs can store files such as test results, coverage reports, and build output as artifacts. Artifacts are uploaded by workflows, for example with [`actions/upload-artifact`](https://github.com/actions/upload-artifact), and appear on the run page after the upload completes.
## Previewing artifacts
Select an artifact on the run page to open its file browser and preview in the same tab. The preview identifies the originating run and attempt, and provides links back to that run and to download the complete artifact. Selecting files in the browser updates the preview in the same tab.
Artifact previews:
- require sign-in and access to the Actions run to open the preview page
- render text-based files, images (including SVG), and PDFs
- run HTML and JavaScript content in a sandboxed frame
Preview content is loaded through signed URLs that expire after one hour and do not require a session cookie. Reopen the preview page to obtain a fresh URL after it expires.
The file browser lists up to 2,000 files per artifact. Larger artifacts show a notice when the list is truncated.
Unsupported or oversized files can still be downloaded with the complete artifact.
## Instance configuration
Site administrators can limit the total artifact size that can be browsed or previewed with `ARTIFACT_PREVIEW_MAX_SIZE` in the `[actions]` section of `app.ini`. The default is 10 MiB. Set it to `0` to disable previews or `-1` to allow artifacts of any size.
The size of an individual previewed file is also limited by [`MAX_DISPLAY_FILE_SIZE`](../../administration/config-cheat-sheet.md#ui-ui) in the `[ui]` section.
+38 -67
View File
@@ -6,123 +6,94 @@ sidebar_position: 120
# Compared to GitHub Actions
Even though Gitea Actions is designed to be compatible with GitHub Actions, there are some differences between them.
Gitea Actions is designed to be compatible with GitHub Actions, with the differences below.
## Additional features
### Absolute action URLs
Gitea Actions supports defining actions via absolute URL, which means that you can use actions from any git repository.
Like `uses: https://github.com/actions/checkout@v4` or `uses: http://your_gitea.com/owner/repo@branch`.
`uses:` accepts an absolute URL to any git host, e.g. `uses: https://gitea.com/actions/checkout@v4`.
### Action prefixes
`uses:` accepts these prefixes:
- `self:` references your own Gitea instance, e.g. `uses: self:owner/repo@v1` or `uses: self:owner/repo/.gitea/workflows/build.yml@v1`
- `builtin:` runs an action built into Gitea Runner, which needs no download and no Node in the job image, e.g. `uses: builtin:checkout`
`builtin:checkout` accepts the `repository`, `ref`, `token`, `path` and `fetch-depth` inputs of `actions/checkout` with the same defaults, and fails on any other input.
### Workflow-relative actions
`$/` references the repository and commit of the workflow, or of the enclosing composite action, e.g. `uses: $/.gitea/actions/build`.
Unlike `./`, it needs no checkout first.
### Actions written in Go
Gitea Actions supports writing actions in Go.
See [Creating Go Actions](https://blog.gitea.com/creating-go-actions/).
### Support the non-standard syntax @yearly, @monthly, @weekly, @daily, @hourly on schedule
Github Actions doesn't support that. https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule
`schedule` also accepts `@yearly`, `@monthly`, `@weekly`, `@daily` and `@hourly`, which [GitHub does not](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule).
## Unsupported workflows syntax
### `concurrency`
It's used to run a single job at a time.
See [Using concurrency](https://docs.github.com/en/actions/using-jobs/using-concurrency).
It's ignored by Gitea Actions now.
### `permissions` and `jobs.<job_id>.permissions`
See [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions).
It's ignored by Gitea Actions now.
### `jobs.<job_id>.timeout-minutes`
See [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes).
It's ignored by Gitea Actions now.
### `jobs.<job_id>.continue-on-error`
See [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idcontinue-on-error).
It's ignored by Gitea Actions now.
### `jobs.<job_id>.environment`
See [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idenvironment).
It's ignored by Gitea Actions now.
[`jobs.<job_id>.environment`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idenvironment) is ignored.
### Complex `runs-on`
See [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on).
[`runs-on`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on) supports:
Gitea Actions only supports `runs-on: xyz` or `runs-on: [xyz]` now.
- Static strings: `runs-on: self-hosted`
- Arrays of labels: `runs-on: [linux, self-hosted]`
- String expressions: `runs-on: ${{ github.event_name == 'push' && 'ubuntu-latest' || 'self-hosted' }}`
- Arrays containing expressions: `runs-on: [linux, "${{ github.event_name == 'push' && 'ubuntu-latest' || 'self-hosted' }}"]`
## Missing features
### Package repository authorization
The `GITEA_TOKEN` for a job running within a repository should be able to publish to the associated package repository (i.e. to upload OCI images). See the "packages" scope for the "default access" in [Automatic token authentication](https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token).
This is not implemented in Gitea Actions now. A workaround for Gitea Actions is to use a Personal Access Token (PAT). See this [github issue and comment](https://github.com/go-gitea/gitea/issues/23642#issuecomment-2119876692) for tracking this feature.
`GITEA_TOKEN` cannot publish to the package registry of its repository, e.g. to push OCI images.
Use a personal access token instead, see [this issue](https://github.com/go-gitea/gitea/issues/23642#issuecomment-2119876692).
### Problem Matchers
Problem Matchers are a way to scan the output of actions for a specified regex pattern and surface that information prominently in the UI.
See [Problem matchers](https://github.com/actions/toolkit/blob/main/docs/problem-matchers.md).
It's ignored by Gitea Actions now.
[Problem matchers](https://github.com/actions/toolkit/blob/main/docs/problem-matchers.md) are ignored.
### Create an error annotation
See [Creating an annotation for an error](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-creating-an-annotation-for-an-error)
It's ignored by Gitea Actions now.
[Error annotations](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-creating-an-annotation-for-an-error) are ignored.
### Expressions
For [expressions](https://docs.github.com/en/actions/learn-github-actions/expressions), only [`always()`](https://docs.github.com/en/actions/learn-github-actions/expressions#always) is supported.
[Expressions](https://docs.github.com/en/actions/learn-github-actions/expressions) support the standard GitHub functions and contexts.
## Missing UI features
### Pre and Post steps
Pre and Post steps don't have their own section in the job log user interface.
Pre and post steps have no section of their own in the job log.
### Services steps
Services steps don't have their own section in the job log user interface.
Service steps have no section of their own in the job log.
## Different behavior
### Concurrency
### Job token permissions (`permissions`)
As of v1.21.0, gitea behaves as if `concurrency.cancel-in-progress` is set to `true`.
This means that newly-triggered workflows will pre-empt runs already in progress for previous triggers.
See [PR #25716](https://github.com/go-gitea/gitea/pull/25716) for additional details.
`permissions` and `jobs.<job_id>.permissions` control the `GITEA_TOKEN` permissions, clamped by the repository and owner settings and further restricted for fork pull requests and cross-repository access.
GitHub-only scopes like `statuses`, `checks`, `deployments`, `security-events` and `pages` are not supported, while Gitea adds `code`, `releases`, `wiki` and `projects`. `id-token` works like on GitHub, see [OpenID Connect](openid-connect.md).
See [Actions job token permissions](token-permissions.md).
### Downloading actions
Previously (Pre 1.21.0), `[actions].DEFAULT_ACTIONS_URL` defaulted to `https://gitea.com`.
We have since restricted this option to only allow two values (`github` and `self`).
When set to `github`, the new default, Gitea will download non-fully-qualified actions from `https://github.com`.
For example, if you use `uses: actions/checkout@v4`, it will download the checkout repository from `https://github.com/actions/checkout.git`.
If you want to download an action from another git hoster, you can use an absolute URL, e.g. `uses: https://gitea.com/actions/checkout@v4`.
If your Gitea instance is in an intranet or a restricted area, you can set the URL to `self` to only download actions from your own instance by default.
Of course, you can still use absolute URLs in workflows.
More details about the `[actions].DEFAULT_ACTIONS_URL` configuration can be found in the [Configuration Cheat Sheet](../../administration/config-cheat-sheet.md#actions-actions)。
Actions without a host, like `uses: actions/checkout@v4`, are downloaded from `https://github.com`, or from your own instance when `[actions].DEFAULT_ACTIONS_URL` is `self`.
See the [Configuration Cheat Sheet](../../administration/config-cheat-sheet.md#actions-actions).
For other sources, see [Absolute action URLs](#absolute-action-urls), [Action prefixes](#action-prefixes) and [Workflow-relative actions](#workflow-relative-actions).
### Context availability
Context availability is not checked, so you can use the env context on more places.
See [Context availability](https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability).
[Context availability](https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability) is not checked, so contexts like `env` work in more places.
+12 -36
View File
@@ -8,33 +8,9 @@ sidebar_position: 140
Gitea Actions has multiple components. This document describes them individually.
## Act
## Gitea Runner
The [nektos/act](https://github.com/nektos/act) project is an excellent tool that allows you to run your GitHub Actions locally.
We were inspired by this and wondered if it would be possible to run actions for Gitea.
However, while [nektos/act](https://github.com/nektos/act) is designed as a command line tool, what we actually needed was a Go library with modifications specifically for Gitea.
So we forked it as [gitea/act](https://gitea.com/gitea/act).
This is a soft fork that will periodically follow the upstream.
Although some custom commits have been added, we will try our best to avoid changing too much of the original code.
The forked act is just a shim or adapter for Gitea's specific usage.
There are some additional commits that have been made, such as:
- Outputting execution logs to logger hook so they can be reported to Gitea
- Disabling the GraphQL URL, since Gitea doesn't support it
- Starting a new container for every job instead of reusing to ensure isolation.
These modifications have no reason to be merged into the upstream.
They don't make sense if the user just wants to run trusted actions locally.
However, there may be overlaps in the future, such as a required bug fix or new feature needed by both projects.
In these cases, we will contribute the changes back to the upstream repository.
## Act runner
Gitea's runner is called act runner because it's based on act.
Gitea Runner is based on a hard fork of [nektos/act](https://github.com/nektos/act).
Like other CI runners, we designed it as an external part of Gitea, which means it should run on a different server than Gitea.
@@ -43,11 +19,11 @@ Additionally, the runner will introduce itself to Gitea and declare what kind of
Earlier, we mentioned that `runs-on: ubuntu-latest` in a workflow file means that the job will be run on a runner with the `ubuntu-latest` label.
But how does the runner know to run `ubuntu-latest`? The answer lies in mapping the label to an environment.
That's why when you add custom labels during registration, you will need to input some complex content like `my_custom_label:docker://centos:7`.
That's why each label of a runner names an environment, like `my_custom_label:docker://centos:7`.
This means that the runner can take the job which needs to run on `my_custom_label`, and it will run it via a docker container with the image `centos:7`.
Docker isn't the only option, though.
The act also supports running jobs directly on the host.
The runner also supports running jobs directly on the host.
This is achieved through labels like `linux_arm:host`.
This label indicates that the runner can take a job that needs to run on `linux_arm` and run it directly on the host.
@@ -58,16 +34,15 @@ So,
- `my_custom_label:docker://node:18`: Run jobs labeled with `my_custom_label` using the `node:18` Docker image.
- `my_custom_label:host`: Run jobs labeled with `my_custom_label` directly on the host.
- `my_custom_label`: Same as `my_custom_label:host`.
- `my_custom_label:vm:ubuntu-latest`: (Example only, not implemented) Run jobs labeled with `my_custom_label` using a virtual machine with the `ubuntu-latest` ISO.
## Communication protocol
As act runner is an independent part of Gitea, we needed a protocol for runners to communicate with the Gitea instance.
As the runner is an independent part of Gitea, we needed a protocol for runners to communicate with the Gitea instance.
However, we did not think it was a good idea to have Gitea listen on a new port.
Instead, we wanted to reuse the HTTP port, which means we needed a protocol that is compatible with HTTP.
We chose to use gRPC over HTTP.
We use [actions-proto-def](https://gitea.com/gitea/actions-proto-def) and [actions-proto-go](https://gitea.com/gitea/actions-proto-go) to wire them up.
The protocol is defined in [actions-proto-def](https://gitea.com/gitea/actions-proto-def), its Go code lives in [actionslib](https://gitea.com/gitea/actionslib).
More information about gRPC can be found on [its website](https://grpc.io/).
## Network architecture
@@ -79,9 +54,9 @@ This will help you troubleshoot some problems and explain why it's a bad idea to
There are four network connections marked in the picture, and the direction of the arrows indicates the direction of establishing the connections.
### Connection 1, act runner to Gitea instance
### Connection 1, runner to Gitea instance
The act runner must be able to connect to Gitea to receive tasks and send back the execution results.
The runner must be able to connect to Gitea to receive tasks and send back the execution results.
### Connection 2, job containers to Gitea instance
@@ -92,10 +67,11 @@ Fetching code is not always necessary to run some jobs, but it is required in mo
If you use a loopback address to register a runner, the runner can connect to Gitea when it is on the same machine.
However, if a job container tries to fetch code from localhost, it will fail because Gitea is not in the same container.
### Connection 3, act runner to internet
### Connection 3, runner to internet
When you use some actions like `actions/checkout@v4`, the act runner downloads the scripts, not the job containers.
By default, it downloads from [github.com](http://github.com/), so it requires access to the internet. If you configure the `DEFAULT_ACTIONS_URL` to `self`, then it will download from your Gitea instance by default. Then it will not connect to internet when downloading the action itself.
When you use some actions like `actions/checkout@v4`, the runner downloads the scripts, not the job containers.
By default, it downloads them from [github.com](https://github.com/), which requires internet access.
With `DEFAULT_ACTIONS_URL` set to `self`, or with `uses: self:owner/repo@ref`, it downloads them from your Gitea instance instead.
It also downloads some docker images from Docker Hub by default, which also requires internet access.
However, internet access is not strictly necessary.
+41 -89
View File
@@ -27,50 +27,24 @@ Still, this is completely optional since both options have the same effect at th
## Where will the runner download scripts when using actions such as `actions/checkout@v4`?
There are tens of thousands of [actions scripts](https://github.com/marketplace?type=actions) in GitHub, and when you write `uses: actions/checkout@v4`, it downloads the scripts from [github.com/actions/checkout](http://github.com/actions/checkout) by default.
But what if you want to use actions from other places such as gitea.com instead of GitHub?
From `https://github.com` by default, or from your own instance when `[actions].DEFAULT_ACTIONS_URL` is `self`, see the [Configuration Cheat Sheet](../../administration/config-cheat-sheet.md#actions-actions).
The good news is that you can specify the URL prefix to use actions from anywhere.
This is an extra syntax in Gitea Actions.
For example:
To use an action from elsewhere, name its host:
- `uses: https://gitea.com/xxx/xxx@xxx`
- `uses: https://github.com/xxx/xxx@xxx`
- `uses: http://your_gitea_instance.com/xxx@xxx`
Be careful, the `https://` or `http://` prefix is necessary!
This is one of the differences from GitHub Actions which supports actions scripts only from GitHub.
But it should allow users much more flexibility in how they run Actions.
Alternatively, if you want your runners to download actions from your own Gitea instance by default, you can configure it by setting `[actions].DEFAULT_ACTIONS_URL`.
See [Configuration Cheat Sheet](../../administration/config-cheat-sheet.md#actions-actions).
- `uses: https://gitea.com/owner/repo@ref`
- `uses: http://your_gitea_instance.com/owner/repo@ref`
- `uses: self:owner/repo@ref` for your own Gitea instance
## How to limit the permission of the runners?
Runners have no more permissions than simply connecting to your Gitea instance.
When any runner receives a job to run, it will temporarily gain limited permission to the repository associated with the job.
If you want to give more permissions to the runner, allowing it to access more private repositories or external systems, you can pass [secrets](usage/actions/secrets.md) to it.
Runners only connect to your Gitea instance.
For each job, a runner gets a `GITEA_TOKEN` limited to the job's repository, see [Actions job token permissions](token-permissions.md).
To give a job access to more private repositories or external systems, pass it [secrets](usage/actions/secrets.md).
Refined permission control to Actions is a complicated job.
In the future, we will add more options to Gitea to make it more configurable, such as allowing more write access to repositories or read access to all repositories in the same organization.
## Which operating systems are supported by Gitea Runner?
## Which operating systems are supported by act runner?
We released official binaries for Linux, macOS, and Windows.
While other operating systems are theoretically supported if it is supported by golang and docker(docker mode enabled).
One thing to note is that if you choose to run jobs directly on the host instead of in job containers, the environmental differences between operating systems may cause unexpected failures.
For example, bash is not available on Windows in most cases, while act tries to use bash to run scripts by default.
Therefore, you need to specify `powershell` as the default shell in your workflow file, see [defaults.run](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#defaultsrun).
```yaml
defaults:
run:
shell: powershell
```
Official binaries are released for Linux, macOS and Windows.
Other systems supported by Go and Docker work in theory.
## How to avoid being hacked?
@@ -99,72 +73,47 @@ It is exciting to be able to reuse them.
## What if it runs on multiple labels, such as `runs-on: [label_a, label_b]`?
This is valid syntax.
It means that it should run on runners that have both the `label_a` **and** `label_b` labels, see [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on).
Unfortunately, act runner does not work this way until v0.2.11.
As mentioned, we map labels to environments:
- `ubuntu` → `ubuntu:22.04`
- `centos` → `centos:8`
But we need to map label groups to environments instead, like so:
- `[ubuntu]` → `ubuntu:22.04`
- `[with-gpu]` → `linux:with-gpu`
- `[ubuntu, with-gpu]` → `ubuntu:22.04_with-gpu`
We also need to re-design how tasks are assigned to runners.
A runner with `ubuntu`, `centos`, or `with-gpu` does not necessarily indicate that it can accept jobs with `[centos, with-gpu]`.
Therefore, the runner should inform the Gitea instance that it can only accept jobs with `[ubuntu]`, `[centos]`, `[with-gpu]`, and `[ubuntu, with-gpu]`.
This is not a technical problem, it was just overlooked in the early design.
See [runtime.go#L65](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L65).
Currently, the act runner attempts to match everyone in the labels and uses the first match it finds.
The job runs on a runner that has all of the labels, as on [GitHub](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on).
The runner uses the environment of the first label it has.
## What is the difference between agent labels and custom labels for a runner?
![labels](/images/usage/actions/labels.png)
Agent labels are reported to the Gitea instance by the runner during registration.
Custom labels, on the other hand, are added manually by a Gitea administrator or owners of the organization or repository (depending on the level of the runner).
However, the design here needs improvement, as it currently has some rough edges.
You can add a custom label such as `centos` to a registered runner, which means the runner will receive jobs with `runs-on: centos`.
However, the runner may not know which environment to use for this label, resulting in it using a default image or leading to a logical dead end.
This default may not match user expectations.
See [runtime.go#L71](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L71).
In the meantime, we suggest that you re-register your runner if you want to change its labels.
Gitea no longer has custom labels.
A runner declares its labels every time it starts, from its `runner.labels` configuration or the labels given at registration, so change them there and restart the runner.
## Will there be more implementations for Gitea Actions runner?
Although we would like to provide more options, our limited manpower means that act runner will be the only officially supported runner at the moment.
Although we would like to provide more options, our limited manpower means that Gitea Runner will be the only officially supported runner at the moment.
However, both Gitea and act runner are completely open source under MIT License, so anyone can modify the code to satisfy their requirements.
However, both Gitea and Gitea Runner are completely open source under MIT License, so anyone can modify the code to satisfy their requirements.
In case you fork act runner to create your own version: Please contribute the changes back if you can and if you think your changes will help others as well.
In case you fork Gitea Runner to create your own version: Please contribute the changes back if you can and if you think your changes will help others as well.
## What workflow trigger events does Gitea support?
All events listed in this table are supported events and are compatible with GitHub.
For events supported only by GitHub, see GitHub's [documentation](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows).
| trigger event | activity types |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------|
| create | not applicable |
| delete | not applicable |
| fork | not applicable |
| gollum | not applicable |
| push | not applicable |
| issues | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `milestoned`, `demilestoned`, `labeled`, `unlabeled` |
| issue_comment | `created`, `edited`, `deleted` |
| pull_request | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `synchronize`, `labeled`, `unlabeled` |
| pull_request_review | `submitted`, `edited` |
| pull_request_review_comment | `created`, `edited` |
| release | `published`, `edited` |
| registry_package | `published` |
| workflow_dispatch | not applicable |
| workflow_run | `requested`, `completed` |
| trigger event | activity types |
|----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| create | not applicable |
| delete | not applicable |
| fork | not applicable |
| gollum | not applicable |
| push | not applicable |
| schedule | not applicable |
| workflow_dispatch | not applicable |
| workflow_call | not applicable |
| issues | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `milestoned`, `demilestoned`, `labeled`, `unlabeled` |
| issue_comment | `created`, `edited`, `deleted` |
| pull_request<br/>pull_request_target | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `synchronize`, `labeled`, `unlabeled`, `milestoned`, `demilestoned`, `review_requested`, `review_request_removed` |
| pull_request_review | `submitted`, `edited` |
| pull_request_review_comment | `created`, `edited` |
| release | `published`, `edited` |
| registry_package | `published` |
| workflow_run | `requested`, `in_progress`, `completed` |
> Without an explicit `types:` filter, `pull_request` and `pull_request_target` only run on `opened`, `reopened` and `synchronize`, matching GitHub. All other events run on every activity type they support.
> For `pull_request` events, in [GitHub Actions](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request), the `ref` is `refs/pull/:prNumber/merge`, which is a reference to the merge commit preview. However, Gitea has no such reference.
> Therefore, the `ref` in Gitea Actions is `refs/pull/:prNumber/head`, which points to the head of pull request rather than the preview of the merge commit.
@@ -173,3 +122,6 @@ For events supported only by GitHub, see GitHub's [documentation](https://docs.g
Go to the repository's **Settings** > **Actions** > **General** page and add collaborative owners.
The private repositories of collaborative owners are allowed to access the actions and workflows in the current repository.
To share within the same user or organization, add the private repositories under its **Settings** > **Actions** > **General** > **Cross-Repository Access** instead.
See [Cross-repository access](token-permissions.md#cross-repository-access).
+60
View File
@@ -0,0 +1,60 @@
---
date: "2026-08-23T00:00:00+00:00"
slug: "openid-connect"
sidebar_position: 40
---
# OpenID Connect
Jobs can request short-lived OpenID Connect (OIDC) tokens to sign in to cloud providers and other services without storing long-lived secrets. The tokens use the GitHub Actions format, so actions like `aws-actions/configure-aws-credentials`, `google-github-actions/auth` and `azure/login` work unchanged.
## Trusting Gitea
Add Gitea as an OIDC identity provider in the service:
- Issuer: `<ROOT_URL>/api/actions/oidc`
- Audience: `<ROOT_URL>/<owner>`, unless the workflow requests another one
Then limit which workflows can sign in with a condition on the [`sub` claim](#claims).
Gitea signs the tokens with a key it creates at `<APP_DATA_PATH>/jwt/actions_oidc.pem`. Instances behind a load balancer must share this file.
## Requesting a token
Grant the `id-token` permission to the workflow or job:
```yaml
permissions:
id-token: write
```
Default permissions never include it, and jobs from fork pull requests never get it. Owners and repositories can disable it with their [maximum token permissions](token-permissions.md#maximum-token-permissions-clamping).
Actions like the ones above request the token themselves. In a script, use `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN`:
```shell
curl --fail --silent --show-error \
--header "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=my-service"
```
The token is in the `value` field of the response and expires after five minutes.
## Claims
The `sub` claim names the owner and repository with their IDs, so a renamed or recreated repository cannot match an existing trust policy:
```text
repo:<owner>@<owner-id>/<repo>@<repo-id>:ref:<ref>
repo:<owner>@<owner-id>/<repo>@<repo-id>:pull_request
```
The `pull_request` event uses the second form, all other events use the first, including `pull_request_target`.
The other claims match GitHub's, like `repository`, `ref`, `sha`, `workflow_ref` and `job_workflow_ref`. The discovery document at `<ROOT_URL>/api/actions/oidc/.well-known/openid-configuration` lists them all.
Differences from GitHub Actions:
- There is no `environment` claim.
- Pull request runs use `refs/pull/<index>/head` and its commit, not the merge ref and merge commit.
- `run_number` counts runs per repository, not per workflow.
+2 -2
View File
@@ -21,8 +21,8 @@ To avoid confusion, we have clarified the spelling here:
## Runners
Just like other CI/CD solutions, Gitea doesn't run the jobs itself, but delegates the jobs to runners.
The runner of Gitea Actions is called [act runner](https://gitea.com/gitea/act_runner), it is a standalone program and also written in Go.
An important part of the application comes from a [fork](https://gitea.com/gitea/act) of [nektos/act](http://github.com/nektos/act).
The runner of Gitea Actions is called [Gitea Runner](https://gitea.com/gitea/runner), it is a standalone program and also written in Go.
An important part of the application comes from a hard fork of [nektos/act](http://github.com/nektos/act).
Because the runner is deployed independently, there could be potential security issues.
To avoid them, please follow two simple rules:
+5 -5
View File
@@ -25,10 +25,10 @@ If you want to learn more or encounter any problems while configuring it, please
### Set up runner
Gitea Actions requires [act runner](https://gitea.com/gitea/act_runner) to run the jobs.
Gitea Actions requires [Gitea Runner](https://gitea.com/gitea/runner) to run the jobs.
In order to avoid consuming too many resources and affecting the Gitea instance, it is recommended to start runners on separate machines from the Gitea instance.
You can use the [pre-built binaries](http://dl.gitea.com/act_runner) or the [docker images](https://hub.docker.com/r/gitea/act_runner/tags) to set up the runner.
You can use the [pre-built binaries](http://dl.gitea.com/gitea-runner) or the [docker images](https://hub.docker.com/r/gitea/runner/tags) to set up the runner.
Before proceeding any further, we suggest running it as a command line with pre-built binaries to ensure that it works with your environment, especially if you are running a runner on your localhost.
And it could be easier to debug if something goes wrong.
@@ -40,7 +40,7 @@ However, it is recommended to use Docker to run the jobs, because it is more sec
Before running a runner, you should first register it to your Gitea instance using the following command:
```bash
./act_runner register --no-interactive --instance <instance> --token <token>
gitea-runner register --no-interactive --instance <instance> --token <token>
```
There are two arguments required, `instance` and `token`.
@@ -69,14 +69,14 @@ If this file is missing or corrupted, you can simply remove it and register agai
Finally, it's time to start the runner:
```bash
./act_runner daemon
gitea-runner daemon
```
And you can see the new runner in the management page:
![view runner](/images/usage/actions/view-runner.png)
You can find more information by visiting [Act runner](act-runner.mdxc).
You can find more information by visiting [Gitea Runner](runner.mdx).
### Use Actions
+53
View File
@@ -0,0 +1,53 @@
---
date: "2023-04-27T15:00:00+08:00"
slug: "runner"
sidebar_position: 20
---
# Gitea Runner
This page will introduce the [Gitea Runner](https://gitea.com/gitea/runner), which is the runner for Gitea Actions.
:::tip
For detailed installation, configuration, and usage instructions, see the [Gitea Runner documentation](/runner/).
:::
## Obtain a registration token
You can register a runner at different levels. It can be:
- Instance level: The runner will run jobs for all repositories in the instance.
- Organization level: The runner will run jobs for all repositories in the organization.
- Repository level: The runner will run jobs for the repository it belongs to.
Note that the repository may still use instance-level or organization-level runners even if it has its own repository-level runners. A future release may provide an option to allow more control over this.
Before registering the runner and running it, you need a registration token. The level of the runner determines where to obtain the registration token.
- Instance level: The admin settings page, like `<your_gitea.com>/-/admin/actions/runners`.
- Organization level: The organization settings page, like `<your_gitea.com>/<org>/settings/actions/runners`.
- Repository level: The repository settings page, like `<your_gitea.com>/<owner>/<repo>/settings/actions/runners`.
If you cannot see the settings page, please make sure that you have the right permissions and that Actions have been enabled.
The format of the registration token is a random string `D0gvfu2iHfUjNqCYVljVyRV14fISpJxxxxxxxxxx`.
A registration token can also be obtained from the Gitea [command-line interface](../../administration/command-line.md#actions-generate-runner-token):
```
gitea --config /etc/gitea/app.ini actions generate-runner-token
```
You can also use `GITEA_RUNNER_REGISTRATION_TOKEN`/`GITEA_RUNNER_REGISTRATION_TOKEN_FILE` environment variables to set a global runner registration token when Gitea starts, for example:
```
openssl rand -hex 24 > /some-dir/runner-token
export GITEA_RUNNER_REGISTRATION_TOKEN_FILE=/some-dir/runner-token
./gitea --config ...
```
The token from the environment is valid until you reset the token (re-create a new one) via the web UI or API.
Tokens are valid for registering multiple runners, until they are revoked and replaced by a new token using the token reset link in the web interface.
Once you have a registration token, follow the [Gitea Runner documentation](/runner/) to install, configure, and run your runner.
+119
View File
@@ -0,0 +1,119 @@
---
date: "2026-06-26T00:00:00+00:00"
slug: "scoped-workflows"
sidebar_position: 60
---
# Scoped Workflows
Scoped workflows let you maintain Actions workflows in one central **source** repository and have them run automatically on many other repositories, without copying the workflow files into each one.
A workflow file committed under a source repository's scoped-workflow directory runs on every repository that the source applies to (a "consuming" repository). Each run executes **in the consuming repository's own context**: its runners, secrets, `GITEA_TOKEN`, and branch, while the workflow **content is read from the source repository**. This is useful for mandating shared CI across an organization or instance: linting, security scans, compliance or policy checks, and similar.
## Levels
A source repository can be registered at two levels:
- **Owner level**: registered by an organization or user. The source's workflows run on every repository owned by that organization or user.
- **Instance level**: registered by a site administrator. The source's workflows run on **every** repository on the instance.
The same repository may be registered at both levels; it is still evaluated once per matching event.
:::note
Instance-level sources apply to **every** repository on the instance, and a required one cannot be opted out. Detection runs on every repository's events. Register them deliberately.
:::
## Configuration
Scoped workflows live in a directory that is separate from regular workflows. It is controlled by `SCOPED_WORKFLOW_DIRS` in the `[actions]` section of `app.ini`:
```ini
[actions]
SCOPED_WORKFLOW_DIRS = .gitea/scoped_workflows
```
- The default is `.gitea/scoped_workflows`.
- It may list multiple directories (comma-separated).
- It **must not overlap** with `WORKFLOW_DIRS` (the regular workflow directories, by default `.gitea/workflows` and `.github/workflows`).
- Leaving it empty means no directory holds scoped workflows, so none are found or run. The settings page still appears and sources can still be registered, but no scoped workflow runs.
Keeping scoped workflows in their own directory means a source repository's *own* Actions are unaffected: only files under `SCOPED_WORKFLOW_DIRS` are treated as scoped workflows.
## Providing scoped workflows from a repository
1. In the would-be source repository, commit your workflow files under the scoped-workflow directory on its **default branch**, for example `.gitea/scoped_workflows/lint.yaml`:
```yaml
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "lint the consuming repository here"
```
2. Register the repository as a source:
- **Organization**: *Organization Settings -> Actions -> Scoped Workflows*
- **User**: *User Settings -> Actions -> Scoped Workflows*
- **Instance (admin)**: *Site Administration -> Actions -> Scoped Workflows*
Search for and add the repository. From then on, its scoped workflows apply to the consuming repositories at that level.
The source repository is within its own scope, so it runs these workflows on itself like any other consumer.
## How scoped workflows run
- The run belongs to the **consuming** repository and uses its runners, secrets, `GITEA_TOKEN`, and ref. It behaves like a normal run there, including rerun, logs, and commit statuses.
- The workflow **content is read from the source** repository, pinned to the source's default-branch commit at the time of the event.
- Detection uses the consuming repository's event, so the workflow's `on:` triggers (such as `push` and `pull_request`) must match that event.
## Opting out
A consuming repository can disable a scoped workflow it does not want, from its **Actions** page (the workflow appears under its source). A workflow that has been marked **required** (see below) can never be disabled or opted out by a consuming repository.
## Required workflows and the merge gate
On the Scoped Workflows settings page you can mark individual workflows as **required** and give each one or more **status-check patterns** (one glob per line). A required scoped workflow:
- Cannot be disabled by consuming repositories.
- Gates pull-request merges: a consuming pull request can only be merged once a commit status matching **every** pattern has **passed** (must-present-and-pass). A required check that never posts a status **blocks** the merge rather than being silently skipped, so disabling Actions on the consumer cannot bypass it.
The status-check context a scoped run posts has the form:
```
<source repo full name>: <workflow display name> / <job> (<event>)
```
The settings page previews these "Expected status checks" for each workflow and marks the ones your patterns match, so you can confirm a pattern is correct. A common pattern wildcards the job and event, for example `my-org/ci-repo: Lint / *`.
Enforcement scope:
- A required check is enforced on any target branch that has a **branch protection rule**, even one whose own status checks are disabled.
- A target branch with **no** protection rule is not gated.
:::warning
Only a workflow that runs on an event that posts a commit status (`push`, `pull_request`, `pull_request_target`, `release`) can be required. A workflow that runs only on events like `workflow_dispatch`, `schedule` or `workflow_call` posts no status, so marking it required would block every consuming pull request forever. The settings page warns you in this case.
:::
## Reusable workflows (`uses:`)
Scoped workflows can call reusable workflows:
- A **local** reference (`uses: ./...` or `uses: $/...`) resolves against the **source** repository: the repository the calling workflow's content came from, not the consuming repository.
- A **cross-repository** reference (`uses: owner/repo/...@ref` or `uses: self:owner/repo/...@ref`) is resolved with the **consuming repository's** read permission. If it points to a private repository, make sure every consuming repository can read it; otherwise the workflow will fail there.
A reusable workflow can live under `SCOPED_WORKFLOW_DIRS` (or `WORKFLOW_DIRS`) of the source repository.
## Security considerations
A source repository's workflow content is executed in every repository it applies to, and its step scripts and their output are written to that repository's Actions logs, readable by anyone who can view the consuming repository's Actions.
- Registering a **private** repository as a source therefore discloses its workflow logic through those logs. Only register repositories whose workflow content may be shared with every consuming repository.
## Limitations
- `on: schedule` and `on: workflow_run` are currently not supported as scoped workflow triggers.
- Scoped workflow content is read from the source's default branch; other branches of the source are not used.
+123
View File
@@ -0,0 +1,123 @@
---
date: "2026-03-19T00:00:00+01:00"
slug: "token-permissions"
sidebar_position: 30
---
# Actions job token permissions (`GITEA_TOKEN`)
Every Actions job receives a built-in token (`GITEA_TOKEN`) which can be used to access Gitea (Git over HTTP(S), API requests, etc.).
This page documents how Gitea decides what the token is allowed to do.
In workflows, it is available as `${{ secrets.GITEA_TOKEN }}`. These settings and `permissions:` only affect `GITEA_TOKEN` (not other secrets like personal access tokens). For API calls, see [API authentication](../../development/api-usage.md#authentication).
## Where permissions come from
Gitea determines the job token permissions in this order:
1. Job-level `permissions:` (`jobs.<job_id>.permissions`)
2. Workflow-level `permissions:` (top-level)
3. Default permissions from settings (owner or repository)
The result is then **clamped** by the configured maximum token permissions (see below).
## Supported workflow syntax
Gitea supports the GitHub Actions-compatible `permissions:` keyword.
### Scalar values
```yaml
permissions: read-all # or: write-all
```
### Scoped mapping
```yaml
permissions:
contents: read
issues: write
pull-requests: none
```
Valid access mode values for each scope are `read`, `write`, and `none`.
### Supported scopes
- `contents` (applies to `code` and `releases`)
- `code`
- `releases`
- `issues`
- `pull-requests`
- `actions`
- `wiki`
- `projects`
- `packages` (if supported by the target feature)
- `id-token` (`write` allows requesting [OpenID Connect tokens](openid-connect.md), `read` grants nothing)
If you specify both `contents` and a more granular scope (like `code` or `releases`), the granular scope wins for that unit.
### Compatibility notes
Gitea supports a subset of GitHub Actions permission scopes.
GitHub-only scopes such as `statuses`, `checks`, `deployments`, `security-events`, and `pages` are not currently supported by Gitea Actions.
Gitea also exposes repository-unit scopes that do not exist as separate scopes in GitHub Actions:
- `code`
- `releases`
- `wiki`
- `projects`
## Default permission mode
If neither the workflow nor the job defines `permissions:`, Gitea uses the configured default mode:
- **Permissive**: read and write permissions for most units in the job's repository (backwards-compatible default).
- **Restricted**: read-only permissions for `code`, `releases`, and `packages` in the job's repository, and no access to other units by default.
Neither mode includes `id-token`.
## Maximum token permissions (clamping)
You can configure a maximum permission per repository unit and for `id-token`.
The job's effective permissions are computed as:
`effective = min(requested, maximum)`
This means workflows can reduce permissions for a job, but cannot exceed your configured maximum.
If you don't configure a maximum, the maximum defaults to `write` for all scopes.
Maximums saved before Gitea supported `id-token` deny it until you set it to `write`.
## Where to configure
You can configure defaults and maximums at:
- **User / Organization**: `Settings` → `Actions` → `General`
- **Repository**: `Settings` → `Actions` → `General`
- For repositories in an organization, the repository can follow the owner-level configuration, or opt out with **Override owner-level configuration**.
Note: Repository-level token permission settings are only shown once **Repository Actions** are enabled.
## Protected branches
Actions job tokens must have code write permission and satisfy [branch protection rules](../access-control/protected-branches.md), including any **Gitea Actions** allowlist requirements.
## Fork pull requests
For security reasons, workflows triggered by pull requests from forks are always restricted to read-only permissions for repository contents, regardless of workflow `permissions:` or settings. They also get no OpenID Connect tokens.
## Cross-repository access
By default, `GITEA_TOKEN` only has access to:
- The job's repository (according to the computed permissions)
- Public repositories (read-only)
Access to other private repositories is denied by default.
A user or organization can allow read-only access to selected private repositories via **Settings → Actions → General → Cross-Repository Access**.
Private repositories can also allow selected collaborative owners via **Settings → Actions → General**.
This allows the private repositories of those owners to read the current private repository for Actions use, such as private actions and reusable workflows.
Fork pull request workflows never gain cross-repository access to private repositories, even if those repositories are listed.
+163 -3
View File
@@ -6,11 +6,171 @@ sidebar_position: 25
# Variables
## Environment variables
These environment variables are set automatically in every workflow run and can be accessed directly (e.g. `$CI` in shell scripts).
| Name | Description | Example |
|---|---|---|
| `CI` | Always set to `true`. | `true` |
| `GITEA_ACTIONS` | Always set to `true`. Useful to distinguish Gitea Actions from other CI systems. | `true` |
| `GITEA_ACTIONS_RUNNER_VERSION` | The version of the runner executing the workflow. | `1.0.8` |
| `GITEA_DOCKER_WORKSPACE` | The workspace path as the Docker daemon sees it, for bind mounts into containers a job starts, e.g. `${GITEA_DOCKER_WORKSPACE:-.}/data:/app/data` in a compose file. Only set for jobs running in a container. | `/var/lib/docker/volumes/GITEA-ACTIONS-TASK-42_***/_data` |
| `GITEA_ENV`<br/>`GITHUB_ENV` | Path to the file that sets environment variables for subsequent steps. | `/home/runner/work/_temp/_runner_file_commands/set_env_***` |
| `GITEA_OUTPUT`<br/>`GITHUB_OUTPUT` | Path to the file that sets step output parameters. | `/home/runner/work/_temp/_runner_file_commands/set_output_***` |
| `GITEA_PATH`<br/>`GITHUB_PATH` | Path to the file that adds system `PATH` entries for subsequent steps. | `/home/runner/work/_temp/_runner_file_commands/add_path_***` |
| `GITEA_STATE`<br/>`GITHUB_STATE` | Path to the file that sets step state variables. | `/home/runner/work/_temp/_runner_file_commands/save_state_***` |
| `GITEA_STEP_SUMMARY`<br/>`GITHUB_STEP_SUMMARY` | Path to the file for writing job summaries. | `/home/runner/work/_temp/_runner_file_commands/step_summary_***` |
| `GITHUB_ACTIONS` | Always set to `true`. | `true` |
| `GITHUB_ACTION` | The name of the action currently running, or the step `id`. | `__run` |
| `GITHUB_ACTION_PATH` | The path where the action is located. | `/home/runner/work/_actions/actions/checkout/v4` |
| `GITHUB_ACTION_REF` | The ref of the action being executed. | `v4` |
| `GITHUB_ACTION_REPOSITORY` | The owner and repository of the action. | `actions/checkout` |
| `GITHUB_ACTOR` | The username of the user that triggered the workflow. | `silverwind` |
| `GITHUB_API_URL` | The URL of the REST API. | `https://gitea.com/api/v1` |
| `GITHUB_BASE_REF` | The target branch of a pull request. | `main` |
| `GITHUB_EVENT_NAME` | The name of the event that triggered the workflow. | `push` |
| `GITHUB_EVENT_PATH` | Path to the file containing the event webhook payload. | `/home/runner/work/_temp/_github_workflow/event.json` |
| `GITHUB_GRAPHQL_URL` | Empty in Gitea (GraphQL is not supported). | _(empty)_ |
| `GITHUB_HEAD_REF` | The source branch of a pull request. | `feature-branch` |
| `GITHUB_JOB` | The `job_id` of the current job. | `build` |
| `GITHUB_REF` | The fully-formed ref that triggered the workflow. | `refs/heads/main` |
| `GITHUB_REF_NAME` | The short ref name. | `main` |
| `GITHUB_REF_TYPE` | The type of ref: `branch` or `tag`. | `branch` |
| `GITHUB_REPOSITORY` | The owner and repository name. | `gitea/docs` |
| `GITHUB_REPOSITORY_OWNER` | The repository owner's username. | `gitea` |
| `GITHUB_RETENTION_DAYS` | The number of days that artifacts are kept, empty when kept forever. | `90` |
| `GITHUB_RUN_ATTEMPT` | The attempt number of the workflow run. | `1` |
| `GITHUB_RUN_ID` | A unique number for each workflow run. | `1234` |
| `GITHUB_RUN_NUMBER` | A unique number for each run of a particular workflow. | `42` |
| `GITHUB_SERVER_URL` | The URL of the Gitea instance. | `https://gitea.com` |
| `GITHUB_SHA` | The commit SHA that triggered the workflow. | `a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2` |
| `GITHUB_WORKFLOW` | The name of the workflow. | `CI` |
| `GITHUB_WORKSPACE` | The default working directory on the runner. | `/workspace/gitea/docs` |
### Runner environment variables
| Name | Description | Example |
|---|---|---|
| `RUNNER_ARCH` | The architecture of the runner. | `X64` |
| `RUNNER_OS` | The operating system of the runner. | `Linux` |
| `RUNNER_TEMP` | Path to a temporary directory on the runner. | `/tmp` |
| `RUNNER_TOOL_CACHE` | Path to the tool cache directory on the runner. | `/opt/hostedtoolcache` |
### Internal environment variables
These are used internally by the runner and actions. They are typically not needed in workflows directly.
| Name | Description | Example |
|---|---|---|
| `ACTIONS_CACHE_URL` | URL for the actions cache service. | `http://192.168.1.10:8088/` |
| `ACTIONS_ID_TOKEN_REQUEST_TOKEN` | Token for OIDC requests. Only set when `id-token: write` is granted. | `***` |
| `ACTIONS_ID_TOKEN_REQUEST_URL` | URL to request OIDC tokens. Only set when `id-token: write` is granted. | `https://gitea.com/api/actions/oidc/token?` |
| `ACTIONS_RESULTS_URL` | URL for storing artifacts. | `https://gitea.com` |
| `ACTIONS_RUNTIME_TOKEN` | Authentication token for the Actions pipeline API. | `***` |
| `ACTIONS_RUNTIME_URL` | URL for the Gitea Actions pipeline API. | `https://gitea.com/api/actions_pipeline/` |
## Context variables
These variables are available in workflow expressions via `${{ gitea.<name> }}`. For compatibility, `${{ github.<name> }}` works as an alias.
| Name | Description | Example |
|---|---|---|
| `gitea.action`<br/>`github.action` | The name of the action currently running, or the `id` of a step. | `__run` |
| `gitea.action_path`<br/>`github.action_path` | The path where an action is located. Only supported in composite actions. | `/home/runner/work/_actions/actions/checkout/v4` |
| `gitea.action_ref`<br/>`github.action_ref` | The ref of the action being executed. | `v4` |
| `gitea.action_repository`<br/>`github.action_repository` | The owner and repository name of the action. | `actions/checkout` |
| `gitea.action_status`<br/>`github.action_status` | The current result of a composite action. | `success` |
| `gitea.actor`<br/>`github.actor` | The username of the user that triggered the initial workflow run. | `silverwind` |
| `gitea.api_url`<br/>`github.api_url` | The URL of the REST API. | `https://gitea.com/api/v1` |
| `gitea.base_ref`<br/>`github.base_ref` | The target branch of a pull request. Only set for `pull_request` and `pull_request_target` events. | `main` |
| `gitea.env`<br/>`github.env` | Path on the runner to the file that sets environment variables from workflow commands. Unique to each step. | `/home/runner/work/_temp/_runner_file_commands/set_env_***` |
| `gitea.event`<br/>`github.event` | The full event webhook payload as an object. See [Event payload](#event-payload). | `{...}` |
| `gitea.event_name`<br/>`github.event_name` | The name of the event that triggered the workflow run. | `push` |
| `gitea.event_path`<br/>`github.event_path` | Path on the runner to the file containing the full event webhook payload. | `/home/runner/work/_temp/_github_workflow/event.json` |
| `gitea.head_ref`<br/>`github.head_ref` | The source branch of a pull request. Only set for `pull_request` and `pull_request_target` events. | `feature-branch` |
| `gitea.job`<br/>`github.job` | The `job_id` of the current job. | `build` |
| `gitea.ref`<br/>`github.ref` | The fully-formed ref that triggered the workflow. | `refs/heads/main` |
| `gitea.ref_name`<br/>`github.ref_name` | The short ref name. | `main` |
| `gitea.ref_protected`<br/>`github.ref_protected` | `true` if branch protections are configured for the ref that triggered the workflow run. | `true` |
| `gitea.ref_type`<br/>`github.ref_type` | The type of ref: `branch` or `tag`. | `branch` |
| `gitea.path`<br/>`github.path` | Path on the runner to the file that sets system `PATH` variables from workflow commands. Unique to each step. | `/home/runner/work/_temp/_runner_file_commands/add_path_***` |
| `gitea.repository`<br/>`github.repository` | The owner and repository name. | `gitea/docs` |
| `gitea.repository_owner`<br/>`github.repository_owner` | The repository owner's username. | `gitea` |
| `gitea.repositoryUrl`<br/>`github.repositoryUrl` | The HTML URL to the repository. | `https://gitea.com/gitea/docs` |
| `gitea.retention_days`<br/>`github.retention_days` | The number of days that artifacts are kept, empty when kept forever. | `90` |
| `gitea.run_id`<br/>`github.run_id` | A unique number for each workflow run within a repository. Does not change on re-run. | `1234` |
| `gitea.run_number`<br/>`github.run_number` | A unique number for each run of a particular workflow. Starts at 1 and increments with each new run. | `42` |
| `gitea.run_attempt`<br/>`github.run_attempt` | A unique number for each re-run attempt. Starts at 1 and increments with each re-run. | `1` |
| `gitea.secret_source`<br/>`github.secret_source` | The source of a secret used in a workflow. Always `Actions` in Gitea. | `Actions` |
| `gitea.server_url`<br/>`github.server_url` | The URL of the Gitea instance. | `https://gitea.com` |
| `gitea.sha`<br/>`github.sha` | The commit SHA that triggered the workflow. | `a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2` |
| `gitea.token`<br/>`github.token` | A token to authenticate on behalf of the Gitea App installed on the repository. See [Token permissions](token-permissions.md). | `ghs_***` |
| `gitea.triggering_actor`<br/>`github.triggering_actor` | The username of the user that initiated the workflow run. May differ from `actor` on re-runs. | `silverwind` |
| `gitea.workflow`<br/>`github.workflow` | The name of the workflow. If unnamed, the full path of the workflow file. | `CI` |
| `gitea.workspace`<br/>`github.workspace` | The default working directory on the runner and the default location of your repository when using the `checkout` action. | `/workspace/gitea/docs` |
| `gitea.gitea_default_actions_url` | The default URL for downloading actions. Gitea-specific. | `https://github.com` |
### Event payload
`gitea.event` is the webhook payload of the event that triggered the run, so which fields exist depends on `gitea.event_name`.
The same payload is written as JSON to the file at `gitea.event_path`.
Payloads use Gitea's webhook format, which is close to GitHub's but not identical. Differences are noted below.
Reading a field that the payload does not have returns an empty value instead of failing, so `${{ gitea.event.pull_request.number }}` is empty on a `push` run.
These fields exist in almost every payload:
| Name | Description | Example |
|---|---|---|
| `gitea.event.action` | The activity type. Only set for events that have activity types, see [supported events](faq.md#what-workflow-trigger-events-does-gitea-support). | `opened` |
| `gitea.event.repository.full_name` | The owner and name of the repository. | `gitea/docs` |
| `gitea.event.repository.default_branch` | The default branch of the repository. | `main` |
| `gitea.event.repository.private` | Whether the repository is private. | `false` |
| `gitea.event.repository.html_url` | The HTML URL of the repository. | `https://gitea.com/gitea/docs` |
| `gitea.event.sender.login` | The username of the user that triggered the event. Also available as `sender.username`. | `silverwind` |
The remaining fields are specific to one or a few events:
| Name | Events | Description | Example |
|---|---|---|---|
| `gitea.event.schedule` | `schedule` | The cron expression that triggered the run. | `*/5 * * * *` |
| `gitea.event.inputs.<name>` | `workflow_dispatch`, `workflow_call` | A raw input value. Prefer `${{ inputs.<name> }}`, which also applies the input's `default`. | `true` |
| `gitea.event.workflow` | `workflow_dispatch` | The file name of the dispatched workflow. | `ci.yaml` |
| `gitea.event.ref` | `push`, `create`, `delete`, `workflow_dispatch` | The ref of the event. Unlike GitHub, `create` and `delete` use the full ref instead of the short name. | `refs/heads/main` |
| `gitea.event.ref_type` | `create`, `delete` | The type of ref: `branch` or `tag`. | `tag` |
| `gitea.event.before`<br/>`gitea.event.after` | `push` | The commit SHA before and after the push. | `a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2` |
| `gitea.event.commits` | `push` | The commits contained in the push, each with `id`, `message`, `url`, `author`, `added`, `removed` and `modified`. | `[{...}]` |
| `gitea.event.head_commit.message` | `push` | The message of the most recent commit of the push. | `fix: broken link` |
| `gitea.event.total_commits` | `push` | The number of commits in the push. Gitea-specific. | `3` |
| `gitea.event.compare_url` | `push` | The URL comparing `before` with `after`. GitHub names this field `compare`. | `https://gitea.com/gitea/docs/compare/a1b2c3d...e5f6a1b` |
| `gitea.event.pusher.login` | `push` | The username of the user that pushed. | `silverwind` |
| `gitea.event.forkee.full_name` | `fork` | The owner and name of the new fork. | `silverwind/docs` |
| `gitea.event.page` | `gollum` | The name of the wiki page. | `Home` |
| `gitea.event.number` | `issues`, `pull_request`, `pull_request_target`, `pull_request_review`, `pull_request_review_comment` | The index of the issue or pull request. Not set for `issue_comment`, use `gitea.event.issue.number` there. | `386` |
| `gitea.event.issue.number`<br/>`gitea.event.issue.title`<br/>`gitea.event.issue.body`<br/>`gitea.event.issue.state`<br/>`gitea.event.issue.labels`<br/>`gitea.event.issue.user.login` | `issues`, `issue_comment` | The issue the event happened on. | `Expand gitea.event in actions docs` |
| `gitea.event.comment.body` | `issue_comment` | The body of the comment. | `LGTM` |
| `gitea.event.is_pull` | `issue_comment` | Whether the comment was made on a pull request. Gitea-specific, GitHub sets `issue.pull_request` on the issue object instead. | `true` |
| `gitea.event.pull_request.number`<br/>`gitea.event.pull_request.title`<br/>`gitea.event.pull_request.body`<br/>`gitea.event.pull_request.draft`<br/>`gitea.event.pull_request.merged`<br/>`gitea.event.pull_request.state`<br/>`gitea.event.pull_request.labels`<br/>`gitea.event.pull_request.user.login` | `pull_request`, `pull_request_target`, `pull_request_review`, `pull_request_review_comment` | The pull request the event happened on. | `Add caching to CI` |
| `gitea.event.pull_request.head.ref`<br/>`gitea.event.pull_request.head.sha`<br/>`gitea.event.pull_request.head.repo.full_name` | `pull_request`, `pull_request_target`, `pull_request_review`, `pull_request_review_comment` | The source branch of the pull request. | `feature-branch` |
| `gitea.event.pull_request.base.ref`<br/>`gitea.event.pull_request.base.sha` | `pull_request`, `pull_request_target`, `pull_request_review`, `pull_request_review_comment` | The target branch of the pull request. | `main` |
| `gitea.event.review.type` | `pull_request_review`, `pull_request_review_comment` | The kind of review: `pull_request_review_approved`, `pull_request_review_rejected` or `pull_request_review_comment`. GitHub uses `review.state` with the values `approved`, `changes_requested` and `commented`. | `pull_request_review_approved` |
| `gitea.event.review.content` | `pull_request_review`, `pull_request_review_comment` | The body of the review. GitHub names this field `review.body`. | `Ship it` |
| `gitea.event.changes.title.from`<br/>`gitea.event.changes.body.from` | `issues`, `issue_comment`, `pull_request` | The previous value. Only set when `action` is `edited`. | `Old title` |
| `gitea.event.release.tag_name`<br/>`gitea.event.release.name`<br/>`gitea.event.release.body`<br/>`gitea.event.release.draft`<br/>`gitea.event.release.prerelease` | `release` | The release the event happened on. | `v1.2.3` |
| `gitea.event.package.name`<br/>`gitea.event.package.type`<br/>`gitea.event.package.version` | `registry_package` | The package the event happened on. | `gitea` |
| `gitea.event.workflow_run.id`<br/>`gitea.event.workflow_run.event`<br/>`gitea.event.workflow_run.status`<br/>`gitea.event.workflow_run.conclusion`<br/>`gitea.event.workflow_run.head_branch`<br/>`gitea.event.workflow_run.head_sha` | `workflow_run` | The workflow run that the event reports on. | `success` |
`schedule` runs have no webhook of their own. Their payload is the payload of the push that registered the schedule, with `schedule`, `repository`, `sender` and, for organization-owned repositories, `organization` filled in.
Only those fields are meaningful, and `sender.login` is always `gitea-actions`.
## User-defined variables
You can create configuration variables on the user, organization and repository level.
The level of the variable depends on where you created it. When creating a variable, the
key will be converted to uppercase. You need use uppercase on the yaml file.
## Naming conventions
### Naming conventions
The following rules apply to variable names:
@@ -21,12 +181,12 @@ The following rules apply to variable names:
- Variable names must be unique at the level they are created at.
- Variable names must not start with `CI`.
## Using variable
### Using variables
After creating configuration variables, they will be automatically filled in the `vars` context.
They can be accessed through expressions like `${{ vars.VARIABLE_NAME }}` in the workflow.
## Precedence
### Precedence
If a variable with the same name exists at multiple levels, the variable at the lowest level takes precedence:
A repository variable will always be chosen over an organization/user variable.
+15 -12
View File
@@ -19,30 +19,33 @@ Git version 2.29 or higher is required on the server side for this to work.
## Creating PRs with AGit
AGit allows to create PRs while pushing code to the remote repo.
This can be done by pushing to the branch followed by a specific refspec (a location identifier known to git).
This can be done by pushing to a special refspec (a location identifier known to git) instead of to a branch.
The following example illustrates this:
```shell
git push origin HEAD:refs/for/main
git push origin HEAD:refs/for/main -o topic="topic_of_my_PR"
```
The command has the following structure:
- `HEAD`: The target branch
- `origin`: The target repository (not a fork!)
- `HEAD`: The local branch containing the changes you are proposing
- `refs/<for|draft|for-review>/<branch>`: The target PR type and configuration
- `for`: Create a normal PR with `<branch>` as the target branch
- `draft`/`for-review`: Currently ignored silently
- `<branch>/`: The branch you want your changes to be merged into
- `-o <topic|title|description>`: Options for the PR
- `topic`: The topic of this change. It will become the name of the branch holding the changes waiting for review. This is REQUIRED to trigger a pull request.
```shell
git push <remote> <local-rev>:refs/for/<branch>[/<topic>] [-o <option>[=<value>] ...]
```
- `<remote>`: The remote pointing at the target repository (not a fork!), `origin` in the example above
- `<local-rev>`: The local branch or commit containing the changes you are proposing, `HEAD` in the example above
- `refs/for/<branch>`: The target PR type and configuration
- `for`: Create a normal PR with `<branch>` as the target branch. This is the only prefix supported at the moment, `refs/draft/...` and `refs/for-review/...` are reserved for future use and do not create a PR.
- `<branch>`: The branch you want your changes to be merged into
- `<topic>`: Optional, an alternative to `-o topic=<topic>`. The push is rejected with `topic-branch is not set` if the topic is given in neither place.
- `-o <option>[=<value>]`: Options for the PR
- `topic`: The topic of this change. It will become the name of the branch holding the changes waiting for review (prefixed with your user name). This is REQUIRED to trigger a pull request, unless it is already part of the refspec.
- `title`: The PR title (optional but recommended), only used for topics not already having an associated PR.
- `description`: The PR description (optional but recommended), only used for topics not already having an associated PR.
- `force-push=true`: Specifies whether to force-update the target branch.
- Note: omitting the value and using just `-o force-push` will also work.
Here's another advanced example for creating a new PR targeting `main` with `topic`, `title`, and `description`:
Here's another example for creating a new PR targeting `main` with `topic`, `title`, and `description`:
```shell
git push origin HEAD:refs/for/main -o topic="topic_of_my_PR" -o title="Title of the PR" -o description="# The PR Description\nThis can be **any** markdown content.\n- [x] Ok"
@@ -15,7 +15,7 @@ creating issues and pull requests. This will cut down on the initial back and fo
of getting some clarifying details.
It is currently not possible to provide generic issue/pull-request templates globally.
Additionally, the New Issue page URL can be suffixed with `?title=Issue+Title&body=Issue+Text` and the form will be populated with those strings. Those strings will be used instead of the template if there is one.
Additionally, the New Issue page URL can be suffixed with `?title=Issue+Title&body=Issue+Text` and the form will be populated with those strings. Those strings will be used instead of the template if there is one. See [Pre-filling Issues and Pull Requests](prefill-issues-pull-requests.md) for all parameters.
## File names
@@ -100,6 +100,8 @@ about: "This template is for testing!"
title: "[TEST] "
ref: "main"
assignees: ["user1"]
projects:
- Example Project
labels:
- bug
@@ -112,8 +114,9 @@ This is the template!
In the above example, when a user is presented with the list of issues they can submit, this would show as `Template Name` with the description
`This template is for testing!`. When submitting an issue with the above example, the issue title would be pre-populated with
`[TEST] ` while the issue body would be pre-populated with `This is the template!`.
`[TEST] ` while the issue body would be pre-populated with `This is the template!`.
The issue would be assigned to `user1`.
The issue would be assigned to the project `Example Project`.
The issue would also be assigned two labels,
`bug` and `help needed`, and the issue will have a reference to `main`.
@@ -12,6 +12,7 @@ aliases:
Possible file names for PR default merge message templates:
- `.gitea/default_merge_message/DEFAULT_TEMPLATE.md`: the default message template for all merge styles if they don't have their own templates.
- `.gitea/default_merge_message/MERGE_TEMPLATE.md`
- `.gitea/default_merge_message/REBASE_TEMPLATE.md`
- `.gitea/default_merge_message/REBASE-MERGE_TEMPLATE.md`
@@ -0,0 +1,42 @@
---
date: "2026-10-17T00:00:00+00:00"
slug: "prefill-issues-pull-requests"
sidebar_position: 14
---
# Pre-filling Issues and Pull Requests
Links to the pages for creating issues and pull requests can pre-fill the form with query parameters.
This lets you link users from another app, a README or a project board to a form that is already categorized.
- New issue: `/{owner}/{repo}/issues/new?…`
- New pull request: `/{owner}/{repo}/compare/{base}...{head}?…`
For example, this link opens a new issue with a title, two labels and an assignee:
```
https://gitea.example.com/owner/repo/issues/new?title=Dashboard+crashes&label=kind/bug,area/dashboard&assignee=alice
```
## Parameters
| Parameter | Value |
| ------------- | --------------------------------------------------------------------------- |
| `title` | Title |
| `body` | Description |
| `label` | Comma-separated label IDs or names |
| `labels` | Alias of `label` |
| `milestone` | Milestone ID or name |
| `project` | Comma-separated project IDs or titles |
| `assignee` | Comma-separated user IDs or usernames |
| `template` | File name of the [template](issue-pull-request-templates.md) to use |
| `field:<id>` | Value of the field with this `id` in a YAML template |
IDs and names can be mixed and names are matched case-insensitively. Values that don't match anything in the repository are ignored.
Labels include the organization's labels, and closed milestones and projects can be selected too.
Milestones and projects are only offered to users who can write to issues or pull requests, so for other users these parameters have no effect.
The values from the link take precedence over the title, description, labels and assignees of the template.
When there are several issue templates to choose from, the parameters are passed through to the chosen one.
On the compare page, any of these parameters also opens the pull request form directly, as `expand=1` does.
+16
View File
@@ -55,6 +55,22 @@ WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP]
The first value of the list will be used in helpers.
## Default pull request title
When opening a new pull request, Gitea pre-fills the title field. The source of that title is controlled by the `DEFAULT_TITLE_SOURCE` setting in `app.ini`:
```ini
[repository.pull-request]
DEFAULT_TITLE_SOURCE = first-commit
```
Two modes are available:
- **`first-commit`** (default): The title is taken from the summary line of the oldest commit in the branch. This applies regardless of how many commits are included in the PR.
- **`auto`**: When the PR contains a single commit, its summary line is used as the title (same as `first-commit` for one commit). When the PR contains multiple commits, Gitea converts the branch name into a human-readable sentence: dashes, underscores, and `camelCase` word boundaries are replaced with spaces, and the first letter is capitalized.
Example: branch name `fix-user-login-flow` with multiple commits produces the title `Fix user login flow` under `auto`, but would use the oldest commit's message under `first-commit`.
## Pull Request Templates
You can find more information about pull request templates at the page [Issue and Pull Request templates](issue-pull-request-templates.md).
+2 -2
View File
@@ -18,7 +18,7 @@ To register the package registry you need to configure a new Conan remote:
```shell
conan remote add {remote} https://gitea.example.com/api/packages/{owner}/conan
conan user --remote {remote} --password {password} {username}
conan remote login {remote} {username} --password {password}
```
| Parameter | Description |
@@ -32,7 +32,7 @@ For example:
```shell
conan remote add gitea https://gitea.example.com/api/packages/testuser/conan
conan user --remote gitea --password password123 testuser
conan remote login gitea testuser --password password123
```
## Publish a package
+1
View File
@@ -35,6 +35,7 @@ The following package managers are currently supported:
| [RPM](usage/packages/rpm.md) | - | `yum`, `dnf`, `zypper` |
| [RubyGems](usage/packages/rubygems.md) | Ruby | `gem`, `Bundler` |
| [Swift](usage/packages/swift.md) | Swift | `swift` |
| [Terraform](usage/packages/terraform.md) | - | `terraform` |
| [Vagrant](usage/packages/vagrant.md) | - | `vagrant` |
**The following paragraphs only apply if Packages are not globally disabled!**
+99
View File
@@ -0,0 +1,99 @@
---
date: "2026-03-04T00:00:00+00:00"
slug: "terraform"
sidebar_position: 118
---
# Terraform State Registry
Publish terraform states to sync it between multiple users or CI system.
## Requirements
To work with the Terraform State registry, you need to use [Terraform](https://www.terraform.io/) or [OpenTofu](https://opentofu.org/).
## Configuring the package registry
To use the Gitea Terraform State registry, you need to configure the `http` backend in your Terraform configuration.
```hcl
terraform {
backend "http" {
address = "https://gitea.example.com/api/packages/{owner}/terraform/state/{name}"
lock_address = "https://gitea.example.com/api/packages/{owner}/terraform/state/{name}/lock"
unlock_address = "https://gitea.example.com/api/packages/{owner}/terraform/state/{name}/lock"
lock_method = "POST"
unlock_method = "DELETE"
username = "{username}"
password = "{password_or_token}"
}
}
```
| Placeholder | Description |
| ----------- | ----------- |
| `owner` | The owner of the state (user or organization). |
| `name` | The name of the state. |
| `username` | Your Gitea username. |
| `password` | Your Gitea password or [personal access token](development/api-usage.md#authentication). |
If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
## Initialize the backend
After configuring the backend, you can initialize it with:
```shell
terraform init
```
Terraform will prompt you to migrate your state if you already have one locally.
## State Locking
Gitea supports state locking to prevent concurrent modifications. The `lock_address` and `unlock_address` should point to the `/lock` sub-route of your state URL.
- **Locking**: Performed via a `POST` request to `{address}/lock`.
- **Unlocking**: Performed via a `DELETE` request to `{address}/lock`.
Terraform handles these requests automatically when configured as shown above.
## Encrypted state
The state registry supports [encrypted state](https://opentofu.org/docs/language/state/encryption/).
## State Versions and Management
Gitea keeps track of your Terraform state versions. You can use the API to retrieve or delete specific versions.
### Fetch state
To fetch the latest version of a state:
```shell
curl --user {username}:{password_or_token} \
https://gitea.example.com/api/packages/{owner}/terraform/state/{name}
```
To fetch a specific version by its serial number:
```shell
curl --user {username}:{password_or_token} \
https://gitea.example.com/api/packages/{owner}/terraform/state/{name}/versions/{serial}
```
### Delete state
To delete the entire state and all its versions:
```shell
curl --user {username}:{password_or_token} -X DELETE \
https://gitea.example.com/api/packages/{owner}/terraform/state/{name}
```
To delete a specific version by its serial number:
```shell
curl --user {username}:{password_or_token} -X DELETE \
https://gitea.example.com/api/packages/{owner}/terraform/state/{name}/versions/{serial}
```
+27
View File
@@ -39,6 +39,9 @@ docs/(aws|google|azure)/[^/]*\\.(md|txt) @user8 @org1/team4
!/assets/.*\\.(bin|exe|msi) @user9
```
Code owners listed in this file will automatically be requested to review pull requests
that modify files matching at least one corresponding rule.
### Escaping
You can escape characters `#`, ` ` (space) and `\` with `\`, like:
@@ -55,3 +58,27 @@ Some character (`.+*?()|[]{}^$\`) should be escaped with `\\` inside regexp, lik
path/\\.with\\.dots
path/with\\+plus
```
### Branch Protection Rules
When setting up branch protection rules, you may choose to enforce code owner approval of
modified files. This will block a PR from being merged until at least one code owner
has given approval for every applicable rule listed in the `CODEOWNERS` file.
For example, say you have the following `CODEOWNERS` file:
```bash
.*\\.go @Bob
.*\\.md @Sally @Chris
migrations/.* @Alice
```
This means that:
- If your PR modifies any `.go` files, it will require approval from Bob.
- If your PR modifies any `.md` files, it will require approval from _either_ Sally _or_ Chris.
- If your PR modifies any file in the `migrations` directory, it will require approval from Alice.
These rules are composable. So, for example, if your PR modifies some `.go` files, as well as
some `.md` files, this means it will require approval from Bob, in addition to approval from
one of either Sally or Chris.
+27
View File
@@ -76,6 +76,33 @@ It will be rendered with issue titles to:
* the other issue title (#456)
```
## Theme-based image display
Gitea supports the GitHub-like theme-based image display. Supported syntax:
* Use Markdown image
```
![My-Light](my-light.png#gh-light-mode-only)![My-Dark](my-dark.png#gh-dark-mode-only)
```
* Use `<img>` HTML tag
```
<img src="my-light.png#gh-light-mode-only" height="120" width="120"/>
<img src="my-dark.png#gh-dark-mode-only" height="120" width="120"/>
```
* Use `<picture>` with `<source media>` (only works for themes with "auto" color preference)
```
<picture>
<source media="(prefers-color-scheme: dark)" srcset="my-dark.png">
<source media="(prefers-color-scheme: light)" srcset="my-light.png">
<img src="my-light.png">
</picture>
```
## Math expressions
Gitea supports GitHub-like math expression formatting.
@@ -37,6 +37,16 @@ a/b/c/d.json
**.[bB][aA][tT]
```
Gitea also supports to use sections to exclude some files:
```
[expand]
*.md
[exclude]
*.log
```
## Variable Expansion
In any file matched by the above globs, the variables below will be expanded.
+679 -137
View File
@@ -9,11 +9,26 @@ aliases:
# Webhooks
Gitea supports webhooks for repository events. This can be configured in the settings
page `/:username/:reponame/settings/hooks` by a repository admin. Webhooks can also be configured on a per-organization and whole system basis.
All event pushes are POST requests. The methods currently supported are:
Gitea can send outbound webhooks for repository activity. Repository webhooks are
configured at `/:username/:reponame/settings/hooks` by a repository admin.
Equivalent webhook pages also exist for organizations, users, and system
administration.
- Gitea (can also be a GET request)
Webhook configuration is available at four scopes:
- `Repository webhooks`: Trigger only for activity in one repository.
- `Organization webhooks`: Trigger for activity in repositories owned by that
organization.
- `User webhooks`: Trigger for activity in repositories owned by that user.
- `System webhooks`: Trigger for all eligible activity on the instance.
Gitea also supports admin-defined `default webhooks`. These are not an extra
delivery scope. Instead, they are copied into newly created repositories and
then behave like ordinary repository webhooks.
Gitea supports these outgoing webhook integrations:
- Gitea
- Gogs
- Slack
- Discord
@@ -21,170 +36,697 @@ All event pushes are POST requests. The methods currently supported are:
- Telegram
- Microsoft Teams
- Feishu
- Matrix
- Wechatwork
- Packagist
### Event information
The `Gitea` and `Gogs` webhook types send generic webhook payloads. The chat and
service integrations listed above transform the same internal event into a
service-specific request body.
:::warning
The `secret` field in the payload is deprecated as of Gitea 1.13.0 and will be removed in 1.14.0: https://github.com/go-gitea/gitea/issues/11755
## Configuration
This section covers the webhook settings you choose when creating or editing a
webhook.
### Configuring a webhook
When creating a webhook, the main options are:
- `Target URL`: The endpoint that receives the delivery.
- `HTTP Method`: Usually `POST` for generic webhooks.
- `POST Content Type`: `application/json` or
`application/x-www-form-urlencoded` for generic webhooks.
- `Secret`: Used to sign the raw request body with HMAC.
- `Authorization Header`: Optional custom `Authorization` header to send with
each request.
- `Branch Filter`: Optional glob filter for branch and tag related events.
- `Trigger On`: `Push Events`, `All Events`, or a custom event selection.
- `Active`: Whether the webhook is enabled.
:::note
Older examples may still show a `secret` field inside the JSON payload. Current
Gitea versions do not send the webhook secret in the payload body. Always verify
the request by checking the signature headers instead.
:::
The following is an example of event information that will be sent by Gitea to
a Payload URL:
### Branch filters
The branch filter uses glob syntax compatible with
[`github.com/gobwas/glob`](https://pkg.go.dev/github.com/gobwas/glob#Compile).
- Empty, `*`, or `**` matches everything.
- A plain branch name such as `main` matches that branch.
- Full refs such as `refs/tags/v*` are also supported.
- Brace expressions such as `{main,release/*}` are supported.
- The filter only applies to events that carry a git ref, such as `create`,
`delete`, and `push`.
- Events without a ref, such as issues or releases, ignore the branch filter.
Examples:
- `main`
- `{main,feature/*}`
- `{refs/heads/feature/*,refs/tags/release/*}`
### Authorization header
Gitea can be configured to send a custom
[Authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization)
with each webhook delivery. This is independent from the webhook secret:
- Use the secret to verify integrity with HMAC.
- Use the `Authorization` header when the receiving endpoint requires
application-level authentication.
## Delivery
This section describes how Gitea sends webhook deliveries and how receivers can
identify and verify them.
### Delivery behavior
- Webhooks are delivered asynchronously over HTTP.
- Generic `Gitea` and `Gogs` webhooks support `POST` and `GET`; `POST` is the
normal choice.
- For `POST` requests, the payload can be sent either as JSON
(`application/json`) or as a form field named `payload`
(`application/x-www-form-urlencoded`).
- Provider-specific integrations may use the HTTP method and body format
required by that provider.
### Delivery headers
Every delivery includes a unique delivery ID and event headers. For
GitHub-compatible integrations, Gitea also sends the corresponding GitHub and
Gogs header names.
| Header | Description |
| --- | --- |
| `X-Gitea-Delivery` | Unique delivery UUID for this attempt. |
| `X-Gitea-Event` | Normalized event name, such as `push`, `issues`, or `pull_request`. |
| `X-Gitea-Event-Type` | More specific event type, such as `issue_assign` or `pull_request_review_comment`. |
| `X-Gitea-Signature` | Hex-encoded HMAC-SHA256 of the raw request body, without a prefix. |
| `X-Gitea-Hook-Installation-Target-Type` | Where the webhook is defined: typically `repository`, `organization`, `user`, or `system`. Default webhooks are copied into repositories before delivery, so they are typically delivered as `repository`. |
| `X-Gogs-Delivery`, `X-Gogs-Event`, `X-Gogs-Event-Type`, `X-Gogs-Signature` | Compatibility headers with the same values as the Gitea variants. |
| `X-GitHub-Delivery`, `X-GitHub-Event`, `X-GitHub-Event-Type` | GitHub-style compatibility headers. |
| `X-GitHub-Hook-Installation-Target-Type` | GitHub-style compatibility header for the webhook scope. |
| `X-Hub-Signature` | GitHub-compatible HMAC-SHA1 header in the form `sha1=<digest>`. |
| `X-Hub-Signature-256` | GitHub-compatible HMAC-SHA256 header in the form `sha256=<digest>`. |
If no secret is configured, the signature headers are still present, but their
digest values are empty.
#### `Event` versus `Event-Type`
Some Gitea webhook subscriptions are grouped together under one normalized event
name. For example, an issue assignment delivery uses the issue event group:
```http
X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
X-GitHub-Event: push
X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
X-Gogs-Event: push
X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
X-Gitea-Event: push
X-Gitea-Event: issues
X-Gitea-Event-Type: issue_assign
X-GitHub-Event: issues
X-GitHub-Event-Type: issue_assign
```
```json
{
"secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3",
"ref": "refs/heads/develop",
"before": "28e1879d029cb852e4844d9c718537df08844e03",
"after": "bffeb74224043ba2feb48d137756c8a9331c449a",
"compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a",
"commits": [
{
"id": "bffeb74224043ba2feb48d137756c8a9331c449a",
"message": "Webhooks Yay!",
"url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a",
"author": {
"name": "Gitea",
"email": "someone@gitea.io",
"username": "gitea"
},
"committer": {
"name": "Gitea",
"email": "someone@gitea.io",
"username": "gitea"
},
"timestamp": "2017-03-13T13:52:11-04:00"
}
],
"repository": {
"id": 140,
"owner": {
"id": 1,
"login": "gitea",
"full_name": "Gitea",
"email": "someone@gitea.io",
"avatar_url": "https://localhost:3000/avatars/1",
"username": "gitea"
},
"name": "webhooks",
"full_name": "gitea/webhooks",
"description": "",
"private": false,
"fork": false,
"html_url": "http://localhost:3000/gitea/webhooks",
"ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git",
"clone_url": "http://localhost:3000/gitea/webhooks.git",
"website": "",
"stars_count": 0,
"forks_count": 1,
"watchers_count": 1,
"open_issues_count": 7,
"default_branch": "master",
"created_at": "2017-02-26T04:29:06-05:00",
"updated_at": "2017-03-13T13:51:58-04:00"
},
"pusher": {
"id": 1,
"login": "gitea",
"full_name": "Gitea",
"email": "someone@gitea.io",
"avatar_url": "https://localhost:3000/avatars/1",
"username": "gitea"
},
"sender": {
"id": 1,
"login": "gitea",
"full_name": "Gitea",
"email": "someone@gitea.io",
"avatar_url": "https://localhost:3000/avatars/1",
"username": "gitea"
}
}
```
Use `X-Gitea-Event-Type` when you need the exact trigger that fired the webhook.
### Example
#### Validating deliveries
This is an example of how to use webhooks to run a php script upon push requests to the repository.
In your repository Settings, under Webhooks, Setup a Gitea webhook as follows:
Gitea signs the raw request body with your webhook secret. To validate a
delivery:
- Target URL: http://mydomain.com/webhook.php
- HTTP Method: POST
- POST Content Type: application/json
- Secret: 123
- Trigger On: Push Events
- Active: Checked
1. Read the request body exactly as it was received.
2. Compute the HMAC-SHA256 digest with your webhook secret.
3. Compare the result with `X-Gitea-Signature` or with the GitHub-compatible
`X-Hub-Signature-256` header.
4. Use a constant-time comparison when possible.
Now on your server create the php file webhook.php
Important details:
- `X-Gitea-Signature` contains only the lowercase hexadecimal SHA-256 digest.
- `X-Hub-Signature-256` contains the same digest with a `sha256=` prefix.
- `X-Hub-Signature` is also sent for compatibility and uses SHA-1.
- The body must be verified before JSON parsing or any other modification.
##### PHP example
The following example verifies a generic `Gitea` webhook sent as
`application/json`.
```php
<?php
$secret_key = '123';
$secret = '123';
// check for POST request
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
error_log('FAILED - not POST - '. $_SERVER['REQUEST_METHOD']);
exit();
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Only POST is allowed');
}
// get content type
$content_type = isset($_SERVER['CONTENT_TYPE']) ? strtolower(trim($_SERVER['CONTENT_TYPE'])) : '';
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_GITEA_SIGNATURE'] ?? '';
if ($content_type != 'application/json') {
error_log('FAILED - not application/json - '. $content_type);
exit();
if ($payload === false || $signature === '') {
http_response_code(400);
exit('Missing payload or signature');
}
// get payload
$payload = trim(file_get_contents("php://input"));
$expected = hash_hmac('sha256', $payload, $secret);
if (empty($payload)) {
error_log('FAILED - no payload');
exit();
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
// get header signature
$header_signature = isset($_SERVER['HTTP_X_GITEA_SIGNATURE']) ? $_SERVER['HTTP_X_GITEA_SIGNATURE'] : '';
$event = $_SERVER['HTTP_X_GITEA_EVENT'] ?? '';
$eventType = $_SERVER['HTTP_X_GITEA_EVENT_TYPE'] ?? '';
$data = json_decode($payload, true);
if (empty($header_signature)) {
error_log('FAILED - header signature missing');
exit();
if (!is_array($data)) {
http_response_code(400);
exit('Invalid JSON payload');
}
// calculate payload signature
$payload_signature = hash_hmac('sha256', $payload, $secret_key, false);
// check payload signature against header signature
if ($header_signature !== $payload_signature) {
error_log('FAILED - payload signature');
exit();
}
// convert json to array
$decoded = json_decode($payload, true);
// check for json decode errors
if (json_last_error() !== JSON_ERROR_NONE) {
error_log('FAILED - json decode - '. json_last_error());
exit();
}
// success, do something
http_response_code(204);
```
There is a Test Delivery button in the webhook settings that allows to test the configuration as well as a list of the most Recent Deliveries.
## Events
### Authorization header
This section follows the same event-by-event style used by GitHub's webhook
documentation: each event describes when it occurs and what the top-level
payload contains.
**With 1.19**, Gitea hooks can be configured to send an [authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) to the webhook target.
The event groups match the webhook settings UI: `Repository Events`,
`Issue Events`, `Pull Request Events`, and `Workflow Events`.
### Repository Events
- `create`, `delete`, `fork`, `push`, `wiki`, `repository`, `release`, `package`, `status`
#### `create`
This event occurs when a branch or tag is created.
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `sha` | `string` | **Required.** The object ID of the created reference. |
| `ref` | `string` | **Required.** The created branch or tag name. |
| `ref_type` | `string` | **Required.** The reference type, such as `branch` or `tag`. |
| `repository` | `object` | **Required.** The repository where the reference was created. |
| `sender` | `object` | **Required.** The user who created the reference. |
#### `delete`
This event occurs when a branch or tag is deleted.
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `ref` | `string` | **Required.** The deleted branch or tag name. |
| `ref_type` | `string` | **Required.** The reference type, such as `branch` or `tag`. |
| `pusher_type` | `string` | **Required.** The actor type that deleted the ref. Current Gitea payloads use `user`. |
| `repository` | `object` | **Required.** The repository where the reference was deleted. |
| `sender` | `object` | **Required.** The user who deleted the reference. |
#### `fork`
This event occurs when a repository is forked.
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `forkee` | `object` | **Required.** The newly created fork repository. |
| `repository` | `object` | **Required.** The original repository that was forked. |
| `sender` | `object` | **Required.** The user who created the fork. |
#### `push`
This event occurs when commits are pushed to a branch or tag.
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `ref` | `string` | **Required.** The full pushed ref, such as `refs/heads/main`. |
| `before` | `string` | **Required.** The commit SHA before the push. |
| `after` | `string` | **Required.** The commit SHA after the push. |
| `compare_url` | `string` | **Required.** URL to compare `before` and `after`. |
| `commits` | `array` | **Required.** Commits included in the push. |
| `total_commits` | `integer` | **Required.** Number of commits in the push. |
| `head_commit` | `object` | The most recent commit in the push. |
| `repository` | `object` | **Required.** The repository that received the push. |
| `pusher` | `object` | **Required.** The user who performed the push. |
| `sender` | `object` | **Required.** The user who triggered the webhook. |
#### `wiki`
This event occurs when a wiki page is created, edited, or deleted.
**Action type:** `created`, `edited`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The wiki page action. |
| `repository` | `object` | **Required.** The repository that owns the wiki. |
| `sender` | `object` | **Required.** The user who changed the wiki page. |
| `page` | `string` | **Required.** The wiki page name. |
| `comment` | `string` | The wiki commit message or comment. |
#### `repository`
This event occurs when a repository is created or deleted.
**Action type:** `created`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The repository action. |
| `repository` | `object` | **Required.** The repository that was created or deleted. |
| `organization` | `object` | Present when the repository belongs to an organization. |
| `sender` | `object` | **Required.** The user who performed the action. |
#### `release`
This event occurs when a release is published, updated, or deleted.
**Action type:** `published`, `updated`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The release action. |
| `release` | `object` | **Required.** The release that was acted on. |
| `repository` | `object` | **Required.** The repository containing the release. |
| `sender` | `object` | **Required.** The user who performed the action. |
#### `package`
This event occurs when a package is created or deleted.
**Action type:** `created`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The package action. |
| `repository` | `object` | The repository associated with the package, when applicable. |
| `package` | `object` | **Required.** The package that was acted on. |
| `organization` | `object` | Present when the package owner is an organization. |
| `sender` | `object` | **Required.** The user who performed the action. |
#### `status`
This event occurs when a commit status is created or updated through the API.
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `commit` | `object` | The commit associated with the status. |
| `context` | `string` | **Required.** The status context, such as `ci/build`. |
| `created_at` | `string` | **Required.** The time the status was created. |
| `description` | `string` | Status description text. |
| `id` | `integer` | **Required.** The status identifier. |
| `repository` | `object` | **Required.** The repository containing the commit. |
| `sender` | `object` | **Required.** The user who created the status. |
| `sha` | `string` | **Required.** The commit SHA. |
| `state` | `string` | **Required.** The state, such as `pending`, `success`, `error`, or `failure`. |
| `target_url` | `string` | Target URL associated with the status. |
| `updated_at` | `string` | The time the status was last updated. |
Unlike most other payloads, this event does not use an `action` field. The
state transition is represented by `state`.
### Issue Events
- `issues`, `issue_assign`, `issue_label`, `issue_milestone`, `issue_comment`
#### `issues`
This event occurs when an issue is opened, closed, reopened, edited, or deleted.
**Action type:** `opened`, `closed`, `reopened`, `edited`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The issue action. |
| `number` | `integer` | **Required.** The issue number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `issue` | `object` | **Required.** The issue that was acted on. |
| `repository` | `object` | **Required.** The repository containing the issue. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the issue action, if applicable. |
#### `issue_assign`
This event occurs when an issue is assigned or unassigned.
**Action type:** `assigned`, `unassigned`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The assignment action. |
| `number` | `integer` | **Required.** The issue number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `issue` | `object` | **Required.** The issue that was acted on. |
| `repository` | `object` | **Required.** The repository containing the issue. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the issue action, if applicable. |
#### `issue_label`
This event occurs when issue labels are updated or cleared.
**Action type:** `label_updated`, `label_cleared`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The label update action. |
| `number` | `integer` | **Required.** The issue number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `issue` | `object` | **Required.** The issue that was acted on. |
| `repository` | `object` | **Required.** The repository containing the issue. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the issue action, if applicable. |
#### `issue_milestone`
This event occurs when an issue is milestoned or demilestoned.
**Action type:** `milestoned`, `demilestoned`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The milestone action. |
| `number` | `integer` | **Required.** The issue number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `issue` | `object` | **Required.** The issue that was acted on. |
| `repository` | `object` | **Required.** The repository containing the issue. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the issue action, if applicable. |
#### `issue_comment`
This event occurs when a comment on an issue is created, edited, or deleted.
**Action type:** `created`, `edited`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The comment action. |
| `issue` | `object` | **Required.** The issue that the comment belongs to. |
| `pull_request` | `object` | Present only when the comment is on a pull request timeline. |
| `comment` | `object` | **Required.** The comment that was created, edited, or deleted. |
| `changes` | `object` | Optional. Previous comment body when the action is `edited`. |
| `repository` | `object` | **Required.** The repository containing the issue. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `is_pull` | `boolean` | **Required.** Whether the comment is on a pull request timeline. |
### Pull Request Events
- `pull_request`, `pull_request_assign`, `pull_request_label`, `pull_request_milestone`, `pull_request_comment`, `pull_request_review`, `pull_request_review_approved`, `pull_request_review_rejected`, `pull_request_review_comment`, `pull_request_sync`, `pull_request_review_request`
#### `pull_request`
This event occurs when a pull request is opened, closed, reopened, edited, or deleted.
**Action type:** `opened`, `closed`, `reopened`, `edited`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The pull request action. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was acted on. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the pull request action, if applicable. |
| `review` | `object` | Present for pull request review events. |
#### `pull_request_assign`
This event occurs when a pull request is assigned or unassigned.
**Action type:** `assigned`, `unassigned`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The assignment action. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was acted on. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the pull request action, if applicable. |
| `review` | `object` | Present for pull request review events. |
#### `pull_request_label`
This event occurs when pull request labels are updated or cleared.
**Action type:** `label_updated`, `label_cleared`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The label update action. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was acted on. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the pull request action, if applicable. |
| `review` | `object` | Present for pull request review events. |
#### `pull_request_milestone`
This event occurs when a pull request is milestoned or demilestoned.
**Action type:** `milestoned`, `demilestoned`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The milestone action. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was acted on. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the pull request action, if applicable. |
| `review` | `object` | Present for pull request review events. |
#### `pull_request_comment`
This event occurs when a timeline comment on a pull request is created, edited, or deleted.
**Action type:** `created`, `edited`, `deleted`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The comment action. |
| `issue` | `object` | **Required.** The related issue record for the pull request. |
| `pull_request` | `object` | **Required.** The pull request the timeline comment belongs to. |
| `comment` | `object` | **Required.** The comment that was created, edited, or deleted. |
| `changes` | `object` | Optional. Previous comment body when the action is `edited`. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `is_pull` | `boolean` | **Required.** Always `true` for this event. |
#### `pull_request_review`
This is a subscription-only umbrella event in the webhook settings UI.
It does not have its own delivery payload. When selected, Gitea delivers the
more specific events `pull_request_review_approved`,
`pull_request_review_rejected`, and `pull_request_review_comment`.
#### `pull_request_review_approved`
This event occurs when a pull request review is submitted with approval.
**Action type:** `reviewed`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** Always `reviewed`. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was reviewed. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who submitted the review. |
| `commit_id` | `string` | The commit SHA associated with the review event, if applicable. |
| `review` | `object` | **Required.** The review payload. For this event, `review.type` is `approved`. |
#### `pull_request_review_rejected`
This event occurs when a pull request review is submitted with a rejection or a
request for changes.
**Action type:** `reviewed`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** Always `reviewed`. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was reviewed. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who submitted the review. |
| `commit_id` | `string` | The commit SHA associated with the review event, if applicable. |
| `review` | `object` | **Required.** The review payload. For this event, `review.type` is `rejected`. |
#### `pull_request_review_comment`
This event occurs when a pull request review is submitted as a comment.
**Action type:** `reviewed`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** Always `reviewed`. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was reviewed. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who submitted the review. |
| `commit_id` | `string` | The commit SHA associated with the review event, if applicable. |
| `review` | `object` | **Required.** The review payload. For this event, `review.type` is `comment`. |
#### `pull_request_sync`
This event occurs when a pull request is synchronized after new commits are pushed.
**Action type:** `synchronized`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** Always `synchronized`. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was synchronized. |
| `requested_reviewer` | `object` | Present for review request events. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who performed the synchronization. |
| `commit_id` | `string` | The commit SHA associated with the synchronization event, if applicable. |
| `review` | `object` | Present for pull request review events. |
#### `pull_request_review_request`
This event occurs when a reviewer is requested or a review request is removed.
**Action type:** `review_requested`, `review_request_removed`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The review request action. |
| `number` | `integer` | **Required.** The pull request number. |
| `changes` | `object` | Optional. Previous values for edited fields or label deltas. |
| `pull_request` | `object` | **Required.** The pull request that was acted on. |
| `requested_reviewer` | `object` | The reviewer that was requested or removed. |
| `repository` | `object` | **Required.** The repository containing the pull request. |
| `sender` | `object` | **Required.** The user who performed the action. |
| `commit_id` | `string` | The commit SHA associated with the pull request action, if applicable. |
| `review` | `object` | Present for pull request review events. |
### Workflow Events
- `workflow_run`, `workflow_job`
#### `workflow_run`
This event occurs when a Gitea Actions workflow run changes status.
**Action type:** `queued`, `waiting`, `in_progress`, `completed`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The workflow run status transition. |
| `workflow` | `object` | **Required.** The workflow definition. |
| `workflow_run` | `object` | **Required.** The workflow run that was acted on. |
| `pull_request` | `object` | Present when the workflow run is associated with a pull request. |
| `organization` | `object` | Present when the repository owner is an organization. |
| `repository` | `object` | **Required.** The repository containing the workflow. |
| `sender` | `object` | **Required.** The user who triggered the workflow run update. |
#### `workflow_job`
This event occurs when a Gitea Actions workflow job changes status.
**Action type:** `queued`, `waiting`, `in_progress`, `completed`
##### Payload parameters
| Name | Type | Description |
| --- | --- | --- |
| `action` | `string` | **Required.** The workflow job status transition. |
| `workflow_job` | `object` | **Required.** The workflow job that was acted on. |
| `pull_request` | `object` | Present when the workflow job is associated with a pull request. |
| `organization` | `object` | Present when the repository owner is an organization. |
| `repository` | `object` | **Required.** The repository containing the workflow job. |
| `sender` | `object` | **Required.** The user who triggered the workflow job update. |
## Testing, recent deliveries, and replay
Each webhook page includes:
- `Test Delivery`, which sends a synthetic `push` event for the repository.
- `Recent Deliveries`, which shows request and response details.
- `Redelivery`, which replays an earlier webhook delivery.
If the repository has no commits yet, the test delivery uses a generated fake
commit so the webhook can still be exercised.
## Administration notes
Administrators can further control webhook delivery with instance settings such
as host allow lists, delivery timeouts, and cleanup policies. See the
[Webhook section of the configuration cheat sheet](../../administration/config-cheat-sheet.md#webhook-webhook).
-496
View File
@@ -1,496 +0,0 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
import { themes as prismThemes } from "prism-react-renderer";
const lightCodeTheme = prismThemes.github;
const darkCodeTheme = prismThemes.dracula;
// order usage directory by type first
function sortItemsByCategory(items) {
// type with "category" (directory) first
const sortedItems = items.sort(function (a, b) {
return a.type.localeCompare(b.type);
});
return sortedItems;
}
const renderApiSSR = process.env.API_SSR !== "false";
const apiConfig = [
"redocusaurus",
{
// Plugin Options for loading OpenAPI files
specs: renderApiSSR
? [
{
route: "/api/next/",
spec: "static/swagger-latest.json",
},
{
route: "/api/",
spec: "static/swagger-25.json",
},
{
route: "/api/1.25/",
spec: "static/swagger-25.json",
},
{
route: "/api/1.24/",
spec: "static/swagger-24.json",
},
{
route: "/api/1.23/",
spec: "static/swagger-23.json",
},
{
route: "/api/1.22/",
spec: "static/swagger-22.json",
},
]
: [],
// Theme Options for modifying how redoc renders them
theme: {
// Change with your site colors
primaryColor: "#1890ff",
},
},
];
const pageConfig = renderApiSSR
? {
exclude: ["api/**"],
}
: {};
const globalVariables = {
"current": {
goVersion: "1.25",
minGoVersion: "1.25",
minNodeVersion: "22",
version: "main-nightly",
sourceVersion: "main",
sourceBranch: "main",
dockerVersion: "nightly",
displayVersion: "1.26-dev",
},
"1.25": {
goVersion: "1.25",
minGoVersion: "1.25",
minNodeVersion: "22",
version: "1.25.4",
sourceVersion: "v1.25.0",
sourceBranch: "release/v1.25",
dockerVersion: "1.25.4",
displayVersion: "1.25.4",
},
"1.24": {
goVersion: "1.24",
minGoVersion: "1.24",
minNodeVersion: "22",
version: "1.24.7",
sourceVersion: "v1.24.0",
sourceBranch: "release/v1.24",
dockerVersion: "1.24.7",
displayVersion: "1.24.7",
},
"1.23": {
goVersion: "1.23",
minGoVersion: "1.22",
minNodeVersion: "18",
version: "1.23.8",
sourceVersion: "v1.23.8",
sourceBranch: "release/v1.23",
dockerVersion: "1.23.8",
displayVersion: "1.23.8",
},
"1.22": {
goVersion: "1.22",
minGoVersion: "1.22",
minNodeVersion: "18",
version: "1.22.6",
sourceVersion: "v1.22.6",
sourceBranch: "release/v1.22",
dockerVersion: "1.22.6",
displayVersion: "1.22.6",
},
};
const versions = {
"current": {
label: globalVariables["current"].displayVersion, // path is kept as next for dev (so users can always find "nightly" docs)
banner: "unreleased",
},
"1.25": {
label: globalVariables["1.25"].displayVersion,
},
"1.24": {
label: globalVariables["1.24"].displayVersion,
},
"1.23": {
label: globalVariables["1.23"].displayVersion,
},
"1.22": {
label: globalVariables["1.22"].displayVersion,
},
};
/** @type {import('@docusaurus/types').Config} */
const config = {
title: "Gitea Documentation",
tagline: "Git with a cup of tea",
url: "https://docs.gitea.com",
baseUrl: "/",
onBrokenLinks: "warn",
favicon: "img/favicon.png",
future: {
experimental_faster: true,
v4: true
},
plugins: [
[
"docusaurus-plugin-plausible",
{
domain: "docs.gitea.com",
},
],
// for runner documentations
[
"@docusaurus/plugin-content-docs",
{
id: "runner-docs",
path: "runner-docs",
routeBasePath: "runner",
//sidebarPath: './runner/sidebars.js',
versions: {
current: {
label: "main",
banner: "unreleased",
},
"0.2.11": {
path: "0.2.11",
label: "0.2.11",
},
},
lastVersion: "0.2.11",
editUrl: ({
versionDocsDirPath,
docPath,
locale,
version,
permalink,
}) => {
return `https://gitea.com/gitea/docs/src/branch/main/${
version === "current"
? "runner-docs"
: `runner-docs_versioned_docs/version-${version}`
}/${docPath}`;
},
async sidebarItemsGenerator({ defaultSidebarItemsGenerator, ...args }) {
const { item } = args;
// Use the provided data to generate a custom sidebar slice
const sidebarItems = await defaultSidebarItemsGenerator(args);
if (item.dirName !== "usage") {
return sidebarItems;
} else {
return sortItemsByCategory(sidebarItems);
}
},
},
],
],
i18n: {
defaultLocale: "en-us",
locales: ["en-us", "zh-cn", "zh-tw"],
localeConfigs: {
"en-us": {
label: "English",
},
"zh-cn": {
label: "简体中文",
},
"zh-tw": {
label: "繁體中文",
},
},
},
presets: [
[
"@docusaurus/preset-classic",
//'classic',
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve("./sidebars.js"),
routeBasePath: "/", // Serve the docs at the site's root
editUrl: ({
versionDocsDirPath,
docPath,
locale,
version,
permalink,
}) => {
// Special case for awesome page
if (docPath.includes("awesome.md")) {
return `https://gitea.com/gitea/awesome-gitea/src/branch/main/README.md`;
}
if (locale === "en-us") {
return `https://gitea.com/gitea/docs/src/branch/main/${
version === "current"
? "docs"
: `versioned_docs/version-${version}`
}/${docPath}`;
}
return `https://gitea.com/gitea/docs/src/branch/main/i18n/${locale}/docusaurus-plugin-content-docs/${
version === "current" ? "current" : `version-${version}`
}/${docPath}`;
},
versions: versions,
lastVersion: "1.25",
async sidebarItemsGenerator({
defaultSidebarItemsGenerator,
...args
}) {
const { item } = args;
// Use the provided data to generate a custom sidebar slice
const sidebarItems = await defaultSidebarItemsGenerator(args);
if (item.dirName !== "usage") {
return sidebarItems;
} else {
return sortItemsByCategory(sidebarItems);
}
},
},
blog: false,
theme: {
customCss: require.resolve("./src/css/custom.css"),
},
pages: pageConfig,
gtag: {
trackingID: "G-KHM0KYT506",
},
}),
],
apiConfig,
],
markdown: {
hooks: {
onBrokenMarkdownLinks: "warn",
},
preprocessor: ({ filePath, fileContent }) => {
var key = "";
var found = false;
for (key in globalVariables) {
let folderName = key == "current" ? "current" : `version-${key}`;
if (filePath.includes(`/${folderName}/`)) {
found = true;
break;
}
}
if (key == "" || !found) {
key = "current";
}
let content = fileContent;
for (const variable in globalVariables[key]) {
content = content.replaceAll(
"@" + variable + "@",
globalVariables[key][variable]
);
}
return content;
},
},
themes: [
[
"@easyops-cn/docusaurus-search-local",
{
hashed: false,
language: ["en", "zh"],
highlightSearchTermsOnTargetPage: true,
explicitSearchResultPath: true,
indexBlog: false,
docsRouteBasePath: "/",
},
],
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
image: '/img/gitea.svg',
metadata: [
{
name: 'og:logo',
content: '/img/gitea.svg'
},
{
name: "keywords",
content:
"gitea, git, devops, actions, packages, documentation, self-hosted, open-source, version control, gitlab, github",
},
],
colorMode: {
defaultMode: "light",
disableSwitch: false,
respectPrefersColorScheme: true,
},
announcementBar: {
id: "announcementBar-4", // Increment on change
content: `<a href="https://about.gitea.com/products/cloud">Try &nbsp; Gitea Cloud &nbsp; ☁️ &nbsp; for 30 days <span aria-hidden="true">&rarr;</span> Accelerate your Development & Deploys!</a>`,
},
navbar: {
title: "Gitea",
logo: {
alt: "Gitea Logo",
src: "img/gitea.svg",
href: "https://about.gitea.com/",
target: "_self",
},
items: [
{
type: "doc",
docId: "index",
position: "left",
label: "Docs",
},
{
to: "/api/1.25/",
label: "API",
position: "left",
activeBaseRegex: "api/(1.22|1.23|1.24|1.25|next)/",
},
{
to: "/runner/0.2.11/",
label: "Runner",
position: "left",
activeBaseRegex: "runner/(0.2.11|next)/",
},
{
position: "left",
label: "Enterprise",
href: "https://docs.gitea.com/enterprise",
className: "internal-href",
target: "_self",
},
{
type: "search",
position: "right",
},
{
type: "localeDropdown",
position: "right",
},
{
type: "docsVersionDropdown",
position: "right",
dropdownActiveClassDisabled: true,
},
{
type: "custom-Dropdown",
label: "API Version",
position: "right",
items: [
{ to: "/api/next/", label: "1.26-dev" },
{ to: "/api/1.25/", label: "1.25.4" },
{ to: "/api/1.24/", label: "1.24.7" },
{ to: "/api/1.23/", label: "1.23.8" },
{ to: "/api/1.22/", label: "1.22.6" },
],
routerRgx: "/api/",
classNames: "api-dropdown",
},
{
type: "custom-Dropdown",
label: "Runner Version",
position: "right",
items: [
{ to: "/runner/next/", label: "development" },
{ to: "/runner/0.2.11/", label: "0.2.11" },
],
routerRgx: "/runner/",
classNames: "runner-dropdown",
},
{
to: "help/support",
position: "right",
label: "Support",
activeBaseRegex: "help/support",
},
{
href: "https://gitea.com/user/login",
label: "Sign In",
position: "right",
className: "internal-href signin-button",
target: "_self",
},
],
},
footer: {
style: "dark",
links: [
{
title: "Community",
items: [
{
label: "Awesome Gitea",
href: "https://gitea.com/gitea/awesome-gitea",
},
{
label: "Stack Overflow",
href: "https://stackoverflow.com/questions/tagged/gitea",
},
{
label: "Discord",
href: "https://discord.gg/gitea",
},
{
label: "Forum",
href: "https://forum.gitea.com/",
},
{
label: "Twitter",
href: "https://twitter.com/giteaio",
},
{
label: "Mastodon",
href: "https://social.gitea.io/@gitea",
},
{
label: "Bluesky",
href: "https://bsky.app/profile/gitea.com",
},
],
},
{
title: "Code",
items: [
{
label: "GitHub",
href: "https://github.com/go-gitea/gitea",
},
{
label: "Gitea",
href: "https://gitea.com/gitea",
},
{
label: "Tea CLI",
href: "https://gitea.com/gitea/tea",
},
],
},
],
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: ["ini", "diff", "json", "http", "docker", "php"],
},
}),
};
module.exports = config;
@@ -1,8 +0,0 @@
{
"sidebar.docs.category.actions": {
"message": "Actions"
},
"sidebar.docs.category.packages": {
"message": "Packages"
}
}
-8
View File
@@ -1,8 +0,0 @@
{
"outdated.message": {
"message": "当前中文文档翻译不是最新版,访问英文版本查看最新内容,或"
},
"outdated.help": {
"message": "帮助我们翻译"
}
}
@@ -2,8 +2,9 @@
date: "2023-05-23T09:00:00+08:00"
slug: adding-legal-pages
sidebar_position: 110
aliases:
- /zh-tw/adding-legal-pages
- /zh-cn/adding-legal-pages
---
# 添加法律页面
@@ -12,10 +13,10 @@ aliases:
## 获取页面
Gitea 源代码附带了示例页面,位于 `contrib/legal` 目录中。将它们复制到 `custom/public/assets/` 目录下。例如,如果要添加隐私政策:
Gitea 源代码附带了示例页面,位于 `contrib/service/sample-page` 目录中。将它们复制到 `custom/public/assets/` 目录下。例如,如果要添加隐私政策:
```
wget -O /path/to/custom/public/assets/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
wget -O /path/to/custom/public/assets/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/service/sample-page/privacy.html.sample
```
现在,你需要编辑该页面以满足你的需求。特别是,你必须更改电子邮件地址、网址以及与 "Your Gitea Instance" 相关的引用,以匹配你的情况。
@@ -80,7 +80,7 @@ cd gitea-dump-1610949662
mv app.ini /etc/gitea/conf/app.ini
mv data/* /var/lib/gitea/data/
mv log/* /var/lib/gitea/log/
mv repos/* /var/lib/gitea/repositories/
mv repos/* /var/lib/gitea/data/gitea-repositories/
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea
# mysql
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,547 @@
---
date: "2017-04-15T14:56:00+02:00"
slug: "customizing-gitea"
sidebar_position: 100
aliases:
- /zh-cn/customizing-gitea
---
# 自定义 Gitea
自定义 Gitea 通常通过 `CustomPath` 目录完成。默认情况下,它是工作目录(WorkPath)下的
`custom` 目录,但如果您的[安装方式](../installation/from-binary.md)做了不同设置,也可能位于其他位置。
这是覆盖配置项、模板等内容的核心位置。您可以通过 `gitea help` 查看 `CustomPath`,也可以在
_站点管理_ 页面的 _Configuration_ 选项卡中找到该路径。您还可以通过设置 `GITEA_CUSTOM`
环境变量,或在 `gitea` 二进制上使用 `--custom-path` 选项来覆盖 `CustomPath`。
(命令行选项会覆盖环境变量。)
如果 Gitea 以二进制方式部署,所有默认路径都相对于 Gitea 二进制文件。
如果通过发行版安装,这些路径通常会按照 Linux 文件系统标准进行调整。Gitea 会尝试创建所需目录,
包括 `custom/`。某些发行版可能会通过 `/etc/gitea/` 为 `custom` 提供一个符号链接。
应用配置可以在 `CustomConf` 文件中找到,默认路径为 `$GITEA_CUSTOM/conf/app.ini`,
但如果您的[安装方式](../installation/from-binary.md)修改了配置,也可能位于其他位置。
同样,您可以通过 `gitea help` 查看该变量,也可以使用 `gitea` 二进制的 `--config` 选项覆盖它。
- [快速备忘单](../administration/config-cheat-sheet.md)
- [完整配置清单](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
如果在检查 `gitea help` 后仍找不到 `CustomPath` 目录,请检查 `GITEA_CUSTOM` 环境变量;
它可以用来将默认路径覆盖为其他位置。例如,`GITEA_CUSTOM` 可能由 init 脚本设置。
您也可以在站点管理页面的 “Configuration” 选项卡下检查该值是否已设置。
- [环境变量清单](../administration/environment-variables.md)
:::note
Gitea 必须执行完整重启后,配置更改才会生效。
:::
## 提供自定义公共文件
要让 Gitea 提供自定义公共文件(例如页面和图片),请将 `$GITEA_CUSTOM/public/`
目录作为 webroot。Gitea 会跟随符号链接。
当前仅提供以下文件:
- `public/robots.txt`
- `public/.well-known/` 目录中的文件
- `public/assets/` 目录中的文件
例如,存放在 `$GITEA_CUSTOM/public/assets/` 中的 `image.png` 文件,可以通过
`http://gitea.domain.tld/assets/image.png` 访问。
## 修改 Logo
如果要构建自定义 logo 和/或 favicon,请克隆 Gitea 源码仓库,替换 `assets/logo.svg`
和/或 `assets/favicon.svg`,然后运行 `make generate-images`。`assets/favicon.svg`
仅用于 favicon。执行后会更新以下输出文件,随后您可以将它们放到服务器上的
`$GITEA_CUSTOM/public/assets/img` 中:
- `public/assets/img/logo.svg` - 用于站点图标、应用图标
- `public/assets/img/logo.png` - 用于 Open Graph
- `public/assets/img/avatar_default.png` - 用作默认头像图片
- `public/assets/img/apple-touch-icon.png` - 用于 iOS 设备书签
- `public/assets/img/favicon.svg` - 用于 favicon
- `public/assets/img/favicon.png` - 用作不支持 SVG favicon 的浏览器回退图标
如果源图片不是矢量格式,您可以尝试使用诸如[这个工具](https://www.aconvert.com/image/png-to-svg/)
将光栅图像转换为矢量图。
## 自定义 Gitea 页面和资源
Gitea 可执行文件内置了运行所需的全部资源:模板、图片、样式表和翻译。您可以在 `custom`
目录下放置与原路径一致的替换文件来覆盖其中任意资源。例如,要替换 C++ 仓库默认提供的
`.gitignore`,我们需要替换 `options/gitignore/C++`。为此,您必须将替换文件放到
`$GITEA_CUSTOM/options/gitignore/C++`(`CustomPath` 目录位置见本文开头说明)。
Gitea 的每一个页面都可以修改。动态内容通过 [go template](https://pkg.go.dev/html/template)
生成,您可以通过在 `$GITEA_CUSTOM/templates` 目录下放置替换文件进行修改。
要获取任意内嵌文件(包括模板),可以使用[`gitea embedded` 工具](../administration/cmd-embedded.md)。
另外,也可以在 Gitea 源码仓库的 [`templates`](https://github.com/go-gitea/gitea/tree/main/templates)
目录中找到它们。(注意:示例链接指向 `main` 分支,请确保所使用的模板与您当前的发布版本兼容。)
请注意,任何包含在 `{{` 和 `}}` 中的语句都是 Gitea 的模板语法,
如果您没有完全理解这些组件,就不应修改它们。
### 自定义首页 / 主页
将与您所使用 Gitea 版本对应的 [`home.tmpl`](https://github.com/go-gitea/gitea/blob/main/templates/home.tmpl)
从 `templates` 目录复制到 `$GITEA_CUSTOM/templates`。
随后按您的需要编辑即可。
不要忘记重启 Gitea 以应用更改。
### 添加链接和页签
如果您只是想为顶部导航栏或页脚添加额外链接,或者为仓库视图添加额外页签,
可以将它们分别放入 `$GITEA_CUSTOM/templates/custom/` 目录中的
`extra_links.tmpl`(添加到导航栏的链接)、`extra_links_footer.tmpl`
(添加到页脚左侧的链接)和 `extra_tabs.tmpl`。
例如,假设您在德国,需要添加法律上通常要求提供的 “Impressum”/关于页面,用来说明谁对站点内容负责:
只需将该页面放到 `$GITEA_CUSTOM/public/assets/` 目录中
(例如 `$GITEA_CUSTOM/public/assets/impressum.html`),再在
`$GITEA_CUSTOM/templates/custom/extra_links.tmpl` 或
`$GITEA_CUSTOM/templates/custom/extra_links_footer.tmpl` 中加入指向它的链接即可。
为了匹配当前样式,该链接应使用类名 `item`,并且您可以使用 `{{AppSubUrl}}` 获取基础 URL:
`<a class="item" href="{{AppSubUrl}}/assets/impressum.html">Impressum</a>`
更多信息请参见[添加法律页面](../administration/adding-legal-pages.md)。
您也可以用同样的方式添加新页签,将其放入 `extra_tabs.tmpl` 中。
与其他页签样式匹配所需的精确 HTML 位于文件 `templates/repo/header.tmpl`
([GitHub 源码](https://github.com/go-gitea/gitea/blob/main/templates/repo/header.tmpl))。
### 页面中的其他插入内容
除了 `extra_links.tmpl` 和 `extra_tabs.tmpl` 之外,您还可以在
`$GITEA_CUSTOM/templates/custom/` 目录中放置其他有用的模板:
- `header.tmpl`,位于 `<head>` 结束标签之前,例如可用于添加自定义 CSS 文件。
- `body_outer_pre.tmpl`,位于 `<body>` 起始标签之后。
- `body_inner_pre.tmpl`,位于顶部导航栏之前,但已处于主容器 `<div class="full height">` 内部。
- `body_inner_post.tmpl`,位于主容器结束之前。
- `body_outer_post.tmpl`,位于底部 `<footer>` 元素之前。
- `footer.tmpl`,位于 `<body>` 结束标签之前,是放置额外 JavaScript 的合适位置。
### 使用 Gitea 变量
您可以在自定义模板中使用各种 Gitea 变量。
首先,_临时_ 启用开发模式:在 `app.ini` 中将 `RUN_MODE = prod` 改为 `RUN_MODE = dev`。
然后在任意模板中添加 `{{ $ | DumpVar }}`,重启 Gitea 并刷新对应页面;
这样会输出所有可用变量。
找到所需数据后,使用对应变量即可;例如,如果您需要仓库名称,可以使用 `{{.Repository.Name}}`。
如果您需要对这些数据做一些转换,而您又不熟悉 Go,一种简单的变通办法是先将数据放入 DOM,
再添加一小段 JavaScript 脚本来处理它。
### 示例:PlantUML
您可以通过 PlantUML 服务器为 Gitea 的 Markdown 添加 [PlantUML](https://plantuml.com/) 支持。
数据会被编码后发送到 PlantUML 服务器,再由服务器生成图片。官方在
http://www.plantuml.com/plantuml 提供了一个在线演示服务器,但如果您(或您的用户)拥有敏感数据,
则可以改为自建一个 [PlantUML 服务器](https://plantuml.com/server)。要启用 PlantUML 渲染,
请从 https://gitea.com/davidsvantesson/plantuml-code-highlight 复制 JavaScript 文件,
并将其放入 `$GITEA_CUSTOM/public/assets/` 目录。然后将以下内容添加到 `$GITEA_CUSTOM/templates/custom/footer.tmpl`:
```html
<script>
$(async () => {
if (!$('.language-plantuml').length) return;
await Promise.all([
$.getScript('https://your-gitea-server.com/assets/deflate.js'),
$.getScript('https://your-gitea-server.com/assets/encode.js'),
$.getScript('https://your-gitea-server.com/assets/plantuml_codeblock_parse.js'),
]);
// Replace call with address to your plantuml server
parsePlantumlCodeBlocks("https://www.plantuml.com/plantuml");
});
</script>
```
随后,您就可以在 Markdown 中添加如下代码块:
```plantuml
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
Alice -> Bob: Another authentication Request
Alice <-- Bob: Another authentication Response
```
该脚本会检测 `class="language-plantuml"` 的标签,不过您也可以通过为
`parsePlantumlCodeBlocks` 提供第二个参数来修改这一行为。
### 示例:使用 Online 3D Viewer 预览 CAD 文件
您可以在自己的 Gitea 实例中实现 CAD 文件预览。这个实现使用的是
[`Online 3D Viewer`](https://github.com/kovacsv/Online3DViewer)。
支持以下 3D 文件格式:
`3dm`, `3ds`, `3mf`, `amf`, `bim`, `brep`, `dae`, `fbx`, `fcstd`, `glb`,
`gltf`, `ifc`, `igs`, `iges`, `stp`, `step`, `stl`, `obj`, `off`, `ply`, `wrl`
(`.gltf` 文件仅支持 v2)
#### 第 1 部分:添加模板
我们需要在 `$GITEA_CUSTOM` 中添加模板。
该模板需要保存到 `$GITEA_CUSTOM/templates/custom/` 中。
在这里创建 `footer.tmpl` 文件,并向其中添加以下内容:
```
nano $GITEA_CUSTOM/templates/custom/footer.tmpl
```
```html
<script>
function onPageChange() {
// Supported 3D file types
const fileTypes = ['3dm', '3ds', '3mf', 'amf', 'bim', 'brep', 'dae', 'fbx', 'fcstd', 'glb', 'gltf', 'ifc', 'igs', 'iges', 'stp', 'step', 'stl', 'obj', 'off', 'ply', 'wrl'];
// Select matching link
const links = Array.from(document.querySelectorAll('a.ui.mini.basic.button'));
const link3D = links.find(link => {
const href = link.href.toLowerCase();
return href.includes('/raw/') && fileTypes.some(ext => href.endsWith(`.${ext}`));
});
if (link3D) {
const existingScript = document.querySelector('script[src="/assets/o3dv/o3dv.min.js"]');
const initializeViewer = () => {
const fileUrl = link3D.getAttribute('href');
const fileView = document.querySelector('.file-view');
if (!fileView) return;
// Remove only the old viewer container if it exists
const oldView3D = document.getElementById('view-3d');
if (oldView3D) {
oldView3D.remove(); // safely remove old viewer container div
} else {
// No #view-3d, so remove all children inside .file-view
while (fileView.firstChild) {
fileView.removeChild(fileView.firstChild);
}
}
// Create a new container for the viewer
const newView3D = document.createElement('div');
newView3D.id = 'view-3d';
newView3D.style.padding = '0';
newView3D.style.margin = '0';
newView3D.style.flexGrow = '1';
newView3D.style.minHeight = '0';
newView3D.style.width = '100%';
const header = document.querySelector('header');
const headerHeight = header ? header.offsetHeight : 0;
newView3D.style.height = `calc(100vh - ${headerHeight}px)`;
// Append the new container inside fileView
fileView.appendChild(newView3D);
const parentDiv = document.getElementById('view-3d');
if (parentDiv) {
const viewer = new OV.EmbeddedViewer(parentDiv, {
backgroundColor: new OV.RGBAColor(59, 68, 76, 0),
defaultColor: new OV.RGBColor(200, 200, 200),
edgeSettings: new OV.EdgeSettings(false, new OV.RGBColor(0, 0, 0), 1),
environmentSettings: new OV.EnvironmentSettings([
'/assets/o3dv/envmaps/fishermans_bastion/negx.jpg',
'/assets/o3dv/envmaps/fishermans_bastion/posx.jpg',
'/assets/o3dv/envmaps/fishermans_bastion/posy.jpg',
'/assets/o3dv/envmaps/fishermans_bastion/negy.jpg',
'/assets/o3dv/envmaps/fishermans_bastion/posz.jpg',
'/assets/o3dv/envmaps/fishermans_bastion/negz.jpg'
], false)
});
viewer.LoadModelFromUrlList([fileUrl]);
}
};
if (typeof OV === 'undefined') {
if (!existingScript) {
const script = document.createElement('script');
script.onload = initializeViewer;
script.src = '/assets/o3dv/o3dv.min.js';
document.head.appendChild(script);
} else {
// Script is loading but OV not yet ready — wait for it
existingScript.addEventListener('load', initializeViewer);
}
} else {
// OV already loaded
initializeViewer();
}
}
};
// Run when the page is fully loaded
document.addEventListener('DOMContentLoaded', onPageChange);
const targetSelector = 'a.ui.mini.basic.button[href*="/raw/"]';
let lastHref = null;
let timeoutId = null;
const checkAndRun = () => {
const rawLink = document.querySelector(targetSelector);
if (!rawLink) return;
const currentHref = rawLink.getAttribute('href');
if (currentHref !== lastHref) {
lastHref = currentHref;
const fileName = currentHref.split('/').pop();
console.log('New Raw file link detected after delay:', fileName);
onPageChange();
}
};
const observer = new MutationObserver(() => {
// Delay execution by 300ms after last mutation
clearTimeout(timeoutId);
timeoutId = setTimeout(checkAndRun, 300);
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
</script>
```
#### 第 2 部分:添加公共文件
现在我们需要下载最新版本的 O3DV。进入 `$GITEA_CUSTOM/public/assets/`。
使用以下命令创建目录(并进入该目录):
```
mkdir o3dv
cd o3dv
```
从 [`GitHub`](https://github.com/kovacsv/Online3DViewer/releases) 复制最新发行版压缩包链接
(当前示例版本为 v0.18.0)。
然后使用例如 wget 或 curl 下载该文件:
```
wget https://github.com/kovacsv/Online3DViewer/releases/download/0.18.0/o3dv.zip
```
或者
```
curl -L -O https://github.com/kovacsv/Online3DViewer/releases/download/0.18.0/o3dv.zip
```
再使用例如 unzip 解压归档文件:
```
unzip o3dv.zip
```
#### 第 3 部分:目录权限
最后一步,修改 public 目录权限:
```
chown -R git:git $GITEA_CUSTOM/public
```
现在一切就绪!重启您的 Gitea 实例以应用这些更改,并在浏览器中进行测试。
简单检查一下。最终目录结构应类似如下:
```
$GITEA_CUSTOM/templates
-- custom
`-- footer.tmpl
$GITEA_CUSTOM/public/assets/
-- o3dv
|-- o3dv.zip
|-- o3dv.license.md
|-- o3dv.min.js
|-- envmaps
\...
```
## 自定义 Gitea 邮件
`$GITEA_CUSTOM/templates/mail` 目录允许您修改 Gitea 每一种邮件的正文。
可被覆盖的模板可以在 Gitea 源码的
[`templates/mail`](https://github.com/go-gitea/gitea/tree/main/templates/mail)
目录中找到。
覆盖方式是将对应文件复制到 `$GITEA_CUSTOM/templates/mail` 下,
并保持与源码一致的完整路径结构。
任何包含在 `{{` 和 `}}` 中的语句都是 Gitea 的模板语法,
如果您没有完全理解这些组件,就不应修改它们。
## 为 Gitea 添加统计分析
Google Analytics、Matomo(原 Piwik)以及其他分析服务都可以集成到 Gitea。
要添加跟踪代码,请参考本文的“页面中的其他插入内容”一节,
并将相应 JavaScript 添加到 `$GITEA_CUSTOM/templates/custom/header.tmpl` 文件中。
## 自定义 gitignores、labels、licenses、locales 和 readmes
将自定义文件放入 `custom/options` 下对应的子目录中。
:::note
这些文件不应带有扩展名,例如应使用 `Labels`,而不是 `Labels.txt`
:::
### gitignores
要添加自定义 `.gitignore`,请在 `$GITEA_CUSTOM/options/gitignore` 中添加一个文件,
文件内容遵循现有的 [.gitignore 规则](https://git-scm.com/docs/gitignore)。
## 自定义 git 配置
从 Gitea 1.20 开始,您可以通过 `git.config` 区块自定义 git 配置。
### 启用签名 git push
[签名推送](https://git-scm.com/docs/git-push#Documentation/git-push.txt---signedtruefalseif-asked)
允许客户端对 push 操作本身进行加密签名(而不仅仅是对单个提交签名)。
要启用签名推送,请将以下内容添加到 `app.ini`:
```ini
[git.config]
receive.certNonceSeed = <randomstring>
```
`certNonceSeed` 应设置为一个随机字符串并妥善保密。它用于生成防重放 nonce。
Gitea 默认已经设置了 `receive.advertisePushOptions = true`,因此无需额外配置。
请注意,Gitea 不会读取 `/etc/gitconfig`,因此必须像上面这样通过 `app.ini` 设置该选项。
在客户端侧,可以通过 `git push --signed` 进行签名推送,
或者使用 `git config --global push.gpgSign if-asked` 永久启用。
### Labels
从 Gitea 1.19 开始,您可以向 `$GITEA_CUSTOM/options/label` 中添加一个遵循
[YAML 标签格式](https://github.com/go-gitea/gitea/blob/main/options/label/Advanced.yaml)
的文件:
```yaml
labels:
- name: "foo/bar" # 下拉列表中显示的标签名称
exclusive: true # 是否为作用域标签使用互斥命名空间,作用域分隔符为 /
color: aabbcc # 十六进制颜色值
description: Some label # 标签用途的详细描述
```
旧的[传统文件格式](https://github.com/go-gitea/gitea/blob/main/options/label/Default)
仍可使用,格式如下,但我们强烈建议改用新的 YAML 格式。
`#hex-color label name ; label description`
更多信息请参阅[标签文档](../usage/issues-prs/labels.md)。
### Licenses
要添加自定义许可证,请将包含许可证文本的文件添加到 `$GITEA_CUSTOM/options/license`。
### Locales
本地化语言由我们的 [Crowdin](https://crowdin.com/project/gitea) 管理。
您可以通过将修改后的语言文件放到 `$GITEA_CUSTOM/options/locale` 中来覆盖某个语言环境。
Gitea 默认的语言文件可以在源码目录
[`options/locale`](https://github.com/go-gitea/gitea/tree/main/options/locale) 中找到,
这些文件可以作为您修改时的参考示例。
如果要添加一个全新的语言环境,除了将文件放到上述位置外,
您还需要在 `app.ini` 的 `[i18n]` 部分中添加新的语言代码和名称。
请记住,Gitea 会将这些设置视为**覆盖项**,因此如果您还想保留其他语言,
就需要复制默认值并在其中加入您自己的语言项。
```ini title="app.ini"
[i18n]
LANGS = en-US,foo-BAR
NAMES = English,FooBar
```
如果用户浏览器的语言与列表中的任何语言都不匹配,则第一种语言会被用作默认语言。
不同版本之间的语言文件可能会变化,因此强烈建议持续跟踪您自定义过的语言文件。
### Readmes
要添加自定义 Readme,请将一个 Markdown 格式的文件(不带 `.md` 扩展名)
放到 `$GITEA_CUSTOM/options/readme` 中。
:::note
Readme 模板支持**变量展开**。
当前可用变量包括 `{Name}`(仓库名称)、`{Description}`、`{CloneURL.SSH}`、`{CloneURL.HTTPS}` 和 `{OwnerName}`
:::
### Reactions
要修改反应表情,您可以在 `app.ini` 中设置允许使用的 reactions。
```ini title="app.ini"
[ui]
REACTIONS = +1, -1, laugh, confused, heart, hooray, eyes
```
完整的受支持 emoji 列表见 [emoji list](https://gitea.com/gitea/gitea.com/issues/8)。
## 自定义 Gitea 外观
内置主题有 `gitea-light`、`gitea-dark` 和 `gitea-auto`
(会自动适应操作系统设置)。
默认主题可以通过 `app.ini` 中 [ui](../administration/config-cheat-sheet.md#界面) 部分的
`DEFAULT_THEME` 进行修改。
Gitea 还支持用户主题,这意味着每位用户都可以选择要使用的主题。
用户可选主题列表可以通过 `app.ini` 中 [ui](../administration/config-cheat-sheet.md#界面)
部分的 `THEMES` 值进行配置。
要让所有用户都能使用自定义主题:
1. 将 CSS 文件添加到 `$GITEA_CUSTOM/public/assets/css/theme-<theme-name>.css`。
您可以通过执行 `gitea help` 并查看其中的 “CustomPath” 值来确认实例的 `$GITEA_CUSTOM`。
2. 将 `<theme-name>` 添加到 `app.ini` 中 `THEMES` 设置的逗号分隔列表中,
或者将 `THEMES` 留空以允许所有主题。
名为 `theme-my-theme.css` 的自定义主题文件会在用户主题选择页面中显示为 `my-theme`。
您还可以在自定义主题 CSS 文件中加入主题元信息,以提供更多说明。
如果自定义主题是暗色主题,请在 `:root` 块中设置全局 CSS 变量 `--is-dark-theme: true`。
这样 Gitea 就可以相应地调整 Monaco 代码编辑器的主题。
如果要实现 “auto” 主题,可以参考 `theme-gitea-auto.css`。
```css
gitea-theme-meta-info {
--theme-display-name: "My Awesome Theme"; /* this theme will be display as "My Awesome Theme" on the UI */
}
:root {
--is-dark-theme: true; /* if it is a dark theme */
--color-primary: #112233;
/* more custom theme variables ... */
}
```
社区主题列在 [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes)。
默认主题源码可在[这里](https://github.com/go-gitea/gitea/blob/main/web_src/css/themes)找到。
## 自定义字体
可以使用 CSS 变量自定义字体:
```css
:root {
--fonts-proportional: /* custom proportional fonts */ !important;
--fonts-monospace: /* custom monospace fonts */ !important;
--fonts-emoji: /* custom emoji fonts */ !important;
}
```
@@ -3,7 +3,7 @@ date: "2018-05-22T11:00:00+00:00"
slug: "reverse-proxies"
sidebar_position: 16
aliases:
- /zh-tw/reverse-proxies
- /zh-cn/reverse-proxies
---
# 反向代理
@@ -14,6 +14,8 @@ aliases:
2. 将 `https://git.example.com/foo` 反向代理到 `http://gitea:3000/foo`
3. 确保反向代理不会解码 URI。`https://git.example.com/a%2Fb`的请求应该被传递给 `http://gitea:3000/a%2Fb`。
4. 确保 `Host` 和 `X-Forwarded-Proto` 头被正确的传递给 Gitea,使 Gitea 可以看到正在访问的真实 URL。
5. 确保 Web 服务器有完整的证书(包括所有中间证书和根证书),以便 `git clone` 和 `git pull` 正常工作。
6. Gitea 会在 `/-/ws` 使用 WebSocket 连接,用于通知计数等实时更新。请确保反向代理使用 HTTP/1.1,并转发 `Upgrade` 和 `Connection` 头,参见下面的示例。否则 Gitea 会回退为定期轮询。
## 使用子路径
@@ -39,6 +41,7 @@ server {
location / {
client_max_body_size 512M;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
@@ -61,8 +64,9 @@ server {
# 确保 nginx 使用未转义 URI, 按原样保持 "%2F"。 确保 nginx 去除 "/gitea" 子路径前缀, 按原样传递 "/v2"。
rewrite ^ $request_uri;
rewrite ^(/gitea)?(/.*) $2 break;
rewrite ^/(gitea($|/))?(.*) /$3 break;
proxy_pass http://127.0.0.1:3000$uri;
proxy_http_version 1.1;
# 其他的常规 HTTP 表头,见上面“使用 Nginx 作为反向代理服务”小节的配置
proxy_set_header Connection $http_connection;
@@ -107,6 +111,7 @@ server {
}
location / {
# 其他指令见上面「使用 Nginx 作为反向代理服务」小节
proxy_pass http://localhost:3000;
}
}
@@ -123,6 +128,7 @@ server {
server_name git.example.com;
location / {
# 其他指令见上面「使用 Nginx 作为反向代理服务」小节
proxy_pass http://localhost:3000;
}
}
@@ -144,6 +150,20 @@ server {
}
```
## Nginx Proxy Manager
如果使用 Nginx Proxy Manager 作为 Gitea 的反向代理,配置与原生 Nginx 略有不同。
它会[默认给自定义 location 加上一些指令](https://github.com/NginxProxyManager/nginx-proxy-manager/blob/master/docker/rootfs/etc/nginx/conf.d/include/proxy.conf),因此上面 Nginx 配置里对应的指令不要再写一遍。否则会因为指令重复(尤其是 `proxy_set_header Host $host`)出现 `400 bad request`。
创建 `/` 自定义 location 时,只需在其配置中加入:
```nginx
client_max_body_size 512M;
```
在代理主机上启用 `Websockets Support`,Nginx Proxy Manager 会自行加入 WebSocket 相关指令。再额外添加 `proxy_http_version` 会导致 Nginx 拒绝启动。
## 使用 Apache HTTPD 作为反向代理服务
如果您想使用 Apache HTTPD 作为 Gitea 的反向代理服务,您可以为您的 Apache HTTPD 作如下配置(在 Ubuntu 中,配置文件通常在 `/etc/apache2/httpd.conf` 目录下):
@@ -154,30 +174,23 @@ server {
ProxyPreserveHost On
ProxyRequests off
AllowEncodedSlashes NoDecode
ProxyPass / http://localhost:3000/ nocanon
ProxyPass / http://localhost:3000/ nocanon upgrade=websocket
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
```
注:必须启用以下 Apache HTTPD 组件:`proxy`, `proxy_http`
:::note
必须启用以下 Apache HTTPD 组件:`proxy`, `proxy_http`。
`upgrade=websocket` 需要 Apache HTTPD 2.4.48 或更高版本。更旧的版本**必须**去掉它,否则 Apache HTTPD 将无法启动。
:::
如果希望用 Let's Encrypt 的 webroot 验证,请在 `ProxyPass` 之前加入 `ProxyPass /.well-known !`,避免把这些请求代理到 Gitea。
## 使用 Apache HTTPD 作为反向代理服务并将 Gitea 路由至一个子路径
如果您已经有一个域名并且想与 Gitea 共享该域名,您可以增加以下配置为 Gitea 添加路由规则(在 Ubuntu 中,配置文件通常在 `/etc/apache2/httpd.conf` 目录下):
```
<VirtualHost *:80>
...
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
AllowEncodedSlashes NoDecode
# 注意: 路径和 URL 后面都不要写路径符号 '/'
ProxyPass /git http://localhost:3000 nocanon
</VirtualHost>
```
```apacheconf
<VirtualHost *:80>
...
@@ -187,7 +200,7 @@ server {
</Proxy>
AllowEncodedSlashes NoDecode
# 注意: 路径和 URL 后面都不要写路径符号 '/'
ProxyPass /git http://localhost:3000 nocanon
ProxyPass /git http://localhost:3000 nocanon upgrade=websocket
ProxyPreserveHost On
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
@@ -195,7 +208,55 @@ server {
然后您**必须**在 Gitea 的配置文件中正确的添加类似 `[server] ROOT_URL = http://git.example.com/git/` 的配置项。
注:必须启用以下 Apache HTTPD 组件:`proxy`, `proxy_http`
:::note
必须启用以下 Apache HTTPD 组件:`proxy`, `proxy_http`。`upgrade=websocket` 需要 Apache HTTPD 2.4.48 或更高版本,更旧的版本请去掉它。
:::
## 使用 Apache HTTPD 直接提供静态资源
我们可以通过将资源分为静态和动态两种类型来调节性能。
CSS 文件、JavaScript 文件、图片和字体是静态内容。首页、仓库视图和工单列表是动态内容。
Apache HTTPD 可以直接提供静态资源,并且只代理动态资源请求给 Gitea。
将 Gitea 源代码仓库的一个快照下载到 `/path/to/gitea/`。
在此之后,在本地仓库目录运行 `make frontend` 来生成静态资源。在这个情况下,我们只对 `public/` 目录感兴趣,您可以删除剩下的其他目录。
(为了生成静态资源,您需要安装一个[带 npm 的 Node ](https://nodejs.org/en/download/)和 `make`)
取决于您的用户量的大小,您可以将流量分离到两个不同的服务器,或者为静态资源配置一个 cdn。
### 单服务器节点,单域名
将 `[server] STATIC_URL_PREFIX = /_/static` 写入您的 Gitea 配置文件:
```apacheconf
<VirtualHost *:80>
...
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPass /_/static/ !
Alias /_/static/ /path/to/gitea/public/
<Directory /path/to/gitea/public/>
Options FollowSymlinks
AllowOverride None
Require all granted
</Directory>
AllowEncodedSlashes NoDecode
# 注意: 路径和 URL 后面都不要写路径符号 '/'
ProxyPass / http://localhost:3000/ nocanon upgrade=websocket
ProxyPreserveHost On
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
```
:::note
必须启用以下 Apache HTTPD 组件:`proxy`, `proxy_http`。`upgrade=websocket` 需要 Apache HTTPD 2.4.48 或更高版本,更旧的版本请去掉它。
:::
## 使用 Caddy 作为反向代理服务
@@ -231,11 +292,13 @@ git.example.com {
- 使用 Microsoft Web Platform Installer 5.1 (WebPI) 安装 Application Request Routing(简称 ARR),或者在 [IIS.net](https://www.iis.net/downloads/microsoft/application-request-routing) 下载这个插件。
- 一但这个模块被安装到 IIS 上,你将会在 IIS 管理控制台看到一个叫做 URL Rewrite 的新图标。
- 安装 Windows 功能 `WebSocket Protocol`,否则 ARR 无法代理 Gitea 的 WebSocket 端点。
- 打开 IIS 管理控制台,在左边的列表中点击 `Gitea Proxy` 网页。在中间选中并且双击 URL Rewrite 的图标来加载 URL 重写的面板。
- 在管理控制台的右边选择 `Add Rule` 操作,并且在 `Inbound and Outbound Rules` 分类中选择 `Reverse Proxy Rule`。
- 在 Inbound Rules 中, 将 server name 设置为 Gitea 正在运行的主机以及对应端口。例如,如果你在 localhost 的 3000 端口上运行 Gitea,则设置为 `127.0.0.1:3000`。
- 启用 SSL Offloading
- 在 Outbound Rules 中,确保设置了 `Rewrite the domain names of the links in HTTP response`,并且将 `From:` 设置为上面的 server name,将 `To:` 设置为你的外部访问名称,例如:`git.example.com`
- 关闭 Application Request Routing 的 `Server Proxy Settings` 中的 `Reverse rewrite host in response headers`(在 IIS 管理器中选择服务器节点,打开 `Application Request Routing Cache`,再打开右侧的 `Server Proxy Settings`)。若保持开启,ARR 会把 `Location` 头里的主机改回内部地址,导致登录或表单提交后的重定向把浏览器送到 `127.0.0.1:3000` 而不是 `git.example.com`。
- 现在,根据下面的内容为您的网页编辑 `web.config`(将 `127.0.0.1:3000` 和 `git.example.com` 改为适当的值)
```xml
@@ -3,7 +3,7 @@ date: "2018-06-24:00:00+02:00"
slug: "api-usage"
sidebar_position: 40
aliases:
- /zh-tw/api-usage
- /zh-cn/api-usage
---
# API 使用指南
@@ -12,6 +12,7 @@ aliases:
通常情况下, `ENABLE_SWAGGER` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat Sheet](../administration/config-cheat-sheet.md) 中获取更多配置相关信息。
<a id="authentication"></a>
## 通过 API 认证
Gitea 支持以下几种 API 认证方式:
Loaded 100 of 2340 files, more files were not shown because too many files have changed in this diff. Show more