diff --git a/.gitea/workflows/build-and-publish.yaml b/.gitea/workflows/build-and-publish.yaml index 1814fbb9..546fc77e 100644 --- a/.gitea/workflows/build-and-publish.yaml +++ b/.gitea/workflows/build-and-publish.yaml @@ -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 diff --git a/.gitea/workflows/cleanup-preview.yaml b/.gitea/workflows/cleanup-preview.yaml new file mode 100644 index 00000000..36cf6fbc --- /dev/null +++ b/.gitea/workflows/cleanup-preview.yaml @@ -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" diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index baf25dbf..c399812a 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -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='' + # 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" diff --git a/.gitea/workflows/update_runner_reference.yaml b/.gitea/workflows/update_runner_reference.yaml new file mode 100644 index 00000000..eea0bfb1 --- /dev/null +++ b/.gitea/workflows/update_runner_reference.yaml @@ -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 "teabot@gitea.io" + 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 </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 "teabot@gitea.io" - 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 "teabot@gitea.io" + 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 < 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) diff --git a/README.md b/README.md index 5c6ea103..d642823a 100644 --- a/README.md +++ b/README.md @@ -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-.json` (released +versions) hold the swagger 2.0 document every gitea version ships, +`openapi3-latest.json` and `openapi3-.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--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. diff --git a/cloudflare/_headers b/cloudflare/_headers new file mode 100644 index 00000000..7653e226 --- /dev/null +++ b/cloudflare/_headers @@ -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 diff --git a/cloudflare/_redirects b/cloudflare/_redirects new file mode 100644 index 00000000..d758d5ef --- /dev/null +++ b/cloudflare/_redirects @@ -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 diff --git a/cloudflare/docsearch-crawler.json b/cloudflare/docsearch-crawler.json new file mode 100644 index 00000000..903d5310 --- /dev/null +++ b/cloudflare/docsearch-crawler.json @@ -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": [] +} diff --git a/docs/administration/adding-legal-pages.md b/docs/administration/adding-legal-pages.md index 650211fd..f4921845 100644 --- a/docs/administration/adding-legal-pages.md +++ b/docs/administration/adding-legal-pages.md @@ -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. diff --git a/docs/administration/audit-logging.md b/docs/administration/audit-logging.md new file mode 100644 index 00000000..64eb5271 --- /dev/null +++ b/docs/administration/audit-logging.md @@ -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 (`//settings/audit_logs`) | Events scoped to that organization | +| Repository administrators | Repository settings → Audit Log (`///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-.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:`, `oauth2-grant:`, `gitea-actions:`, + `deploy-key:`. +- **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. diff --git a/docs/administration/authentication.md b/docs/administration/authentication.md index 2cbd44cc..bbfe0ea3 100644 --- a/docs/administration/authentication.md +++ b/docs/administration/authentication.md @@ -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. +::: diff --git a/docs/administration/backup-and-restore.md b/docs/administration/backup-and-restore.md index 063a3bae..39fa9a24 100644 --- a/docs/administration/backup-and-restore.md +++ b/docs/administration/backup-and-restore.md @@ -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 diff --git a/docs/administration/command-line.md b/docs/administration/command-line.md index 9bf4a16e..6597689b 100644 --- a/docs/administration/command-line.md +++ b/docs/administration/command-line.md @@ -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 diff --git a/docs/administration/config-cheat-sheet.md b/docs/administration/config-cheat-sheet.md index 34adcf95..f08ac133 100644 --- a/docs/administration/config-cheat-sheet.md +++ b/docs/administration/config-cheat-sheet.md @@ -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__
__`. 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 `
` or `` 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- ` or `ssh- , ssh- `. 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`: **\**: 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://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (See [queue/CONN_STR](#queue-queue-and-queue) for information on additional supported connection types) - For a Redis cluster: `redis+cluster://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` - For a Redis sentinel: `redis+sentinel://:macaron@sentinel0:26379,sentinel1:26379,sentinel2:26379/0?pool_size=100&idle_timeout=180s&master_name=mymaster` - - Memcache: `127.0.0.1:9090;127.0.0.1:9091` + - 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 ``, `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 `/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`) diff --git a/docs/administration/customizing-gitea.md b/docs/administration/customizing-gitea.md index 3439febd..597857fc 100644 --- a/docs/administration/customizing-gitea.md +++ b/docs/administration/customizing-gitea.md @@ -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 `` 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 - +``` + +随后,您就可以在 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 + +``` + +#### 第 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 = +``` + +`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-.css`。 + 您可以通过执行 `gitea help` 并查看其中的 “CustomPath” 值来确认实例的 `$GITEA_CUSTOM`。 +2. 将 `` 添加到 `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; +} +``` diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/email-setup.md b/i18n/zh-cn/docs/current/administration/email-setup.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/email-setup.md rename to i18n/zh-cn/docs/current/administration/email-setup.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/environment-variables.md b/i18n/zh-cn/docs/current/administration/environment-variables.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/environment-variables.md rename to i18n/zh-cn/docs/current/administration/environment-variables.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/external-renderers.md b/i18n/zh-cn/docs/current/administration/external-renderers.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/external-renderers.md rename to i18n/zh-cn/docs/current/administration/external-renderers.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/fail2ban-setup.md b/i18n/zh-cn/docs/current/administration/fail2ban-setup.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/fail2ban-setup.md rename to i18n/zh-cn/docs/current/administration/fail2ban-setup.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/git-lfs-support.md b/i18n/zh-cn/docs/current/administration/git-lfs-support.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/git-lfs-support.md rename to i18n/zh-cn/docs/current/administration/git-lfs-support.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/https-support.md b/i18n/zh-cn/docs/current/administration/https-support.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/https-support.md rename to i18n/zh-cn/docs/current/administration/https-support.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/logging-config.md b/i18n/zh-cn/docs/current/administration/logging-config.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/logging-config.md rename to i18n/zh-cn/docs/current/administration/logging-config.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/mail-templates.md b/i18n/zh-cn/docs/current/administration/mail-templates.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/mail-templates.md rename to i18n/zh-cn/docs/current/administration/mail-templates.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/repo-indexer.md b/i18n/zh-cn/docs/current/administration/repo-indexer.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/repo-indexer.md rename to i18n/zh-cn/docs/current/administration/repo-indexer.md diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/administration/reverse-proxies.md b/i18n/zh-cn/docs/current/administration/reverse-proxies.md similarity index 78% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/administration/reverse-proxies.md rename to i18n/zh-cn/docs/current/administration/reverse-proxies.md index 89e35107..20cd8b82 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/administration/reverse-proxies.md +++ b/i18n/zh-cn/docs/current/administration/reverse-proxies.md @@ -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} ``` -注:必须启用以下 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` 目录下): -``` - - ... - - Order allow,deny - Allow from all - - AllowEncodedSlashes NoDecode - # 注意: 路径和 URL 后面都不要写路径符号 '/' - ProxyPass /git http://localhost:3000 nocanon - -``` - ```apacheconf ... @@ -187,7 +200,7 @@ server { 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} @@ -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 + + ... + + Order allow,deny + Allow from all + + + ProxyPass /_/static/ ! + Alias /_/static/ /path/to/gitea/public/ + + Options FollowSymlinks + AllowOverride None + Require all granted + + + AllowEncodedSlashes NoDecode + # 注意: 路径和 URL 后面都不要写路径符号 '/' + ProxyPass / http://localhost:3000/ nocanon upgrade=websocket + ProxyPreserveHost On + RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME} + +``` + +:::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 diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/search-engines-indexation.md b/i18n/zh-cn/docs/current/administration/search-engines-indexation.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/search-engines-indexation.md rename to i18n/zh-cn/docs/current/administration/search-engines-indexation.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/signing.md b/i18n/zh-cn/docs/current/administration/signing.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/signing.md rename to i18n/zh-cn/docs/current/administration/signing.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/_category_.json b/i18n/zh-cn/docs/current/contributing/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/_category_.json rename to i18n/zh-cn/docs/current/contributing/_category_.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/guidelines-backend.md b/i18n/zh-cn/docs/current/contributing/guidelines-backend.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/guidelines-backend.md rename to i18n/zh-cn/docs/current/contributing/guidelines-backend.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/guidelines-frontend.md b/i18n/zh-cn/docs/current/contributing/guidelines-frontend.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/guidelines-frontend.md rename to i18n/zh-cn/docs/current/contributing/guidelines-frontend.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/guidelines-refactoring.md b/i18n/zh-cn/docs/current/contributing/guidelines-refactoring.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/guidelines-refactoring.md rename to i18n/zh-cn/docs/current/contributing/guidelines-refactoring.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/localization.md b/i18n/zh-cn/docs/current/contributing/localization.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/contributing/localization.md rename to i18n/zh-cn/docs/current/contributing/localization.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/development/_category_.json b/i18n/zh-cn/docs/current/development/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/development/_category_.json rename to i18n/zh-cn/docs/current/development/_category_.json diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/version-1.22/development/api-usage.md b/i18n/zh-cn/docs/current/development/api-usage.md similarity index 98% rename from i18n/zh-tw/docusaurus-plugin-content-docs/version-1.22/development/api-usage.md rename to i18n/zh-cn/docs/current/development/api-usage.md index b6ecc47f..1b98d07b 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/version-1.22/development/api-usage.md +++ b/i18n/zh-cn/docs/current/development/api-usage.md @@ -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) 中获取更多配置相关信息。 + ## 通过 API 认证 Gitea 支持以下几种 API 认证方式: diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/development/hacking-on-gitea.md b/i18n/zh-cn/docs/current/development/hacking-on-gitea.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/development/hacking-on-gitea.md rename to i18n/zh-cn/docs/current/development/hacking-on-gitea.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/development/integrations.md b/i18n/zh-cn/docs/current/development/integrations.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/development/integrations.md rename to i18n/zh-cn/docs/current/development/integrations.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/development/migrations.md b/i18n/zh-cn/docs/current/development/migrations.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/development/migrations.md rename to i18n/zh-cn/docs/current/development/migrations.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/development/oauth2-provider.md b/i18n/zh-cn/docs/current/development/oauth2-provider.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/development/oauth2-provider.md rename to i18n/zh-cn/docs/current/development/oauth2-provider.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/_category_.json b/i18n/zh-cn/docs/current/help/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/help/_category_.json rename to i18n/zh-cn/docs/current/help/_category_.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/faq.md b/i18n/zh-cn/docs/current/help/faq.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/help/faq.md rename to i18n/zh-cn/docs/current/help/faq.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/support.md b/i18n/zh-cn/docs/current/help/support.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/help/support.md rename to i18n/zh-cn/docs/current/help/support.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/index.md b/i18n/zh-cn/docs/current/index.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/index.md rename to i18n/zh-cn/docs/current/index.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/_category_.json b/i18n/zh-cn/docs/current/installation/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/_category_.json rename to i18n/zh-cn/docs/current/installation/_category_.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/comparison.md b/i18n/zh-cn/docs/current/installation/comparison.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/comparison.md rename to i18n/zh-cn/docs/current/installation/comparison.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/database-preparation.md b/i18n/zh-cn/docs/current/installation/database-preparation.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/database-preparation.md rename to i18n/zh-cn/docs/current/installation/database-preparation.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/from-binary.md b/i18n/zh-cn/docs/current/installation/from-binary.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/from-binary.md rename to i18n/zh-cn/docs/current/installation/from-binary.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/from-package.md b/i18n/zh-cn/docs/current/installation/from-package.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/from-package.md rename to i18n/zh-cn/docs/current/installation/from-package.md diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/version-1.22/installation/from-source.md b/i18n/zh-cn/docs/current/installation/from-source.md similarity index 95% rename from i18n/zh-tw/docusaurus-plugin-content-docs/version-1.22/installation/from-source.md rename to i18n/zh-cn/docs/current/installation/from-source.md index 917fe9bc..7cb4da5b 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/version-1.22/installation/from-source.md +++ b/i18n/zh-cn/docs/current/installation/from-source.md @@ -1,20 +1,18 @@ --- date: "2016-12-01T16:00:00+02:00" - slug: "install-from-source" sidebar_position: 30 - aliases: - - /zh-tw/install-from-source + - /zh-cn/install-from-source --- # 使用源代码安装 你需要 [安装 Go](https://golang.google.cn/doc/install) 并正确设置 Go 环境。特别的,建议设置`$GOPATH`环境变量,并将 Go 的二进制目录或目录`${GOPATH//://bin:}/bin`添加到`$PATH`中。请参阅 Go 百科上关于 [GOPATH](https://github.com/golang/go/wiki/GOPATH) 的词条。 -接下来,[安装 Node.js 和 npm](https://nodejs.org/zh-tw/download/), 这是构建 JavaScript 和 CSS 文件所需的。最低支持的 Node.js 版本是 @minNodeVersion@,建议使用最新的 LTS 版本。 +接下来,[安装 Node.js 和 npm](https://nodejs.org/zh-cn/download/), 这是构建 JavaScript 和 CSS 文件所需的。最低支持的 Node.js 版本是 @minNodeVersion@,建议使用最新的 LTS 版本。 -**注意**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。 +**注意**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](https://github.com/go-gitea/gitea/blob/main/docs/build-setup.md) 中给出的建议。 ## 下载 @@ -54,8 +52,8 @@ git checkout @sourceVersion@ # or git checkout pr-xyz 要从源代码进行构建,系统必须预先安装以下程序: - `go` @minGoVersion@ 或更高版本,请参阅 [这里](https://go.dev/dl/) -- `node` @minNodeVersion@ 或更高版本,并且安装 `npm`, 请参阅 [这里](https://nodejs.org/zh-tw/download/) -- `make`, 请参阅 [这里](development/hacking-on-gitea.md) +- `node` @minNodeVersion@ 或更高版本,并且安装 `npm`, 请参阅 [这里](https://nodejs.org/zh-cn/download/) +- `make`, 请参阅 [这里](https://github.com/go-gitea/gitea/blob/main/docs/build-setup.md) 为了尽可能简化编译过程,提供了各种 [make 任务](https://github.com/go-gitea/gitea/blob/main/Makefile)。 @@ -83,7 +81,7 @@ TAGS="bindata sqlite sqlite_unlock_notify" make build `build`目标分为两个子目标: - `make backend` 需要 [Go @minGoVersion@](https://golang.google.cn/doc/install) 或更高版本。 -- `make frontend` 需要 [Node.js @minNodeVersion@](https://nodejs.org/zh-tw/download/) 或更高版本。 +- `make frontend` 需要 [Node.js @minNodeVersion@](https://nodejs.org/zh-cn/download/) 或更高版本。 如果存在预构建的前端文件,可以仅构建后端: diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/on-kubernetes.md b/i18n/zh-cn/docs/current/installation/on-kubernetes.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/on-kubernetes.md rename to i18n/zh-cn/docs/current/installation/on-kubernetes.md diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/run-as-service-in-ubuntu.md b/i18n/zh-cn/docs/current/installation/run-as-service-in-ubuntu.md similarity index 87% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/run-as-service-in-ubuntu.md rename to i18n/zh-cn/docs/current/installation/run-as-service-in-ubuntu.md index f02d3256..0ca23e0b 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/run-as-service-in-ubuntu.md +++ b/i18n/zh-cn/docs/current/installation/run-as-service-in-ubuntu.md @@ -3,7 +3,7 @@ date: "2017-07-21T12:00:00+02:00" slug: "linux-service" sidebar_position: 40 aliases: - - /zh-tw/linux-service + - /zh-cn/linux-service --- # 在 Linux 中以 service 方式运行 @@ -18,7 +18,7 @@ aliases: sudo vim /etc/systemd/system/gitea.service ``` -接着拷贝示例代码 [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/systemd/gitea.service) 并取消对任何需要运行在主机上的服务部分的注释,譬如 MySQL。 +接着拷贝示例代码 [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/service/systemd/gitea.service) 并取消对任何需要运行在主机上的服务部分的注释,譬如 MySQL。 修改 user,home 目录以及其他必须的初始化参数,如果使用自定义端口,则需修改 PORT 参数,反之如果使用默认端口则需删除 -p 标记。 @@ -51,7 +51,7 @@ sudo vim /etc/supervisor/supervisord.conf ``` 增加如下示例配置 -[supervisord config](https://github.com/go-gitea/gitea/blob/main/contrib/supervisor/gitea)。 +[supervisord config](https://github.com/go-gitea/gitea/blob/main/contrib/service/supervisor/gitea)。 将 user(git) 和 home(/home/git) 设置为与上文部署中匹配的值。如果使用自定义端口,则需修改 PORT 参数,反之如果使用默认端口则需删除 -p 标记。 diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/upgrade-from-gitea.md b/i18n/zh-cn/docs/current/installation/upgrade-from-gitea.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/upgrade-from-gitea.md rename to i18n/zh-cn/docs/current/installation/upgrade-from-gitea.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/windows-service.md b/i18n/zh-cn/docs/current/installation/windows-service.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/installation/windows-service.md rename to i18n/zh-cn/docs/current/installation/windows-service.md diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/with-docker-rootless.md b/i18n/zh-cn/docs/current/installation/with-docker-rootless.md similarity index 97% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/with-docker-rootless.md rename to i18n/zh-cn/docs/current/installation/with-docker-rootless.md index 4038c428..0823127d 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/with-docker-rootless.md +++ b/i18n/zh-cn/docs/current/installation/with-docker-rootless.md @@ -3,7 +3,7 @@ date: "2020-02-09T20:00:00+02:00" slug: "install-with-docker-rootless" sidebar_position: 60 aliases: - - /zh-tw/install-with-docker-rootless + - /zh-cn/install-with-docker-rootless --- # 使用 Docker 安装 (rootless) @@ -53,7 +53,7 @@ sudo chown 1000:1000 config/ data/ > 如果未为卷设置正确的权限,容器可能无法启动。 -对于稳定版本,您可以使用 `:latest-rootless`、`:1-rootless`,或指定特定的版本,如: `@dockerVersion@-rootless`。如果您想使用最新的开发版本,则可以使用 `:dev-rootless` 标签。如果您想运行发布分支的最新提交,可以使用 `:1.x-dev-rootless` 标签,其中 x 是 Gitea 的次要版本号(例如:`1.16-dev-rootless`)。 +对于稳定版本,您可以使用 `:latest-rootless`、`:1-rootless`,或指定特定的版本,如: `@dockerVersion@-rootless`。如果您想使用最新的开发版本,则可以使用 `:main-nightly-rootless` 标签。如果您想运行发布分支的最新提交,可以使用 `:1.x-nightly-rootless` 标签,其中 x 是 Gitea 的次要版本号(例如:`1.27-nightly-rootless`)。 ## 自定义端口 diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/with-docker.md b/i18n/zh-cn/docs/current/installation/with-docker.md similarity index 96% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/with-docker.md rename to i18n/zh-cn/docs/current/installation/with-docker.md index 9edd4f1f..812d73cb 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/installation/with-docker.md +++ b/i18n/zh-cn/docs/current/installation/with-docker.md @@ -3,7 +3,7 @@ date: "2016-12-01T16:00:00+02:00" slug: "install-with-docker" sidebar_position: 70 aliases: - - /zh-tw/install-with-docker + - /zh-cn/install-with-docker --- # 使用 Docker 安装 @@ -14,7 +14,7 @@ Gitea 在其 Docker Hub 组织内提供自动更新的 Docker 镜像。可以始 ## 基本 -最简单的设置只是创建一个卷和一个网络,然后将 `docker.gitea.com/gitea:latest` 镜像作为服务启动。由于没有可用的数据库,因此可以使用 SQLite3 初始化数据库。创建一个类似 `gitea` 的目录,并将以下内容粘贴到名为 `docker-compose.yml` 的文件中。请注意,该卷应由配置文件中指定的 UID/GID 的用户/组拥有。如果您不授予卷正确的权限,则容器可能无法启动。另请注意,标签 `:latest` 将安装当前的开发版本。对于稳定的发行版,您可以使用 `:1` 或指定某个发行版,例如 `@dockerVersion@`。 +最简单的设置只是创建一个卷和一个网络,然后将 `docker.gitea.com/gitea:latest` 镜像作为服务启动。由于没有可用的数据库,因此可以使用 SQLite3 初始化数据库。创建一个类似 `gitea` 的目录,并将以下内容粘贴到名为 `docker-compose.yml` 的文件中。请注意,该卷应由配置文件中指定的 UID/GID 的用户/组拥有。如果您不授予卷正确的权限,则容器可能无法启动。另请注意,标签 `:latest` 安装的是最新的稳定版本。对于稳定的发行版,您也可以使用 `:1` 或指定某个发行版,例如 `@dockerVersion@`。如果您想使用最新的开发版本,则可以使用 `:main-nightly` 标签;如果您想运行发布分支的最新提交,可以使用 `:1.x-nightly` 标签,其中 x 是 Gitea 的次要版本号(例如:`1.27-nightly`)。 ```yaml version: "3" @@ -296,7 +296,6 @@ docker run -it --rm docker.gitea.com/gitea:1 gitea generate secret INTERNAL_TOKE ``` ```yaml - --- services: server: diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/_category_.json b/i18n/zh-cn/docs/current/usage/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/_category_.json rename to i18n/zh-cn/docs/current/usage/_category_.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/access-control/_category_.json b/i18n/zh-cn/docs/current/usage/access-control/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/access-control/_category_.json rename to i18n/zh-cn/docs/current/usage/access-control/_category_.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/access-control/permissions.md b/i18n/zh-cn/docs/current/usage/access-control/permissions.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/access-control/permissions.md rename to i18n/zh-cn/docs/current/usage/access-control/permissions.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/access-control/protected-tags.md b/i18n/zh-cn/docs/current/usage/access-control/protected-tags.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/access-control/protected-tags.md rename to i18n/zh-cn/docs/current/usage/access-control/protected-tags.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/actions/_category_.json b/i18n/zh-cn/docs/current/usage/actions/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/actions/_category_.json rename to i18n/zh-cn/docs/current/usage/actions/_category_.json diff --git a/i18n/zh-cn/docs/current/usage/actions/comparison.md b/i18n/zh-cn/docs/current/usage/actions/comparison.md new file mode 100644 index 00000000..43d349a6 --- /dev/null +++ b/i18n/zh-cn/docs/current/usage/actions/comparison.md @@ -0,0 +1,102 @@ +--- +date: "2023-05-24T15:00:00+08:00" +slug: "comparison" +sidebar_position: 15 +--- + +# 与GitHub Actions的对比 + +Gitea Actions旨在与GitHub Actions兼容,差异如下。 + +## 额外功能 + + +### Action URL绝对路径 + +`uses:`支持指向任意Git托管平台的绝对URL,例如`uses: https://gitea.com/actions/checkout@v4`。 + + +### Action前缀 + +`uses:`支持以下前缀: + +- `self:`引用您自己的Gitea实例,例如`uses: self:owner/repo@v1`或`uses: self:owner/repo/.gitea/workflows/build.yml@v1` +- `builtin:`运行Gitea Runner内置的Action,无需下载,Job镜像中也无需Node,例如`uses: builtin:checkout` + +`builtin:checkout`支持`actions/checkout`的`repository`、`ref`、`token`、`path`和`fetch-depth`输入,默认值相同,其他输入会使步骤失败。 + + +### 相对于工作流的Actions + +`$/`引用工作流所在的仓库和提交,或外层复合Action所在的仓库和提交,例如`uses: $/.gitea/actions/build`。 +与`./`不同,它无需事先检出代码。 + +### 使用Go编写Actions + +请参阅[创建Go Actions](https://blog.gitea.com/creating-go-actions/)。 + +### 支持非标准的调度语法 @yearly, @monthly, @weekly, @daily, @hourly + +`schedule`还支持`@yearly`、`@monthly`、`@weekly`、`@daily`和`@hourly`,而[GitHub不支持](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule)。 + +## 不支持的工作流语法 + +### `jobs..environment` + +[`jobs..environment`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idenvironment)会被忽略。 + +### 复杂的`runs-on` + +[`runs-on`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on)支持: + +- 静态字符串:`runs-on: self-hosted` +- 标签数组:`runs-on: [linux, self-hosted]` +- 字符串表达式:`runs-on: ${{ github.event_name == 'push' && 'ubuntu-latest' || 'self-hosted' }}` +- 包含表达式的数组:`runs-on: [linux, "${{ github.event_name == 'push' && 'ubuntu-latest' || 'self-hosted' }}"]` + +## 缺失的功能 + +### 软件包仓库授权 + +`GITEA_TOKEN`无法发布到其所属仓库的软件包注册表,例如无法推送OCI镜像。 +请改用个人访问令牌,参见[此问题](https://github.com/go-gitea/gitea/issues/23642#issuecomment-2119876692)。 + +### 问题匹配器 + +[问题匹配器](https://github.com/actions/toolkit/blob/main/docs/problem-matchers.md)会被忽略。 + +### 为错误创建注释 + +[错误注释](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-creating-an-annotation-for-an-error)会被忽略。 + +### 表达式 + +[表达式](https://docs.github.com/en/actions/learn-github-actions/expressions)支持GitHub的标准函数和上下文。 + +## 缺失的UI功能 + +### 预处理和后处理步骤 + +预处理和后处理步骤在Job日志中没有单独的区块。 + +### 服务步骤 + +服务步骤在Job日志中没有单独的区块。 + +## 不一样的行为 + +### `permissions`和`jobs..permissions` + +`permissions`和`jobs..permissions`控制`GITEA_TOKEN`的权限,该权限受仓库和所有者设置的限制,并在fork拉取请求和跨仓库访问时受到进一步限制。 +不支持`statuses`、`checks`、`deployments`、`security-events`和`pages`等GitHub专有的权限范围,而Gitea额外提供了`code`、`releases`、`wiki`和`projects`。`id-token`与GitHub相同,请参阅[OpenID Connect](openid-connect.md)。 +请参阅[Actions Job令牌权限](token-permissions.md)。 + +### 下载Actions + +未指定主机的Actions(如`uses: actions/checkout@v4`)会从`https://github.com`下载,当`[actions].DEFAULT_ACTIONS_URL`为`self`时则从您自己的实例下载。 +请参阅[配置备忘单](../../administration/config-cheat-sheet.md#actions-actions)。 +其他来源请参阅[Action URL绝对路径](#absolute-action-urls)、[Action前缀](#action-prefixes)和[相对于工作流的Actions](#workflow-relative-actions)。 + +### 上下文可用性 + +不检查[上下文可用性](https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability),因此`env`等上下文可以在更多地方使用。 diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/design.md b/i18n/zh-cn/docs/current/usage/actions/design.md similarity index 59% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/design.md rename to i18n/zh-cn/docs/current/usage/actions/design.md index f7588171..a23f03e8 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/design.md +++ b/i18n/zh-cn/docs/current/usage/actions/design.md @@ -8,46 +8,22 @@ sidebar_position: 40 Gitea Actions由多个组件组成。本文档将对它们进行逐个描述。 -## Act +## Gitea Runner -[nektos/act](https://github.com/nektos/act) 项目是一个优秀的工具,允许你在本地运行GitHub Actions。 -我们受到了它的启发,并思考它是否可能为Gitea运行Actions。 +Gitea Runner部分基于[nektos/act](https://github.com/nektos/act)的硬分支。 -然而,尽管[nektos/act](https://github.com/nektos/act)被设计为一个命令行工具,但我们实际上需要的是一个专为Gitea修改的Go库。 -因此,我们在[gitea/act](https://gitea.com/gitea/act)基础上进行了分叉。 - -这是一个软分叉,将定期跟进上游。 -虽然添加了一些自定义提交,但我们会尽力避免对原始代码进行太多更改。 - -分叉的 act 只是Gitea特定用途的桥接或适配器。 -还添加了一些额外的提交,例如: - -- 将执行日志输出到日志记录器钩子,以便报告给Gitea -- 禁用 GraphQL URL,因为Gitea不支持它 -- 每个Job启动一个新的容器,而不是重复使用,以确保隔离性。 - -这些修改没有理由合并到上游。 -如果用户只想在本地运行可信的Actions,它们是没有意义的。 - -然而,将来可能会出现重叠,例如两个项目都需要的必要错误修复或新功能。 -在这些情况下,我们将向上游仓库贡献变更。 - -## act runner - -Gitea的Runner被称为act runner,因为它基于act。 - -与其他CIRunner一样,我们将其设计为Gitea的外部部分,这意味着它应该在与Gitea不同的服务器上运行。 +与其他CI Runner一样,我们将其设计为Gitea的外部部分,这意味着它应该在与Gitea不同的服务器上运行。 为了确保Runner连接到正确的Gitea实例,我们需要使用令牌注册它。 此外,Runner通过声明自己的标签向Gitea报告它可以运行的Job类型。 之前,我们提到工作流文件中的 `runs-on: ubuntu-latest` 表示该Job将在具有`ubuntu-latest`标签的Runner上运行。 但是,Runner如何知道要运行 `ubuntu-latest`?答案在于将标签映射到环境。 -这就是为什么在注册过程中添加自定义标签时,需要输入一些复杂内容,比如`my_custom_label:docker://centos:7`。 +这就是为什么Runner的每个标签都会指定一个环境,比如`my_custom_label:docker://centos:7`。 这意味着Runner可以接受需要在`my_custom_label`上运行的Job,并通过使用`centos:7`镜像的Docker容器来运行它。 然而,Docker不是唯一的选择。 -act 也支持直接在主机上运行Job。 +Runner 也支持直接在主机上运行Job。 这是通过像`linux_arm:host`这样的标签实现的。 这个标签表示Runner可以接受需要在`linux_arm`上运行的Job,并直接在主机上运行它们。 @@ -59,32 +35,31 @@ act 也支持直接在主机上运行Job。 - `my_custom_label:docker://node:18`:使用`node:18 Docker`镜像运行带有`my_custom_label`标签的Job。 - `my_custom_label:host`:在主机上直接运行带有`my_custom_label`标签的Job。 - `my_custom_label`:等同于`my_custom_label:host`。 -- `my_custom_label:vm:ubuntu-latest`:(仅为示例,未实现)使用带有`ubuntu-latest` ISO的虚拟机运行带有`my_custom_label`标签的Job。 ## 通信协议 -由于act runner是Gitea的独立部分,我们需要一种协议让Runner与Gitea实例进行通信。 +由于 runner 是 Gitea 的独立部分,我们需要一种协议让 Runner 与 Gitea 实例进行通信。 然而,我们不认为让Gitea监听一个新端口是个好主意。 相反,我们希望重用HTTP端口,这意味着我们需要一个与HTTP兼容的协议。 因此,我们选择使用基于HTTP的gRPC。 -我们使用[actions-proto-def](https://gitea.com/gitea/actions-proto-def) 和 [actions-proto-go](https://gitea.com/gitea/actions-proto-go) 进行连接。 +该协议定义在[actions-proto-def](https://gitea.com/gitea/actions-proto-def)中,其Go代码位于[actionslib](https://gitea.com/gitea/actionslib)。 有关 gRPC 的更多信息,请访问[其官方网站](https://grpc.io/)。 ## 网络架构 让我们来看一下整体的网络架构。 -这将帮助您解决一些问题,并解释为什么使用回环地址注册Runner是个不好的主意。 +这将帮助您解决一些问题,并解释为什么使用回环地址注册 Runner 是个不好的主意。 ![network](/images/usage/actions/network.png) 图片中标记了四个网络连接,并且箭头的方向表示建立连接的方向。 -### 连接 1,act runner到Gitea实例 +### 连接 1,runner 到 Gitea 实例 -act runner 必须能够连接到Gitea以接收任务并发送执行结果回来。 +Runner 必须能够连接到Gitea以接收任务并发送执行结果回来。 -### 连接 2,Job容器到Gitea实例 +### 连接 2,Job 容器到 Gitea 实例 即使Job容器位于同一台机器上,它们的网络命名空间与Runner不同。 举个例子,如果工作流中包含 `actions/checkout@v4`,Job容器需要连接到Gitea来获取代码。 @@ -93,11 +68,11 @@ act runner 必须能够连接到Gitea以接收任务并发送执行结果回来 如果您使用回环地址注册Runner,当Runner与Gitea在同一台机器上时,Runner可以连接到Gitea。 然而,如果Job容器尝试从本地主机获取代码,它将失败,因为Gitea不在同一个容器中。 -### 连接 3,act runner到互联网 +### 连接 3,runner 到互联网 -当您使用诸如 `actions/checkout@v4` 的一些Actions时,act runner下载的是脚本,而不是Job容器。 -默认情况下,它从[github.com](http://github.com/)下载,因此需要访问互联网。如果您设置的是 self, -那么默认将从您的当前Gitea实例下载,那么此步骤不需要连接到互联网。 +当您使用诸如 `actions/checkout@v4` 的一些Actions时, runner下载的是脚本,而不是Job容器。 +默认情况下,它从[github.com](https://github.com/)下载这些脚本,这需要访问互联网。 +如果将`DEFAULT_ACTIONS_URL`设置为`self`,或使用`uses: self:owner/repo@ref`,它会改为从您的Gitea实例下载。 它还默认从Docker Hub下载一些Docker镜像,这也需要互联网访问。 然而,互联网访问并不是绝对必需的。 diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/faq.md b/i18n/zh-cn/docs/current/usage/actions/faq.md similarity index 55% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/faq.md rename to i18n/zh-cn/docs/current/usage/actions/faq.md index eeb8e08d..61cd8c9d 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/faq.md +++ b/i18n/zh-cn/docs/current/usage/actions/faq.md @@ -27,34 +27,19 @@ DEFAULT_REPO_UNITS = ...,repo.actions ## 使用`actions/checkout@v4`等Actions时,Job容器会从何处下载脚本? -GitHub 上有成千上万个 [Actions 脚本](https://github.com/marketplace?type=actions)。 -当您编写 `uses: actions/checkout@v4` 时,它默认会从 [github.com/actions/checkout](https://github.com/actions/checkout) 下载脚本。 -那如果您想使用一些托管在其它平台上的脚本呢,比如在 gitea.com 上的? +默认从`https://github.com`下载,当`[actions].DEFAULT_ACTIONS_URL`为`self`时则从您自己的实例下载,参见[配置速查表](../../administration/config-cheat-sheet.md#actions-actions)。 -好消息是,您可以指定要从任何位置使用Actions的URL前缀。 -这是Gitea Actions中的额外语法。 -例如: +要使用其他位置的Action,请指明其主机: -- `uses: https://gitea.com/xxx/xxx@xxx` -- `uses: https://github.com/xxx/xxx@xxx` -- `uses: http://your_gitea_instance.com/xxx@xxx` - -注意,`https://`或`http://`前缀是必需的! - -这是与 GitHub Actions 的一个区别,GitHub Actions 只允许使用托管在 GitHub 上的 actions 脚本。 -但用户理应拥有权利去灵活决定如何运行 Actions。 - -另外,如果您希望您的 Runner 默认从您自己的 Gitea 实例下载 Actions,可以通过设置 `[actions].DEFAULT_ACTIONS_URL`进行配置。 -参见[配置速查表](../../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`,用于您自己的Gitea实例 ## 如何限制Runner的权限? -Runner仅具有连接到您的Gitea实例的权限。 -当任何Runner接收到要运行的Job时,它将临时获得与Job关联的仓库的有限权限。 -如果您想为Runner提供更多权限,允许它访问更多私有仓库或外部系统,您可以向其传递[密钥](usage/actions/secrets.md)。 - -对于 Actions 的细粒度权限控制是一项复杂的工作。 -在未来,我们将添加更多选项以使Gitea更可配置,例如允许对仓库进行更多写访问或对同一组织中的所有仓库进行读访问。 +Runner仅连接到您的Gitea实例。 +对于每个Job,Runner会获得一个仅限于该Job所属仓库的`GITEA_TOKEN`,参见[Actions Job令牌权限](token-permissions.md)。 +如需让Job访问更多私有仓库或外部系统,请向其传递[密钥](usage/actions/secrets.md)。 ## 如何避免被黑客攻击? @@ -73,21 +58,10 @@ Runner仅具有连接到您的Gitea实例的权限。 - 对于 fork 的拉取请求,需要获得批准才能运行Actions。参见[#22803](https://github.com/go-gitea/gitea/pull/22803)。 - 如果有人在[gitea.com](http://gitea.com/)为其仓库或组织注册自己的Runner,我们不会反对,只是不会在我们的组织中使用它。然而,他们应该注意确保该Runner不被他们不认识的其他用户使用。 -## act runner支持哪些操作系统? +## Runner 支持哪些操作系统? -它在Linux、macOS和Windows上运行良好。 -虽然理论上支持其他操作系统,但需要进一步测试。 - -需要注意的一点是,如果选择直接在主机上运行Job而不是在Job容器中运行,操作系统之间的环境差异可能会导致意外的失败。 - -例如,在大多数情况下,Windows上没有可用的bash,而act尝试默认使用bash运行脚本。 -因此,您需要在工作流文件中将默认shell指定为`powershell`,参考[defaults.run](https://docs.github.com/zh/actions/using-workflows/workflow-syntax-for-github-actions#defaultsrun)。 - -```yaml -defaults: - run: - shell: powershell -``` +官方发布了Linux、macOS和Windows的二进制文件。 +理论上,Go和Docker支持的其他系统也可以运行。 ## 为什么选择GitHub Actions?为什么不选择与GitLab CI/CD兼容的工具? @@ -99,49 +73,20 @@ defaults: ## 如果它在多个标签上运行,例如 `runs-on: [label_a, label_b]`,会发生什么? -这是有效的语法。 -它意味着它应该在具有`label_a` **和** `label_b`标签的Runner上运行,参考[GitHub Actions的工作流语法](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on)。 -不幸的是,act runner 并不支持这种方式。 -如上所述,我们将标签映射到环境: - -- `ubuntu` → `ubuntu:22.04` -- `centos` → `centos:8` - -但我们需要将标签组映射到环境,例如: - -- `[ubuntu]` → `ubuntu:22.04` -- `[with-gpu]` → `linux:with-gpu` -- `[ubuntu, with-gpu]` → `ubuntu:22.04_with-gpu` - -我们还需要重新设计任务分配给Runner的方式。 -具有`ubuntu`、`centos`或`with-gpu`的Runner并不一定表示它可以接受`[centos, with-gpu]`的Job。 -因此,Runner应该通知Gitea实例它只能接受具有 `[ubuntu]`、`[centos]`、`[with-gpu]` 和 `[ubuntu, with-gpu]`的Job。 -这不是一个技术问题,只是在早期设计中被忽视了。 -参见[runtime.go#L65](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L65)。 - -目前,act runner尝试匹配标签中的每一个,并使用找到的第一个匹配项。 +该Job会在拥有所有这些标签的Runner上运行,与[GitHub](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on)一致。 +Runner会使用这些标签中它所拥有的第一个标签对应的环境。 ## 代理标签和自定义标签对于Runner有什么区别? -![labels](/images/usage/actions/labels.png) - -代理标签是由Runner在注册过程中向Gitea实例报告的。 -而自定义标签则是由Gitea的管理员或组织或仓库的所有者手动添加的(取决于Runner所属的级别)。 - -然而,目前这方面的设计还有待改进,因为它目前存在一些不完善之处。 -您可以向已注册的Runner添加自定义标签,比如 `centos`,这意味着该Runner将接收具有`runs-on: centos`的Job。 -然而,Runner可能不知道要使用哪个环境来执行该标签,导致它使用默认镜像或导致逻辑死胡同。 -这个默认值可能与用户的期望不符。 -参见[runtime.go#L71](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L71)。 - -与此同时,如果您想更改Runner的标签,我们建议您重新注册Runner。 +Gitea已不再有自定义标签。 +Runner每次启动时都会声明其标签,标签来自`runner.labels`配置或注册时指定的标签,因此请在那里修改并重启Runner。 ## Gitea Actions runner会有更多的实现吗? -虽然我们希望提供更多的选择,但由于我们有限的人力资源,act runner将是唯一受支持的官方Runner。 -然而,无论您如何决定,Gitea 和act runner都是完全开源的,所以任何人都可以创建一个新的/更好的实现。 +虽然我们希望提供更多的选择,但由于我们有限的人力资源,runner 将是唯一受支持的官方 Runner。 +然而,无论您如何决定,Gitea 和 runner都是完全开源的,所以任何人都可以创建一个新的/更好的实现。 我们支持您的选择,无论您如何决定。 -如果您选择分支act runner来创建自己的版本,请在您认为您的更改对其他人也有帮助的情况下贡献这些更改。 +如果您选择分支 runner来创建自己的版本,请在您认为您的更改对其他人也有帮助的情况下贡献这些更改。 ## Gitea 支持哪些工作流触发事件? @@ -165,3 +110,11 @@ defaults: > 对于 `pull_request` 事件,在 [GitHub Actions](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request) 中 `ref` 是 `refs/pull/:prNumber/merge`,它指向这个拉取请求合并提交的一个预览。但是 Gitea 没有这种 reference。 > 因此,Gitea Actions 中 `ref` 是 `refs/pull/:prNumber/head`,它指向这个拉取请求的头分支而不是合并提交的预览。 + +## 如何共享私有仓库中的Actions和可复用工作流? + +前往仓库的**设置** > **Actions** > **常规**页面并添加协作所有者。 +协作所有者的私有仓库可以访问当前仓库中的Actions和工作流。 + +如需在同一用户或组织内共享,请改为在该用户或组织的**设置** > **Actions** > **常规** > **跨仓库访问**中添加这些私有仓库。 +参见[跨仓库访问](token-permissions.md#cross-repository-access)。 diff --git a/i18n/zh-cn/docs/current/usage/actions/openid-connect.md b/i18n/zh-cn/docs/current/usage/actions/openid-connect.md new file mode 100644 index 00000000..d345e063 --- /dev/null +++ b/i18n/zh-cn/docs/current/usage/actions/openid-connect.md @@ -0,0 +1,63 @@ +--- +date: "2026-08-23T00:00:00+00:00" +slug: "openid-connect" +sidebar_position: 40 +--- + +# OpenID Connect + +Job可以请求短期有效的OpenID Connect(OIDC)令牌来登录云服务商和其他服务,无需存储长期有效的密钥。这些令牌采用GitHub Actions的格式,因此`aws-actions/configure-aws-credentials`、`google-github-actions/auth`和`azure/login`等Action无需修改即可使用。 + + +## 信任Gitea + +在服务中将Gitea添加为OIDC身份提供方: + +- Issuer:`/api/actions/oidc` +- Audience:`/`,除非工作流请求了其他值 + +然后通过[`sub`声明](#claims)上的条件限制哪些工作流可以登录。 + +Gitea使用其在`/jwt/actions_oidc.pem`创建的密钥签名令牌。负载均衡器后的多个实例必须共享此文件。 + + +## 请求令牌 + +为工作流或Job授予`id-token`权限: + +```yaml +permissions: + id-token: write +``` + +默认权限从不包含此权限,来自fork拉取请求的Job也永远无法获得。所有者和仓库可以通过[最大令牌权限](token-permissions.md#maximum-token-permissions-clamping)禁用它。 + +上述Action会自行请求令牌。在脚本中,请使用`ACTIONS_ID_TOKEN_REQUEST_URL`和`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" +``` + +令牌位于响应的`value`字段中,五分钟后过期。 + + +## 声明 + +`sub`声明包含所有者和仓库的名称及ID,因此重命名或重新创建的仓库无法匹配已有的信任策略: + +```text +repo:@/@:ref: +repo:@/@:pull_request +``` + +`pull_request`事件使用第二种格式,其他所有事件(包括`pull_request_target`)使用第一种。 + +其他声明与GitHub相同,例如`repository`、`ref`、`sha`、`workflow_ref`和`job_workflow_ref`。位于`/api/actions/oidc/.well-known/openid-configuration`的发现文档列出了所有声明。 + +与GitHub Actions的区别: + +- 没有`environment`声明。 +- 拉取请求的运行使用`refs/pull//head`及其提交,而不是合并引用和合并提交。 +- `run_number`按仓库计数,而不是按工作流计数。 diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/overview.md b/i18n/zh-cn/docs/current/usage/actions/overview.md similarity index 87% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/overview.md rename to i18n/zh-cn/docs/current/usage/actions/overview.md index c3649841..c7b969ff 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/overview.md +++ b/i18n/zh-cn/docs/current/usage/actions/overview.md @@ -21,8 +21,8 @@ Gitea Actions与[GitHub Actions](https://github.com/features/actions)相似且 ## Runner 和其他CI/CD解决方案一样,Gitea不会自己运行Job,而是将Job委托给Runner。 -Gitea Actions的Runner被称为[act runner](https://gitea.com/gitea/act_runner),它是一个独立的程序,也是用Go语言编写的。 -它是基于[nektos/act](http://github.com/nektos/act)的一个[分支](https://gitea.com/gitea/act) 。 +Gitea Actions的Runner被称为[Gitea Runner](https://gitea.com/gitea/runner),它是一个独立的程序,也是用Go语言编写的。 +它的重要部分来自[nektos/act](http://github.com/nektos/act)的一个硬分支。 由于Runner是独立部署的,可能存在潜在的安全问题。 为了避免这些问题,请遵循两个简单的规则: diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/quickstart.md b/i18n/zh-cn/docs/current/usage/actions/quickstart.md similarity index 92% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/quickstart.md rename to i18n/zh-cn/docs/current/usage/actions/quickstart.md index 6153462d..2f5dc4b2 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/usage/actions/quickstart.md +++ b/i18n/zh-cn/docs/current/usage/actions/quickstart.md @@ -25,10 +25,10 @@ ENABLED=true ### 设置Runner -Gitea Actions需要[act runner](https://gitea.com/gitea/act_runner) 来运行Job。 +Gitea Actions需要[runner](https://gitea.com/gitea/runner) 来运行Job。 为了避免消耗过多资源并影响Gitea实例,建议您在与Gitea实例分开的机器上启动Runner。 -您可以使用[预构建的二进制文件](http://dl.gitea.com/act_runner)或[容器镜像](https://hub.docker.com/r/gitea/act_runner/tags)来设置Runner。 +您可以使用[预构建的二进制文件](http://dl.gitea.com/gitea-runner)或[容器镜像](https://hub.docker.com/r/gitea/runner/tags)来设置Runner。 在进一步操作之前,建议您先使用预构建的二进制文件以命令行方式运行它,以确保它与您的环境兼容,尤其是如果您在本地主机上运行Runner。 如果出现问题,这样调试起来会更容易。 @@ -40,7 +40,7 @@ Gitea Actions需要[act runner](https://gitea.com/gitea/act_runner) 来运行Job 在运行Runner之前,您需要使用以下命令将其注册到Gitea实例中: ```bash -./act_runner register --no-interactive --instance --token +gitea-runner register --no-interactive --instance --token ``` 需要两个必需的参数:`instance` 和 `token`。 @@ -52,10 +52,10 @@ Runner和Job容器(由Runner启动以执行Job)将连接到此地址。 如果不确定使用哪个地址,通常选择局域网地址即可。 `token` 用于身份验证和标识,例如 `P2U1U0oB4XaRCi8azcngmPCLbRpUGapalhmddh23`。 -它只能使用一次,并且不能用于注册多个Runner。 +每个令牌都可用于注册多个Runner。通过重置链接替换为新令牌后,旧令牌将失效。 您可以从以下位置获取不同级别的`token`,从而创建出相应级别的`runner` -- 实例级别:管理员设置页面,例如 `/admin/actions/runners`。 +- 实例级别:管理员设置页面,例如 `/-/admin/actions/runners`。 - 组织级别:组织设置页面,例如 `//settings/actions/runners`。 - 存储库级别:存储库设置页面,例如 `///settings/actions/runners`。 @@ -68,14 +68,14 @@ Runner和Job容器(由Runner启动以执行Job)将连接到此地址。 最后,是时候启动Runner了: ```bash -./act_runner daemon +gitea-runner daemon ``` 您可以在管理页面上看到新的Runner: ![view runner](/images/usage/actions/view-runner.png) -您可以通过访问[act runner](usage/actions/act-runner.md) 获取更多信息。 +您可以通过访问[Gitea Runner](runner) 获取更多信息。 ### 使用Actions diff --git a/i18n/zh-cn/docs/current/usage/actions/runner.md b/i18n/zh-cn/docs/current/usage/actions/runner.md new file mode 100644 index 00000000..631c05fb --- /dev/null +++ b/i18n/zh-cn/docs/current/usage/actions/runner.md @@ -0,0 +1,57 @@ +--- +date: "2023-05-24T15:00:00+08:00" +slug: "runner" +sidebar_position: 20 +aliases: + - /zh-cn/act-runner +--- + +# Runner + +本页面将介绍[Gitea Runner](https://gitea.com/gitea/runner),这是Gitea Actions的Runner。 + +:::tip +详细的安装、配置和使用说明,请参阅 [Gitea Runner 文档](/runner/)。 +::: + +## 获取注册令牌 + +### Runner级别 + +您可以在不同级别上注册Runner,它可以是: + +- 实例级别:Runner将为实例中的所有存储库运行Job。 +- 组织级别:Runner将为组织中的所有存储库运行Job。 +- 存储库级别:Runner将为其所属的存储库运行Job。 + +请注意,即使存储库具有自己的存储库级别Runner,它仍然可以使用实例级别或组织级别Runner。未来的版本可能提供更多对此进行更好控制的选项。 + +Runner级别决定了从哪里获取注册令牌。 + +- 实例级别:管理员设置页面,例如 `/-/admin/actions/runners`。 +- 组织级别:组织设置页面,例如 `//settings/actions/runners`。 +- 存储库级别:存储库设置页面,例如 `///settings/actions/runners`。 + +如果您无法看到设置页面,请确保您具有正确的权限并且已启用 Actions。 + +注册令牌的格式是一个随机字符串 `D0gvfu2iHfUjNqCYVljVyRV14fISpJxxxxxxxxxx`。 + +注册令牌也可以通过 Gitea 的 [命令行](../../administration/command-line.md#actions-generate-runner-token) 获得: + +``` +gitea --config /etc/gitea/app.ini actions generate-runner-token +``` + +用户也可以使用 `GITEA_RUNNER_REGISTRATION_TOKEN` 或 `GITEA_RUNNER_REGISTRATION_TOKEN_FILE` 环境变量以在 Gitea 启动时设置全局的注册令牌,例如: + +``` +openssl rand -hex 24 > /some-dir/runner-token +export GITEA_RUNNER_REGISTRATION_TOKEN_FILE=/some-dir/runner-token +./gitea --config ... +``` + +来自环境变量的令牌在通过 Web 界面或 API 重置(重新创建新令牌)前将一直有效。 + +令牌可用于注册多个 Runner,直到使用 Web 界面中的令牌重置链接将其撤销并替换为新令牌。 + +获取注册令牌后,请参阅 [Gitea Runner 文档](/runner/) 了解如何安装、配置和运行您的 Runner。 diff --git a/i18n/zh-cn/docs/current/usage/actions/scoped-workflows.md b/i18n/zh-cn/docs/current/usage/actions/scoped-workflows.md new file mode 100644 index 00000000..1000357c --- /dev/null +++ b/i18n/zh-cn/docs/current/usage/actions/scoped-workflows.md @@ -0,0 +1,119 @@ +--- +date: "2026-06-26T00:00:00+00:00" +slug: "scoped-workflows" +sidebar_position: 60 +--- + +# 作用域工作流 + +作用域工作流(Scoped Workflows)让你把 Actions 工作流集中维护在一个**源(source)**仓库中,并让它们自动在许多其他仓库上运行,而无需把工作流文件复制到每个仓库里。 + +提交到源仓库作用域工作流目录下的工作流文件,会在该源所适用的每个仓库(称为**消费方(consuming)**仓库)上运行。每次运行都在**消费方仓库自身的上下文**中执行:使用它的 runner、密钥、`GITEA_TOKEN` 和分支,而工作流**内容则读取自源仓库**。这适用于在组织或实例范围内强制推行共享 CI:代码检查、安全扫描、合规或策略检查等。 + +## 级别 + +源仓库可以在两个级别注册: + +- **所有者级别(Owner level)**:由组织或用户注册。该源的工作流会在该组织或用户拥有的每个仓库上运行。 +- **实例级别(Instance level)**:由站点管理员注册。该源的工作流会在实例上的**每一个**仓库上运行。 + +同一个仓库可以同时在两个级别注册;对于每个匹配的事件,它仍只会被评估一次。 + +:::note +实例级别的源适用于实例上的**每一个**仓库,且被设为必需(required)的源无法被选择退出(opt out)。检测会在每个仓库的每次事件上运行。请谨慎注册。 +::: + +## 配置 + +作用域工作流存放在一个与常规工作流分开的目录中,由 `app.ini` 中 `[actions]` 段的 `SCOPED_WORKFLOW_DIRS` 控制: + +```ini +[actions] +SCOPED_WORKFLOW_DIRS = .gitea/scoped_workflows +``` + +- 默认值为 `.gitea/scoped_workflows`。 +- 可以列出多个目录(以逗号分隔)。 +- **不得与** `WORKFLOW_DIRS`(常规工作流目录,默认为 `.gitea/workflows` 和 `.github/workflows`)**重叠**。 +- 留空意味着没有任何目录存放作用域工作流,因此不会找到也不会运行任何作用域工作流。设置页面仍会显示、源仍可注册,但不会有任何作用域工作流运行。 + +把作用域工作流放在它们自己的目录中,意味着源仓库**自身**的 Actions 不受影响:只有 `SCOPED_WORKFLOW_DIRS` 下的文件才会被当作作用域工作流。 + +## 从一个仓库提供作用域工作流 + +1. 在准备作为源的仓库中,把工作流文件提交到其**默认分支**上的作用域工作流目录下,例如 `.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. 将该仓库注册为源: + + - **组织**:*组织设置 -> Actions -> 作用域工作流* + - **用户**:*用户设置 -> Actions -> 作用域工作流* + - **实例(管理员)**:*管理后台 -> Actions -> 作用域工作流* + + 搜索并添加该仓库。此后,它的作用域工作流便会适用于该级别下的消费方仓库。 + +源仓库也在它自己的作用域内,因此它会像其他消费方一样在自身上运行这些工作流。 + +## 作用域工作流如何运行 + +- 该运行属于**消费方**仓库,使用它的 runner、密钥、`GITEA_TOKEN` 和 ref。它在那里的表现与普通运行一致,包括重跑、日志和提交状态。 +- 工作流**内容读取自源**仓库,并钉定在事件发生时源默认分支的 commit 上。 +- 检测使用消费方仓库的事件,因此工作流的 `on:` 触发器(例如 `push` 和 `pull_request`)必须与该事件匹配。 + +## 选择退出(Opting out) + +消费方仓库可以在其 **Actions** 页面(该工作流会显示在其源之下)禁用一个它不想要的作用域工作流。已被标记为**必需(required)**(见下文)的工作流,消费方仓库永远无法将其禁用,也无法选择退出。 + +## 必需工作流与合并门禁 + +在作用域工作流设置页面上,你可以把单个工作流标记为**必需(required)**,并为每个工作流给定一个或多个**状态检查模式(status-check patterns)**(每行一个 glob)。一个必需的作用域工作流: + +- 无法被消费方仓库禁用。 +- 会对合并请求(PR)形成合并门禁:消费方的 PR 只有在一个匹配**每一个**模式的提交状态都**通过**后才能合并(必须存在且通过,must-present-and-pass)。一个从不产生任何状态的必需检查会**阻止**合并,而不是被静默跳过,因此在消费方关闭 Actions 也无法绕过它。 + +作用域运行产生的状态检查 context 形如: + +``` +<源仓库全名>: <工作流显示名> / () +``` + +设置页面会为每个工作流预览这些 “Expected status checks(预期状态检查)”,并标记出与你的模式匹配的项,便于你确认模式是否正确。一种常见模式是对 job 和 event 使用通配符,例如 `my-org/ci-repo: Lint / *`。 + +强制范围: + +- 必需检查会在任何设有**分支保护规则**的目标分支上强制生效,即使该规则自身的状态检查处于关闭状态。 +- **没有**保护规则的目标分支不受门禁约束。 + +:::warning +只有运行在会产生提交状态的事件(`push`、`pull_request`、`pull_request_target`、`release`)上的工作流才能被设为必需。仅运行在 `workflow_dispatch`、`schedule` 或 `workflow_call` 等事件上的工作流不会产生任何状态,因此把它设为必需会**永久**阻止每一个消费方 PR 的合并。设置页面在这种情况下会向你发出警告。 +::: + +## 可复用工作流(`uses:`) + +作用域工作流可以调用可复用工作流: + +- **本地**引用(`uses: ./...` 或 `uses: $/...`)会相对于**源**仓库解析:即调用方工作流内容的来源仓库,而非消费方仓库。 +- **跨仓库**引用(`uses: owner/repo/...@ref` 或 `uses: self:owner/repo/...@ref`)会以**消费方仓库的**读取权限来解析。如果它指向一个私有仓库,请确保每个消费方仓库都能读取它,否则工作流会在那里失败。 + +可复用工作流可以放在源仓库的 `SCOPED_WORKFLOW_DIRS`(或 `WORKFLOW_DIRS`)之下。 + +## 安全注意事项 + +源仓库的工作流内容会在它所适用的每个仓库中执行,其步骤脚本及其输出会写入该仓库的 Actions 日志,任何能查看消费方仓库 Actions 的人都能读取这些日志。 + +- 因此,将一个**私有**仓库注册为源,会通过这些日志泄露其工作流逻辑。只应注册那些其工作流内容可以与每个消费方仓库共享的仓库。 + +## 限制 + +- 目前不支持将 `on: schedule` 和 `on: workflow_run` 作为作用域工作流触发器。 +- 作用域工作流内容读取自源的默认分支;源的其他分支不会被使用。 diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/actions/secrets.md b/i18n/zh-cn/docs/current/usage/actions/secrets.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/actions/secrets.md rename to i18n/zh-cn/docs/current/usage/actions/secrets.md diff --git a/i18n/zh-cn/docs/current/usage/actions/token-permissions.md b/i18n/zh-cn/docs/current/usage/actions/token-permissions.md new file mode 100644 index 00000000..fef7aacf --- /dev/null +++ b/i18n/zh-cn/docs/current/usage/actions/token-permissions.md @@ -0,0 +1,130 @@ +--- +date: "2026-03-19T00:00:00+01:00" +slug: "token-permissions" +sidebar_position: 30 +--- + +# Actions Job令牌权限(`GITEA_TOKEN`) + +每个Actions Job都会获得一个内置令牌(`GITEA_TOKEN`),可用于访问Gitea(通过HTTP(S)访问Git、API请求等)。 +本页面介绍Gitea如何决定该令牌可以执行哪些操作。 + +在工作流中,可以通过`${{ secrets.GITEA_TOKEN }}`使用该令牌。这些设置和`permissions:`仅影响`GITEA_TOKEN`(不影响个人访问令牌等其他密钥)。关于API调用,请参阅[API认证](../../development/api-usage.md#authentication)。 + + +## 权限来源 + +Gitea按以下顺序确定Job令牌的权限: + +1. Job级别的`permissions:`(`jobs..permissions`) +2. 工作流级别的`permissions:`(顶层) +3. 设置中的默认权限(所有者或仓库) + +然后,该结果会受到所配置的最大令牌权限的**限制**(见下文)。 + + +## 支持的工作流语法 + +Gitea支持与GitHub Actions兼容的`permissions:`关键字。 + + +### 标量值 + +```yaml +permissions: read-all # or: write-all +``` + + +### 按权限范围映射 + +```yaml +permissions: + contents: read + issues: write + pull-requests: none +``` + +每个权限范围的有效访问模式值为`read`、`write`和`none`。 + + +### 支持的权限范围 + +- `contents`(适用于`code`和`releases`) +- `code` +- `releases` +- `issues` +- `pull-requests` +- `actions` +- `wiki` +- `projects` +- `packages`(如果目标功能支持) +- `id-token`(`write`允许请求[OpenID Connect令牌](openid-connect.md),`read`不授予任何权限) + +如果同时指定了`contents`和更细粒度的权限范围(如`code`或`releases`),则该单元以更细粒度的权限范围为准。 + + +### 兼容性说明 + +Gitea支持GitHub Actions权限范围的一个子集。 +Gitea Actions目前不支持`statuses`、`checks`、`deployments`、`security-events`和`pages`等GitHub专有的权限范围。 + +Gitea还提供了一些仓库单元权限范围,它们在GitHub Actions中不作为独立的权限范围存在: + +- `code` +- `releases` +- `wiki` +- `projects` + + +## 默认权限模式 + +如果工作流和Job都没有定义`permissions:`,Gitea会使用所配置的默认模式: + +- **宽松**:对Job所属仓库的大多数单元拥有读写权限(向后兼容的默认值)。 +- **受限**:对Job所属仓库的`code`、`releases`和`packages`拥有只读权限,默认无权访问其他单元。 + +两种模式都不包含`id-token`。 + + +## 最大令牌权限(限制) + +您可以为每个仓库单元以及`id-token`配置最大权限。 +Job的实际权限按以下方式计算: + +`effective = min(requested, maximum)` + +这意味着工作流可以降低Job的权限,但不能超过您配置的最大权限。 +如果未配置最大权限,则所有权限范围的最大权限默认为`write`。 +在Gitea支持`id-token`之前保存的最大权限会拒绝`id-token`,直到您将其设为`write`。 + + +## 配置位置 + +您可以在以下位置配置默认权限和最大权限: + +- **用户/组织**:`Settings` → `Actions` → `General` +- **仓库**:`Settings` → `Actions` → `General` + - 对于组织中的仓库,可以遵循所有者级别的配置,也可以通过**覆盖所有者级别的配置**选择不遵循。 + +注意:仅在启用**仓库Actions**后,才会显示仓库级别的令牌权限设置。 + + +## Fork拉取请求 + +出于安全考虑,由fork拉取请求触发的工作流始终只拥有仓库内容的只读权限,与工作流的`permissions:`或设置无关。这些Job也无法获取OpenID Connect令牌。 + + +## 跨仓库访问 + +默认情况下,`GITEA_TOKEN`只能访问: + +- Job所属仓库(依据计算出的权限) +- 公开仓库(只读) + +默认拒绝访问其他私有仓库。 +用户或组织可以通过**设置 → Actions → 常规 → 跨仓库访问**,允许以只读方式访问选定的私有仓库。 + +私有仓库也可以通过**设置 → Actions → 常规**允许选定的协作所有者。 +这样,这些所有者的私有仓库便可读取当前私有仓库以供Actions使用,例如私有Actions和可复用工作流。 + +fork拉取请求的工作流永远不会获得对私有仓库的跨仓库访问权限,即使这些仓库已被列出。 diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/actions/variables.md b/i18n/zh-cn/docs/current/usage/actions/variables.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/actions/variables.md rename to i18n/zh-cn/docs/current/usage/actions/variables.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/agit-support.md b/i18n/zh-cn/docs/current/usage/agit-support.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/agit-support.md rename to i18n/zh-cn/docs/current/usage/agit-support.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/_category.json b/i18n/zh-cn/docs/current/usage/issues-prs/_category.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/_category.json rename to i18n/zh-cn/docs/current/usage/issues-prs/_category.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/issue-pull-request-templates.md b/i18n/zh-cn/docs/current/usage/issues-prs/issue-pull-request-templates.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/issue-pull-request-templates.md rename to i18n/zh-cn/docs/current/usage/issues-prs/issue-pull-request-templates.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/labels.md b/i18n/zh-cn/docs/current/usage/issues-prs/labels.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/labels.md rename to i18n/zh-cn/docs/current/usage/issues-prs/labels.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/linked-references.md b/i18n/zh-cn/docs/current/usage/issues-prs/linked-references.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/linked-references.md rename to i18n/zh-cn/docs/current/usage/issues-prs/linked-references.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/merge-message-templates.md b/i18n/zh-cn/docs/current/usage/issues-prs/merge-message-templates.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/issues-prs/merge-message-templates.md rename to i18n/zh-cn/docs/current/usage/issues-prs/merge-message-templates.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/version-1.24/usage/pull-request.md b/i18n/zh-cn/docs/current/usage/issues-prs/pull-request.md similarity index 97% rename from i18n/zh-cn/docusaurus-plugin-content-docs/version-1.24/usage/pull-request.md rename to i18n/zh-cn/docs/current/usage/issues-prs/pull-request.md index 01b7a7df..5a8ff375 100644 --- a/i18n/zh-cn/docusaurus-plugin-content-docs/version-1.24/usage/pull-request.md +++ b/i18n/zh-cn/docs/current/usage/issues-prs/pull-request.md @@ -57,4 +57,4 @@ WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP] ## 合并请求模板 -有关合并请求模板的更多信息请您移步 : [工单与合并请求模板](usage/issue-pull-request-templates.md) +有关合并请求模板的更多信息请您移步 : [工单与合并请求模板](issue-pull-request-templates.md) diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/_category_.json b/i18n/zh-cn/docs/current/usage/packages/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/_category_.json rename to i18n/zh-cn/docs/current/usage/packages/_category_.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/alpine.md b/i18n/zh-cn/docs/current/usage/packages/alpine.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/alpine.md rename to i18n/zh-cn/docs/current/usage/packages/alpine.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/cargo.md b/i18n/zh-cn/docs/current/usage/packages/cargo.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/cargo.md rename to i18n/zh-cn/docs/current/usage/packages/cargo.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/chef.md b/i18n/zh-cn/docs/current/usage/packages/chef.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/chef.md rename to i18n/zh-cn/docs/current/usage/packages/chef.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/composer.md b/i18n/zh-cn/docs/current/usage/packages/composer.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/composer.md rename to i18n/zh-cn/docs/current/usage/packages/composer.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/conan.md b/i18n/zh-cn/docs/current/usage/packages/conan.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/conan.md rename to i18n/zh-cn/docs/current/usage/packages/conan.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/conda.md b/i18n/zh-cn/docs/current/usage/packages/conda.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/conda.md rename to i18n/zh-cn/docs/current/usage/packages/conda.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/container.md b/i18n/zh-cn/docs/current/usage/packages/container.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/container.md rename to i18n/zh-cn/docs/current/usage/packages/container.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/cran.md b/i18n/zh-cn/docs/current/usage/packages/cran.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/cran.md rename to i18n/zh-cn/docs/current/usage/packages/cran.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/debian.md b/i18n/zh-cn/docs/current/usage/packages/debian.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/debian.md rename to i18n/zh-cn/docs/current/usage/packages/debian.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/generic.md b/i18n/zh-cn/docs/current/usage/packages/generic.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/generic.md rename to i18n/zh-cn/docs/current/usage/packages/generic.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/go.md b/i18n/zh-cn/docs/current/usage/packages/go.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/go.md rename to i18n/zh-cn/docs/current/usage/packages/go.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/helm.md b/i18n/zh-cn/docs/current/usage/packages/helm.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/helm.md rename to i18n/zh-cn/docs/current/usage/packages/helm.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/maven.md b/i18n/zh-cn/docs/current/usage/packages/maven.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/maven.md rename to i18n/zh-cn/docs/current/usage/packages/maven.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/npm.md b/i18n/zh-cn/docs/current/usage/packages/npm.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/npm.md rename to i18n/zh-cn/docs/current/usage/packages/npm.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/nuget.md b/i18n/zh-cn/docs/current/usage/packages/nuget.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/nuget.md rename to i18n/zh-cn/docs/current/usage/packages/nuget.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/overview.md b/i18n/zh-cn/docs/current/usage/packages/overview.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/overview.md rename to i18n/zh-cn/docs/current/usage/packages/overview.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/pub.md b/i18n/zh-cn/docs/current/usage/packages/pub.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/pub.md rename to i18n/zh-cn/docs/current/usage/packages/pub.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/pypi.md b/i18n/zh-cn/docs/current/usage/packages/pypi.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/pypi.md rename to i18n/zh-cn/docs/current/usage/packages/pypi.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/rpm.md b/i18n/zh-cn/docs/current/usage/packages/rpm.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/rpm.md rename to i18n/zh-cn/docs/current/usage/packages/rpm.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/rubygems.md b/i18n/zh-cn/docs/current/usage/packages/rubygems.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/rubygems.md rename to i18n/zh-cn/docs/current/usage/packages/rubygems.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/storage.md b/i18n/zh-cn/docs/current/usage/packages/storage.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/storage.md rename to i18n/zh-cn/docs/current/usage/packages/storage.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/swift.md b/i18n/zh-cn/docs/current/usage/packages/swift.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/swift.md rename to i18n/zh-cn/docs/current/usage/packages/swift.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/vagrant.md b/i18n/zh-cn/docs/current/usage/packages/vagrant.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/packages/vagrant.md rename to i18n/zh-cn/docs/current/usage/packages/vagrant.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/_category_.json b/i18n/zh-cn/docs/current/usage/repository/_category_.json similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/_category_.json rename to i18n/zh-cn/docs/current/usage/repository/_category_.json diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/clone-filter.md b/i18n/zh-cn/docs/current/usage/repository/clone-filter.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/clone-filter.md rename to i18n/zh-cn/docs/current/usage/repository/clone-filter.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/incoming-email.md b/i18n/zh-cn/docs/current/usage/repository/incoming-email.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/incoming-email.md rename to i18n/zh-cn/docs/current/usage/repository/incoming-email.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/profile-readme.md b/i18n/zh-cn/docs/current/usage/repository/profile-readme.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/profile-readme.md rename to i18n/zh-cn/docs/current/usage/repository/profile-readme.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/push.md b/i18n/zh-cn/docs/current/usage/repository/push.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/push.md rename to i18n/zh-cn/docs/current/usage/repository/push.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/repo-mirror.md b/i18n/zh-cn/docs/current/usage/repository/repo-mirror.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/repo-mirror.md rename to i18n/zh-cn/docs/current/usage/repository/repo-mirror.md diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/template-repositories.md b/i18n/zh-cn/docs/current/usage/repository/template-repositories.md similarity index 100% rename from i18n/zh-cn/docusaurus-plugin-content-docs/current/usage/repository/template-repositories.md rename to i18n/zh-cn/docs/current/usage/repository/template-repositories.md diff --git a/i18n/zh-cn/docs/current/usage/repository/webhooks.md b/i18n/zh-cn/docs/current/usage/repository/webhooks.md new file mode 100644 index 00000000..3596adc1 --- /dev/null +++ b/i18n/zh-cn/docs/current/usage/repository/webhooks.md @@ -0,0 +1,720 @@ +--- +date: "2016-12-01T16:00:00+02:00" +slug: "webhooks" +sidebar_position: 30 +aliases: + - /zh-cn/webhooks +--- + +# Webhooks + +Gitea 可以为仓库活动发送出站 Webhook。仓库级 Webhook 由仓库管理员在 +`/:username/:reponame/settings/hooks` 中配置。组织、用户和系统管理级别 +也有对应的 Webhook 配置页面。 + +Webhook 配置支持四种作用域: + +- `仓库 Webhook`:仅对单个仓库中的活动触发。 +- `组织 Webhook`:对该组织拥有的仓库中的活动触发。 +- `用户 Webhook`:对该用户拥有的仓库中的活动触发。 +- `系统 Webhook`:对实例中的所有符合条件的活动触发。 + +Gitea 还支持由管理员定义的 `默认 Webhook`。它并不是额外的投递作用域, +而是会在新仓库创建时被复制到仓库中,之后按普通仓库 Webhook 的方式工作。 + +Gitea 支持以下出站 Webhook 集成: + +- Gitea +- Gogs +- Slack +- Discord +- Dingtalk +- Telegram +- Microsoft Teams +- Feishu +- Matrix +- Wechatwork +- Packagist + +`Gitea` 和 `Gogs` 类型会发送通用 Webhook 负载。上面列出的聊天和服务集成 +会将同一个内部事件转换为各自服务所需的请求体格式。 + +本页分为三个部分: + +- `配置`:如何配置 Webhook 设置,例如 URL、密钥、分支过滤器和授权头。 +- `投递`:Gitea 如何发送 Webhook 请求、会携带哪些请求头,以及如何校验投递。 +- `事件`:Gitea 会投递哪些事件,以及每个事件包含哪些顶层 payload 参数。 + +## 配置 + +本节介绍在创建或编辑 Webhook 时可以设置的选项。 + +### 配置 Webhook + +创建 Webhook 时,主要配置项包括: + +- `Target URL`:接收投递的目标地址。 +- `HTTP Method`:通用 Webhook 通常使用 `POST`。 +- `POST Content Type`:通用 Webhook 可使用 `application/json` 或 + `application/x-www-form-urlencoded`。 +- `Secret`:用于对原始请求体进行 HMAC 签名。 +- `Authorization Header`:可选的自定义 `Authorization` 请求头,会随每次请求发送。 +- `Branch Filter`:可选的分支或标签过滤规则。 +- `Trigger On`:`Push Events`、`All Events` 或自定义事件选择。 +- `Active`:是否启用该 Webhook。 + +:::note +旧示例里可能仍会在 JSON payload 中看到 `secret` 字段。当前版本的 Gitea +不会再把 Webhook 密钥放进 payload 正文中。请始终通过签名请求头来验证请求。 +::: + +### 分支过滤器 + +分支过滤器使用与 +[`github.com/gobwas/glob`](https://pkg.go.dev/github.com/gobwas/glob#Compile) +兼容的 glob 语法。 + +- 空值、`*` 或 `**` 表示匹配全部。 +- 像 `main` 这样的普通分支名会匹配该分支。 +- 也支持 `refs/tags/v*` 这样的完整 ref。 +- 支持 `{main,release/*}` 这样的花括号表达式。 +- 过滤器只对带 git ref 的事件生效,例如 `create`、`delete` 和 `push`。 +- 不带 ref 的事件,例如 issue 或 release,会忽略分支过滤器。 + +示例: + +- `main` +- `{main,feature/*}` +- `{refs/heads/feature/*,refs/tags/release/*}` + +### 授权头 + +Gitea 可以配置为在每次 Webhook 投递时发送自定义 +[Authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization)。 +它与 Webhook 密钥是相互独立的: + +- 使用密钥通过 HMAC 校验请求完整性。 +- 当接收端需要应用层认证时,使用 `Authorization` 请求头。 + +## 投递 + +本节说明 Gitea 如何发送 Webhook 投递,以及接收端如何识别和验证这些请求。 + +### 投递行为 + +- Webhook 会通过 HTTP 异步投递。 +- 通用 `Gitea` 和 `Gogs` Webhook 支持 `POST` 与 `GET`;通常应使用 `POST`。 +- 对于 `POST` 请求,payload 可以直接作为 JSON + (`application/json`)发送,也可以放在名为 `payload` 的表单字段中 + (`application/x-www-form-urlencoded`)。 +- 某些特定服务的集成可能会使用该服务要求的 HTTP 方法和请求体格式。 + +### 投递请求头 + +每次投递都包含唯一的 delivery ID 和事件请求头。对于兼容 GitHub 的集成, +Gitea 也会同时发送对应的 GitHub 和 Gogs 风格请求头。 + +| 请求头 | 说明 | +| --- | --- | +| `X-Gitea-Delivery` | 本次投递尝试的唯一 UUID。 | +| `X-Gitea-Event` | 规范化事件名,例如 `push`、`issues` 或 `pull_request`。 | +| `X-Gitea-Event-Type` | 更具体的事件类型,例如 `issue_assign` 或 `pull_request_review_comment`。 | +| `X-Gitea-Signature` | 原始请求体的十六进制 HMAC-SHA256 值,不带前缀。 | +| `X-Gitea-Hook-Installation-Target-Type` | Webhook 定义所在范围,通常是 `repository`、`organization`、`user` 或 `system`。默认 Webhook 会先复制到仓库后再投递,因此通常会表现为 `repository`。 | +| `X-Gogs-Delivery`、`X-Gogs-Event`、`X-Gogs-Event-Type`、`X-Gogs-Signature` | 与 Gitea 对应请求头值相同的兼容请求头。 | +| `X-GitHub-Delivery`、`X-GitHub-Event`、`X-GitHub-Event-Type` | GitHub 风格兼容请求头。 | +| `X-GitHub-Hook-Installation-Target-Type` | GitHub 风格的 Webhook 作用域请求头。 | +| `X-Hub-Signature` | GitHub 兼容的 HMAC-SHA1 请求头,格式为 `sha1=`。 | +| `X-Hub-Signature-256` | GitHub 兼容的 HMAC-SHA256 请求头,格式为 `sha256=`。 | + +如果未配置密钥,签名请求头仍然会存在,但摘要值为空。 + +#### `Event` 与 `Event-Type` + +某些 Gitea Webhook 订阅会被归类到同一个规范化事件名下。例如,issue 指派 +投递会归类到 issue 事件组: + +```http +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign +``` + +如果你需要知道真正触发投递的具体事件类型,请使用 `X-Gitea-Event-Type`。 + +#### 校验投递 + +Gitea 会使用你的 Webhook 密钥对原始请求体进行签名。要校验一次投递: + +1. 按接收到的原始内容读取请求体。 +2. 使用 Webhook 密钥计算 HMAC-SHA256 摘要。 +3. 将结果与 `X-Gitea-Signature` 或 GitHub 兼容的 + `X-Hub-Signature-256` 进行比较。 +4. 尽量使用常量时间比较函数。 + +注意事项: + +- `X-Gitea-Signature` 仅包含小写十六进制的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但带有 `sha256=` 前缀。 +- `X-Hub-Signature` 也会出于兼容性目的发送,其算法是 SHA-1。 +- 在完成签名校验之前,不应先解析 JSON 或修改请求体。 + +##### PHP 示例 + +下面的示例演示如何校验以 `application/json` 发送的通用 `Gitea` Webhook。 + +```php +`。 | +| `X-Hub-Signature-256` | GitHub 兼容的 HMAC-SHA256 请求头,格式为 `sha256=`。 | + +如果未配置密钥,签名请求头仍然会存在,但摘要值为空。 + +#### `Event` 与 `Event-Type` + +某些 Gitea Webhook 订阅会被归类到同一个规范化事件名下。例如,issue 指派 +投递会归类到 issue 事件组: + +```http +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign +``` + +如果你需要知道真正触发投递的具体事件类型,请使用 `X-Gitea-Event-Type`。 + +#### 校验投递 + +Gitea 会使用你的 Webhook 密钥对原始请求体进行签名。要校验一次投递: + +1. 按接收到的原始内容读取请求体。 +2. 使用 Webhook 密钥计算 HMAC-SHA256 摘要。 +3. 将结果与 `X-Gitea-Signature` 或 GitHub 兼容的 + `X-Hub-Signature-256` 进行比较。 +4. 尽量使用常量时间比较函数。 + +注意事项: + +- `X-Gitea-Signature` 仅包含小写十六进制的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但带有 `sha256=` 前缀。 +- `X-Hub-Signature` 也会出于兼容性目的发送,其算法是 SHA-1。 +- 在完成签名校验之前,不应先解析 JSON 或修改请求体。 + +##### PHP 示例 + +下面的示例演示如何校验以 `application/json` 发送的通用 `Gitea` Webhook。 + +```php + gitea-db.sql +mysqldump -u$USER -p$PASS --databases $DATABASE > gitea-db.sql # postgres pg_dump -U $USER $DATABASE > gitea-db.sql ``` @@ -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 diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/version-1.25/administration/cmd-embedded.md b/i18n/zh-cn/docs/version-1.26/administration/cmd-embedded.md similarity index 99% rename from i18n/zh-tw/docusaurus-plugin-content-docs/version-1.25/administration/cmd-embedded.md rename to i18n/zh-cn/docs/version-1.26/administration/cmd-embedded.md index ba2adb21..a2d2dc7e 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/version-1.25/administration/cmd-embedded.md +++ b/i18n/zh-cn/docs/version-1.26/administration/cmd-embedded.md @@ -4,7 +4,7 @@ slug: "cmd-embedded" sidebar_position: 20 aliases: - - /zh-tw/cmd-embedded + - /zh-cn/cmd-embedded --- # 嵌入资源提取工具 diff --git a/i18n/zh-tw/docusaurus-plugin-content-docs/current/administration/command-line.md b/i18n/zh-cn/docs/version-1.26/administration/command-line.md similarity index 99% rename from i18n/zh-tw/docusaurus-plugin-content-docs/current/administration/command-line.md rename to i18n/zh-cn/docs/version-1.26/administration/command-line.md index e3dbddd4..e7a563cb 100644 --- a/i18n/zh-tw/docusaurus-plugin-content-docs/current/administration/command-line.md +++ b/i18n/zh-cn/docs/version-1.26/administration/command-line.md @@ -4,7 +4,7 @@ slug: "command-line" sidebar_position: 1 aliases: - - /zh-tw/command-line + - /zh-cn/command-line --- # 命令行 diff --git a/i18n/zh-cn/docusaurus-plugin-content-docs/version-1.24/administration/config-cheat-sheet.md b/i18n/zh-cn/docs/version-1.26/administration/config-cheat-sheet.md similarity index 82% rename from i18n/zh-cn/docusaurus-plugin-content-docs/version-1.24/administration/config-cheat-sheet.md rename to i18n/zh-cn/docs/version-1.26/administration/config-cheat-sheet.md index ce3e64bd..91237ec5 100644 --- a/i18n/zh-cn/docusaurus-plugin-content-docs/version-1.24/administration/config-cheat-sheet.md +++ b/i18n/zh-cn/docs/version-1.26/administration/config-cheat-sheet.md @@ -23,10 +23,10 @@ aliases: 本文档使用以下约定: -- `[section].FOO_BAR` 或 `[section]FOO_BAR`: 一个位于 INI 文件 `[section]` 段中的配置项。 -- `FooBar`: 这是一个 Gitea 内部变量,不是一个配置项,仅用于描述相关逻辑。 -- `$FOO_BAR`: 这是一个环境变量,Gitea 可能会使用它的值,但是它不能直接用于配置文件中。 -- `{FOO_BAR}/something` 或 `{FooBar}/something`: 这个值会默认使用配置项 `FOO_BAR` 或者内部变量 `FooBar`。 +* `[section].FOO_BAR` 或 `[section]FOO_BAR`: 一个位于 INI 文件 `[section]` 段中的配置项。 +* `FooBar`: 这是一个 Gitea 内部变量,不是一个配置项,仅用于描述相关逻辑。 +* `$FOO_BAR`: 这是一个环境变量,Gitea 可能会使用它的值,但是它不能直接用于配置文件中。 +* `{FOO_BAR}/something` 或 `{FooBar}/something`: 这个值会默认使用配置项 `FOO_BAR` 或者内部变量 `FooBar`。 **注意:** 修改完配置文件后,需要重启 Gitea 服务才能生效。 @@ -113,6 +113,7 @@ aliases: - `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: 允许非管理员用户删除未被认领的仓库。 - `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: 不允许从用户界面下载源代码存档文件。 - `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT`: **true**: 允许无限制得派生仓库。 +- `ALLOW_FORK_INTO_SAME_OWNER`: **false**: 允许将仓库派生到同一所有者(用户或组织)中。此功能为实验性功能,尚未完全测试,将来可能会更改。 ### 仓库 - 编辑器 (`repository.editor`) @@ -134,7 +135,8 @@ aliases: - `DEFAULT_MERGE_MESSAGE_OFFICIAL_APPROVERS_ONLY`: **true**: 在默认合并消息中,仅包括官方允许审查的审批者。 - `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`: **false**: 在默认的 squash 合并消息中,包括构成拉取请求的所有提交的提交消息。 - `ADD_CO_COMMITTER_TRAILERS`: **true**: 如果提交者与作者不匹配,在合并提交消息中添加`co-authored-by`和`co-committed-by`标记。 -- `TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY`:使用三方合并方法测试`PR Patch`以发现是否存在冲突。如果此设置`true`,将使用`git apply`重新测试冲突的`PR Pathch` - 这是 1.18(和之前版本)中的先前行为,但效率相对较低。如果发现需要此设置,请报告。 +- `RETARGET_CHILDREN_ON_MERGE`: **true**: 当父合并请求被合并时,将子合并请求重新定向到父合并请求的目标分支。仅适用于头分支和基分支指向同一仓库的已合并合并请求。 +- `DEFAULT_DELETE_BRANCH_AFTER_MERGE`: **false**: 为新仓库设置"合并后默认删除合并请求分支"的默认值。 ### 仓库 - 工单 (`repository.issue`) @@ -153,6 +155,8 @@ aliases: - `ALLOWED_TYPES`: **_empty_**: 允许发布的文件类型列表,用逗号分隔 。如压缩包类型(`.zip`), mime 类型 (`text/plain`) ,也支持通配符 (`image/*`, `audio/*`, `video/*`)。 空值或者 `*/*` 代表允许所有类型。 - `DEFAULT_PAGING_NUM`: **10**: 默认的发布版本页面分页大小 +- `FILE_MAX_SIZE`: **2048**: 版本发布附件的最大文件大小限制(MB) +- `MAX_FILES`: **5**: 版本发布一次最多上传的附件数量。 - 关于版本发布相关的附件设置,详见`附件`部分。 ### 仓库 - Signing (`repository.signing`) @@ -216,17 +220,24 @@ aliases: - `DEFAULT_THEME`: **gitea-auto**: 在 Gitea 安装时候设置的默认主题,自定义的主题可以通过 `{CustomPath}/public/assets/css/theme-*.css` 提供。 - `SHOW_USER_EMAIL`: **true**: 用户的电子邮件是否应该显示在`Explore Users`页面中。 - `THEMES`: **_empty_**: 所有可用的主题(由 `{CustomPath}/public/assets/css/theme-*.css` 提供)。允许用户选择个性化的主题, +- `FILE_ICON_THEME`: **material**: 文件图标主题(basic/material)。 +- `FOLDER_ICON_THEME`: **basic**: 文件夹图标主题(basic/material)。 - `MAX_DISPLAY_FILE_SIZE`: **8388608**: 能够显示文件的最大大小(默认为 8MiB)。 +- `AMBIGUOUS_UNICODE_DETECTION`: **true**: 检测文件内容中的歧义 Unicode 字符并在界面上显示警告。 - `REACTIONS`: 用户可以在问题(Issue)、Pull Request(PR)以及评论中选择的所有可选的反应。 这些值可以是表情符号别名(例如::smile:)或 Unicode 表情符号。 对于自定义的反应,在 public/assets/img/emoji/ 目录下添加一个紧密裁剪的正方形图像,文件名为 reaction_name.png。 +- `REACTION_MAX_USER_NUM`: **10**: 更改在反应工具提示中显示的用户数量(鼠标悬停时触发)。 - `CUSTOM_EMOJIS`: **gitea, codeberg, gitlab, git, github, gogs**: 不在 utf8 标准中定义的额外表情符号。 默认情况下,我们支持 Gitea 表情符号(:gitea:)。要添加更多表情符号,请将它们复制到 public/assets/img/emoji/ 目录下, 并将其添加到此配置中。 +- `ENABLED_EMOJIS`: **_empty_**: 以逗号分隔的启用表情符号列表,例如:"smile, thumbsup, thumbsdown"。留空以启用所有表情符号。 - `DEFAULT_SHOW_FULL_NAME`: **false**: 是否在可能的情况下显示用户的全名。如果没有设置全名,则将使用用户名。 - `SEARCH_REPO_DESCRIPTION`: **true**: 是否在探索页面上的仓库搜索中搜索描述。 - `ONLY_SHOW_RELEVANT_REPOS`: **false** 在没有指定关键字并使用默认排序时,是否仅在探索页面上显示相关的仓库。 如果一个仓库是分叉或者没有元数据(没有描述、图标、主题),则被视为不相关的仓库。 +- `EXPLORE_PAGING_DEFAULT_SORT`: **recentupdate**: 更改探索页面的排序类型。有效值为 "recentupdate"、"alphabetically"、"reverselastlogin"、"newest" 和 "oldest"。 +- `PREFERRED_TIMESTAMP_TENSE`: **mixed**: 所有时间戳应呈现的时态。可选值为 `absolute` 时间(即 1970-01-01, 11:59)和 `mixed`。`mixed` 表示大部分时间戳以相对时间显示(即 2 天前)。 ### 界面 - 管理员 (`ui.admin`) @@ -264,17 +275,21 @@ aliases: ## Markdown (`markdown`) -- `ENABLE_HARD_LINE_BREAK_IN_COMMENTS`: **true**: 在评论中将软换行符呈现为硬换行符, - 这意味着段落之间的单个换行符将导致换行, - 并且不需要在段落后添加尾随空格来强制换行。 -- `ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS`: **false**: 在文档中将软换行符呈现为硬换行符, - 这意味着段落之间的单个换行符将导致换行, - 并且不需要在段落后添加尾随空格来强制换行。 +- `RENDER_OPTIONS_COMMENT`: **short-issue-pattern, new-line-hard-break**: 自定义不同上下文的渲染选项。 + 设置为 "none" 以禁用默认值,或使用逗号分隔的列表: + - short-issue-pattern: 识别 "#123" 工单引用并将其渲染为指向工单的链接 + - new-line-hard-break: 将软换行符渲染为硬换行符,这意味着段落之间的单个换行符将导致换行, + 并且不需要在段落后添加尾随空格来强制换行。 +- `RENDER_OPTIONS_WIKI`: **short-issue-pattern**: 参见 RENDER_OPTIONS_COMMENT +- `RENDER_OPTIONS_REPO_FILE`: **_empty_**: 参见 RENDER_OPTIONS_COMMENT - `CUSTOM_URL_SCHEMES`: 使用逗号分隔的列表(ftp、git、svn)来指示要在 Markdown 中呈现的附加 URL 超链接。 以 http 和 https 开头的 URL 始终显示。 如果此条目为空,则允许所有 URL 方案。 - `FILE_EXTENSIONS`: **.md,.markdown,.mdown,.mkd,.livemd**: 应呈现/编辑为 Markdown 的文件扩展名列表。使用逗号分隔扩展名。要将没有任何扩展名的文件呈现为 Markdown,请只需放置一个逗号。 - `ENABLE_MATH`: **true**: 启用对`\(...\)`, `\[...\]`, `$...$`和`$$...$$` 作为数学块的检测。 +- `MATH_CODE_BLOCK_DETECTION`: **inline-dollar,block-dollar**: 启用数学代码块检测的分隔符。 + 设置为 "none" 以禁用全部,或使用逗号分隔的列表:inline-dollar, inline-parentheses, block-dollar, block-square-brackets。 + 默认值遵循 GitHub 的行为。 ## 服务器 (`server`) @@ -292,6 +307,7 @@ aliases: 虽然它的默认值是 "legacy"(避免影响老的用户),大多数实例都应当使用 "auto" 行为,尤其是 Gitea 实例需要在容器网络中被访问的场景。 - "legacy": 当 "X-Forwarded-Proto" 请求头存在的时候,使用 "Host" 请求头生成公共 URL,否则使用 "ROOT_URL"。 - "auto": 总是使用 "Host" 请求头生成公共 URL,如果 "X-Forwarded-Proto" 请求头存在也会使用它。如果没有 "Host" 请求头则使用 "ROOT_URL"。 + - "never": 总是使用 "ROOT_URL" 生成公共 URL,不从请求头进行检测。 - `STATIC_URL_PREFIX`: **_empty_**: 覆盖此选项以从不同的 URL 请求静态资源。 这包括 CSS 文件、图片、JS 文件和 Web 字体。 @@ -364,12 +380,14 @@ aliases: - `PPROF_DATA_PATH`: **_`AppWorkPath`_/data/tmp/pprof**: `PPROF_DATA_PATH`,当您将 Gitea 作为服务启动时,请使用绝对路径。 - `LANDING_PAGE`: **home**: 未经身份验证用户的登录页面 \[home, explore, organizations, login, **custom**]。其中 custom 可以是任何 URL,例如 "/org/repo" 或甚至是 `https://anotherwebsite.com`。 - `LFS_START_SERVER`: **false**: 启用 Git LFS 支持。 +- `LFS_ALLOW_PURE_SSH`: **false**: 启用 Git LFS 纯 SSH 协议支持。当前默认禁用,参见 [Git LFS 支持](administration/git-lfs-support.md)。 - `LFS_CONTENT_PATH`: **`{APP_DATA_PATH}/lfs`**: 默认的 LFS 内容路径(如果它在本地存储中)。**已弃用**,请使用 `[lfs]` 中的设置。 - `LFS_JWT_SECRET`: **_empty_**: LFS 身份验证密钥,将其更改为唯一的字符串。你可以通过 Gitea 子命令来生成此字符串。转到 [Command Line](administration/command-line.md#generate)。 - `LFS_JWT_SECRET_URI`: **_empty_**: 代替在配置中定义 LFS_JWT_SECRET,可以使用此配置选项为 Gitea 提供包含密钥的文件的路径(示例值:`file:/etc/gitea/lfs_jwt_secret`)。 - `LFS_HTTP_AUTH_EXPIRY`: **24h**: LFS 身份验证的有效期,以 time.Duration 表示,超过此期限的推送可能会失败。 - `LFS_MAX_FILE_SIZE`: **0**: 允许的最大 LFS 文件大小(以字节为单位,设置为 0 为无限制)。 - `LFS_LOCKS_PAGING_NUM`: **50**: 每页返回的最大 LFS 锁定数。 +- `LFS_MAX_BATCH_SIZE`: **0**: 客户端可通过 LFS 批量 API 请求的最大 LFS 指针数量。零为默认行为,允许任意大小的批量请求。 - `REDIRECT_OTHER_PORT`: **false**: 如果为 true 并且 `PROTOCOL` 为 https,则允许将 http 请求重定向到 Gitea 监听的 https 端口的 `PORT_TO_REDIRECT`。 - `REDIRECTOR_USE_PROXY_PROTOCOL`: **`{USE_PROXY_PROTOCOL}`**: 在连接到 https 重定向器时,需要 PROXY 协议头。 - `PORT_TO_REDIRECT`: **80**: http 重定向服务监听的端口。当 `REDIRECT_OTHER_PORT` 为 true 时使用。 @@ -426,6 +444,7 @@ aliases: - `NAME`: **gitea**: 数据库名称。 - `USER`: **root**: 数据库用户名。 - `PASSWD`: **_empty_**: 数据库密码。如果密码包含特殊字符,请使用 \`your password\` 或 """your password"""。 +- `CHARSET_COLLATION`: **_empty_**:(仅限 MySQL/MSSQL)Gitea 期望使用区分大小写的排序规则。留空以使用 Gitea 决定的默认排序规则。除非您明确知道需要什么,否则不要更改它。 - `SCHEMA`: **_empty_**: 对于 PostgreSQL,如果与 "public" 不同的模式。模式必须事先存在,用户必须对其具有创建特权,并且用户搜索路径必须设置为首先查找模式(例如 `ALTER USER user SET SEARCH_PATH = schema_name,"$user",public;`)。 - `SSL_MODE`: **disable**: MySQL 或 PostgreSQL 数据库是否启用 SSL 模式,仅适用于 MySQL 和 PostgreSQL。 - MySQL 的有效值: @@ -450,6 +469,7 @@ aliases: - `MAX_IDLE_CONNS`:**2**: 连接池上的最大空闲数据库连接数,默认为 2 - 这将限制为 `MAX_OPEN_CONNS`。 - `CONN_MAX_LIFETIME`:**0 或 3s**: 设置 DB 连接可以重用的最长时间 - 默认为 0,表示没有限制(除了 MySQL,其中为 3s - 请参见 #6804 和 #7071)。 - `AUTO_MIGRATION`:**true**: 是否自动执行数据库模型迁移。 +- `SLOW_QUERY_THRESHOLD` **5s**: 超过此秒数阈值的查询执行时间将在 xorm 日志中记录为警告。 请参见 #8540 和 #8273 以获取有关 `MAX_OPEN_CONNS`、`MAX_IDLE_CONNS` 和 `CONN_MAX_LIFETIME` 的适当值及其与端口耗尽的关系的进一步讨论。 @@ -510,6 +530,14 @@ Gitea 创建以下非唯一队列: - `deletion`: 用户不能通过界面或者 API 删除他自己。 - `manage_ssh_keys`: 用户不能通过界面或者 API 配置 SSH Keys。 - `manage_gpg_keys`: 用户不能配置 GPG 密钥。 +- `EXTERNAL_USER_DISABLE_FEATURES`:**_empty_**:仅在用户使用外部登录方式(例如 LDAP、OAuth 等)时禁用的功能列表,以逗号分隔,可选值为 `deletion`、`manage_ssh_keys`、`manage_gpg_keys`、`manage_mfa`、`manage_credentials`。此设置独立于 `USER_DISABLED_FEATURES`,并作为其行为的补充。 + - `deletion`:用户不能删除自己的帐户。 + - `manage_ssh_keys`:用户不能配置 SSH 密钥。 + - `manage_gpg_keys`:用户不能配置 GPG 密钥。 + - `manage_mfa`:用户不能配置 MFA 设备。 + - `manage_credentials`:用户不能配置邮箱、密码或 OpenID。 + - `change_username`:用户不能更改其用户名。 + - `change_full_name`:用户不能更改其全名。 ## 安全性 (`security`) @@ -518,6 +546,7 @@ Gitea 创建以下非唯一队列: - `SECRET_KEY_URI`: **_empty_**: 与定义 `SECRET_KEY` 不同,此选项可用于使用存储在文件中的密钥(示例值:`file:/etc/gitea/secret_key`)。它不应该像 `SECRET_KEY` 一样容易丢失。 - `LOGIN_REMEMBER_DAYS`: **31**: 在要求重新登录之前,记住用户的登录状态多长时间(以天为单位)。 - `COOKIE_REMEMBER_NAME`: **gitea_incredible**: 保存自动登录信息的 Cookie 名称。 +- `REVERSE_PROXY_LOGOUT_REDIRECT`: **_empty_**: 当使用反向代理或 SSO 进行身份认证时,用户登出后重定向到的 URL 或相对路径。例如:`/my-sso/logout?return=/my-sso/home`。 - `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**: 反向代理认证的 HTTP 头部名称,用于提供用户信息。 - `REVERSE_PROXY_AUTHENTICATION_EMAIL`: **X-WEBAUTH-EMAIL**: 反向代理认证的 HTTP 头部名称,用于提供邮箱信息。 - `REVERSE_PROXY_AUTHENTICATION_FULL_NAME`: **X-WEBAUTH-FULLNAME**: 反向代理认证的 HTTP 头部名称,用于提供全名信息。 @@ -561,6 +590,8 @@ Gitea 创建以下非唯一队列: - off - 不检查密码复杂性 - `PASSWORD_CHECK_PWN`: **false**: 检查密码是否在 [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) 中曝光。 - `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: 缓存成功的令牌哈希。API 令牌在数据库中存储为 pbkdf2 哈希,但这意味着在存在多个 API 操作时可能会有显着的哈希负载。此缓存将在 LRU 缓存中存储成功的哈希令牌,以在性能和安全性之间保持平衡。 +- `DISABLE_QUERY_AUTH_TOKEN`: **false**: 拒绝通过 URL 查询字符串发送的 API 令牌(仅接受基于 Header 的 API 令牌)。此设置将在 Gitea 1.23 中默认为 `true`,并在 Gitea 1.24 中弃用。 +- `TWO_FACTOR_AUTH`:**_empty_**:设置为 enforced 以强制启用双因素认证。仅在 Gitea 1.24 及更高版本中可用。 ## Camo (`camo`) @@ -602,7 +633,10 @@ Gitea 创建以下非唯一队列: - `REQUIRE_SIGNIN_VIEW`: **false**: 启用此项以强制用户登录以查看任何页面或使用 API。 - `ENABLE_NOTIFY_MAIL`: **false**: 启用此项以在发生某些情况(如创建问题)时向存储库的观察者发送电子邮件。需要启用`Mailer`。 - `ENABLE_BASIC_AUTHENTICATION`: **true**: 禁用此项以禁止使用 HTTP BASIC 和用户的密码进行身份验证。请注意,如果禁用此项,您将无法使用密码访问令牌 API 端点。此外,这仅会禁用使用密码的 BASIC 身份验证,而不会禁用令牌或 OAuth Basic。 +- `ENABLE_PASSWORD_SIGNIN_FORM`:**true**:显示密码登录表单(用于基于密码的登录),否则仅显示已启用的 OAuth2 或 Passkey 登录方式。如果设置为 false,可能还需要将 `ENABLE_BASIC_AUTHENTICATION` 设置为 false 以完全禁用基于密码的身份验证。 +- `ENABLE_PASSKEY_AUTHENTICATION`:**true**:允许用户使用 Passkey 登录。 - `ENABLE_REVERSE_PROXY_AUTHENTICATION`: **false**: 启用此项以允许反向代理身份验证。 +- `ENABLE_REVERSE_PROXY_AUTHENTICATION_API`:**false**:启用此项以允许 API 请求的反向代理身份验证,反向代理负责确保不会发生 CSRF 攻击。 - `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: **false**: 启用此项以允许反向身份验证的自动注册。 - `ENABLE_REVERSE_PROXY_EMAIL`: **false**: 启用此项以允许使用提供的电子邮件而不是生成的电子邮件进行自动注册。 - `ENABLE_REVERSE_PROXY_FULL_NAME`: **false**: 启用此项以允许使用提供的全名进行自动注册。 @@ -654,6 +688,13 @@ Gitea 创建以下非唯一队列: - `DISABLE_ORGANIZATIONS_PAGE`: **false**: 禁用组织探索页面。 - `DISABLE_CODE_PAGE`: **false**: 禁用代码探索页面。 +### 请求服务质量(`qos`) + +- `ENABLED`: **false**: 启用请求服务质量和过载保护。 +- `MAX_INFLIGHT`: **(动态)**: 服务器在将新请求加入队列之前将处理的最大并发请求数。默认值为"CpuNum * 4"。 +- `MAX_WAITING`: **100**: 在新请求被丢弃之前可以加入队列的最大请求数。 +- `TARGET_WAIT_TIME`: **250ms**: 请求在队列中等待的目标最大时间。等待时间低于此值的请求不会被丢弃。当等待时间超过此值时,将丢弃部分请求,直到等待时间降低到此值以下。 + ## SSH Minimum Key Sizes (`ssh.minimum_key_sizes`) 定义允许的算法及其最小密钥长度(使用-1 来禁用某个类型): @@ -710,6 +751,7 @@ Gitea 创建以下非唯一队列: - `HELO_HOSTNAME`: **(从系统检索)**: HELO 主机名。 - `FROM`: **_empty_**: 邮件的发件人地址,符合 RFC 5322。这可以是一个电子邮件地址,也可以是 "Name" \ 格式。 - `ENVELOPE_FROM`: **_empty_**: 在 SMTP 邮件信封上设置的地址作为发件地址。设置为 `<>` 以发送一个空地址。 +- `FROM_DISPLAY_NAME_FORMAT`:**`{{ .DisplayName }}`**:当 Gitea 代表用户发送邮件时,将使用 WebUI 中显示的名称。如果您希望例如 `Mister X (by CodeIt) `,请设置为 `{{ .DisplayName }} (by {{ .AppName }})`。可用变量:`.DisplayName`、`.AppName` 和 `.Domain`。 - `SUBJECT_PREFIX`: **_empty_**: 放置在电子邮件主题行之前的前缀。 - `SENDMAIL_PATH`: **sendmail**: 操作系统上 `sendmail` 的位置(可以是命令或完整路径)。 - `SENDMAIL_ARGS`: **_empty_**: 指定任何额外的 sendmail 参数。(注意:您应该知道电子邮件地址可能看起来像选项 - 如果您的 `sendmail` 命令带有选项,您必须设置选项终止符 `--`) @@ -717,6 +759,22 @@ Gitea 创建以下非唯一队列: - `SENDMAIL_CONVERT_CRLF`: **true**: 大多数版本的 sendmail 偏好使用 LF 换行符,而不是 CRLF 换行符。如果您的 sendmail 版本需要 CRLF 换行符,请将此设置为 false。 - `SEND_BUFFER_LEN`: **100**: 邮件队列的缓冲区长度。**已弃用**,请在 `[queue.mailer]` 中使用 `LENGTH`。 - `SEND_AS_PLAIN_TEXT`: **false**: 仅以纯文本形式发送邮件,不包括 HTML 备选方案。 +- `EMBED_ATTACHMENT_IMAGES`: **false**: 在 HTML 邮件中以 base64 格式嵌入附件图片。(适用于不加载外部图片的客户端或断开 VPN 连接仍接收邮件的用户;注意:gmail 等在线 Web 客户端不会显示 base64 嵌入的图片) + +## 覆盖邮件头(`mailer.override_header`) + +:::warning +此项默认为空,仅在您明确知道需要时使用。 +::: + +示例如下: + +```ini +[mailer.override_header] +Reply-To = test@example.com, test2@example.com +Content-Type = text/html; charset=utf-8 +In-Reply-To = +``` ## 入站邮件 (`email.incoming`) @@ -781,7 +839,7 @@ Gitea 创建以下非唯一队列: - none = 不显示任何头像 - random = 生成随机头像 - image = 使用默认图像(在 `REPOSITORY_AVATAR_FALLBACK_IMAGE` 中设置),如果设置为 image 并且未上传任何图像。 -- `REPOSITORY_AVATAR_FALLBACK_IMAGE`: **/img/repo_default.png**: 作为默认仓库头像的图像(如果将 `REPOSITORY_AVATAR_FALLBACK` 设置为 image 并且没有上传图像)。 +- `REPOSITORY_AVATAR_FALLBACK_IMAGE`: **_empty_**: 作为默认仓库头像的图像(如果将 `REPOSITORY_AVATAR_FALLBACK` 设置为 image 并且没有上传图像)。该值将原样使用,不会自动添加 `ROOT_URL` 中的子路径。留空则使用 Gitea 内置的仓库头像。 ## 项目 (`project`) @@ -796,19 +854,22 @@ Gitea 创建以下非唯一队列: - `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**: 允许的文件扩展名(`.zip`)、mime 类型(`text/plain`)或通配符类型(`image/*`、`audio/*`、`video/*`)的逗号分隔列表。空值或 `*/*` 允许所有类型。 - `MAX_SIZE`: **2048**: 附件的最大限制(MB)。 - `MAX_FILES`: **5**: 一次最多上传的附件数量。 -- `STORAGE_TYPE`: **local**: 附件的存储类型,`local` 表示本地磁盘,`minio` 表示兼容 S3 的对象存储服务,如果未设置将使用默认值 `local` 或其他在 `[storage.xxx]` 中定义的名称。 -- `SERVE_DIRECT`: **false**: 允许存储驱动器重定向到经过身份验证的 URL 以直接提供文件。目前,只支持 Minio/S3 通过签名 URL 提供支持,local 不会执行任何操作。 -- `PATH`: **attachments**: 存储附件的路径,仅当 STORAGE_TYPE 为 `local` 时可用。如果是相对路径,将会被解析为 `{AppDataPath}/{attachment.PATH}`. -- `MINIO_ENDPOINT`: **localhost:9000**: Minio 端点以连接,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_ACCESS_KEY_ID`: Minio accessKeyID 以连接,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_SECRET_ACCESS_KEY`: Minio secretAccessKey 以连接,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_BUCKET`: **gitea**: Minio 存储附件的存储桶,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_LOCATION`: **us-east-1**: Minio 存储桶的位置以创建,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_BASE_PATH`: **attachments/**: Minio 存储桶上的基本路径,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_USE_SSL`: **false**: Minio 启用 SSL,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio 跳过 SSL 验证,仅当 STORAGE_TYPE 为 `minio` 时可用。 -- `MINIO_CHECKSUM_ALGORITHM`: **default**: Minio 校验算法:`default`(适用于 MinIO 或 AWS S3)或 `md5`(适用于 Cloudflare 或 Backblaze) -- `MINIO_BUCKET_LOOKUP_TYPE`: **auto**: Minio 的 bucket 查找方式默认为`auto`模式,可将其设置为`dns`(虚拟托管样式)或`path`(路径样式),仅当`STORAGE_TYPE`为`minio`时可用。 +- `STORAGE_TYPE`: **local**: 附件的存储类型,可以为空、`local`、`minio`、`azureblob` 或在 `[storage.xxx]` 中定义的其他名称。 + + 当 `STORAGE_TYPE` 为空或未配置此项时,所有存储将从 `[storage]`(如已配置)或默认值派生。 + + 当 `STORAGE_TYPE = local` 时,以下为可用配置项 + + - `PATH`: **attachments**: 存储附件的路径,仅当 STORAGE_TYPE 为 `local` 时可用。如果是相对路径,将会被解析为 `{AppDataPath}/{attachment.PATH}`。 + + 当 `STORAGE_TYPE = minio` 时,相关配置详见 [Minio 存储配置](#storage_minio),您也可以如下定义配置来覆盖派生的或默认的值。 + + - `MINIO_BASE_PATH`: **attachments/**: Minio 存储桶上的基本路径,仅当 STORAGE_TYPE 为 `minio` 时可用。 + + 当 `STORAGE_TYPE = xxx` 时,配置将从 `[storage.xxx]` 派生,以下配置项可被覆盖。 + + - `PATH`: 同上 + - `MINIO_BASE_PATH`: 同上 ## 日志 (`log`) @@ -886,25 +947,34 @@ Gitea 创建以下非唯一队列: - `ENABLED`: **true**: 是否启用该定时任务。 - `RUN_AT_START`: **true**: 设置在服务启动时运行。 +- `NOTICE_ON_SUCCESS`: **false**: 是否在成功执行时也发出通知。 - `SCHEDULE`: **@midnight**: 使用 Cron 语法的定时任务触发配置,例如 `@every 1h`。 - `OLDER_THAN`: **24h**: 超过`OLDER_THAN`时间的存档将被删除,例如 `12h`。 #### 定时任务 - 更新镜像仓库 (`cron.update_mirrors`) +- `ENABLED`: **true**: 启用定期运行更新镜像任务。 - `SCHEDULE`: **@every 10m**: 使用 Cron 语法的定时任务触发配置,例如 `@every 3h`。 +- `RUN_AT_START`: **false**: 在 Gitea 启动时运行更新镜像任务。 +- `NOTICE_ON_SUCCESS`: **false**: 是否在成功时发出通知。 - `PULL_LIMIT`: **50**: 将要添加到队列的镜像数量限制为此数字(负值表示无限制,0 将导致不会将镜像加入队列,从而有效地禁用镜像更新)。 - `PUSH_LIMIT`: **50**: 将要添加到队列的镜像数量限制为此数字(负值表示无限制,0 将导致不会将镜像加入队列,从而有效地禁用镜像更新)。 #### 定时任务 - 健康检查所有仓库 (`cron.repo_health_check`) +- `ENABLED`: **true**: 启用定期运行仓库健康检查任务。 - `SCHEDULE`: **@midnight**: Cron 语法,用于安排仓库健康检查。 +- `RUN_AT_START`: **false**: 在 Gitea 启动时运行仓库健康检查任务。 +- `NOTICE_ON_SUCCESS`: **false**: 是否在成功时发出通知。 - `TIMEOUT`: **60s**: 用于健康检查执行超时的时间持续语法。 - `ARGS`: **_empty_**: `git fsck` 命令的参数,例如 `--unreachable --tags`。在 http://git-scm.com/docs/git-fsck 上了解更多。 #### 定时任务 - 检查所有仓库统计 (`cron.check_repo_stats`) -- `RUN_AT_START`: **true**: 在启动时运行仓库统计检查。 - `SCHEDULE`: **@midnight**: Cron 语法,用于安排仓库统计检查。 +- `ENABLED`: **true**: 启用定期运行仓库统计检查任务。 +- `RUN_AT_START`: **true**: 在启动时运行仓库统计检查。 +- `NOTICE_ON_SUCCESS`: **false**: 是否在成功时发出通知。 #### 定时任务 - 清理 hook_task 表 (`cron.cleanup_hook_task_table`) @@ -925,15 +995,49 @@ Gitea 创建以下非唯一队列: #### Cron - 更新迁移海报 ID (`cron.update_migration_poster_id`) +- `ENABLED`: **true**: 启用更新迁移海报 ID 任务。 +- `RUN_AT_START`: **true**: 在启动服务器时更新迁移仓库的工单和评论的海报 ID。 +- `NOTICE_ON_SUCCESS`: **false**: 是否在成功时发出通知。 - `SCHEDULE`: **@midnight** : 同步之间的间隔作为持续时间,每次实例启动时都会尝试同步。 #### Cron - 同步外部用户 (`cron.sync_external_users`) +- `ENABLED`: **true**: 启用同步外部用户数据任务。 +- `RUN_AT_START`: **false**: 在启动服务器时同步外部用户数据。 +- `NOTICE_ON_SUCCESS`: **false**: 是否在成功时发出通知。 - `SCHEDULE`: **@midnight** : 同步之间的间隔作为持续时间,每次实例启动时都会尝试同步。 - `UPDATE_EXISTING`: **true**: 创建新用户,更新现有用户数据,并禁用不再在外部源中的用户(默认设置)或仅在 UPDATE_EXISTING 设置为 false 时创建新用户。 +#### Cron - 清理过期的 Actions 资源 (`cron.cleanup_actions`) + +- `ENABLED`: **true**: 启用清理过期 Actions 资源的任务。 +- `RUN_AT_START`: **true**: 在启动时运行任务(如果启用)。 +- `SCHEDULE`: **@midnight**: Cron 语法,用于任务调度。 + +#### Cron - 清理已删除的分支 (`cron.deleted_branches_cleanup`) + +- `ENABLED`: **true**: 启用已删除分支清理。 +- `RUN_AT_START`: **true**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以记录成功消息。 +- `SCHEDULE`: **@midnight**: Cron 语法,用于安排已删除分支清理。 +- `OLDER_THAN`: **24h**: 删除超过 OLDER_THAN 时间的已删除分支。 + +#### Cron - 同步仓库许可证 (`cron.sync_repo_licenses`) + +- `ENABLED`: **false**: 启用仓库许可证同步。 +- `RUN_AT_START`: **false**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以记录成功消息。 +- `SCHEDULE`: **@annually*: Cron 语法,用于安排仓库许可证同步。 + ### 扩展的定时任务(默认未启用) +#### Cron - 删除所有仓库存档 (`cron.delete_repo_archives`) + +- `ENABLED`: **false**: 启用服务。 +- `RUN_AT_START`: **false**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@annually**: Cron 语法,用于删除所有仓库存档,例如 `@annually`。 + #### Cron - 垃圾收集所有仓库 (`cron.git_gc_repos`) - `ENABLED`: **false**: 启用服务。 @@ -950,6 +1054,13 @@ Gitea 创建以下非唯一队列: - `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 - `SCHEDULE`: **@every 72h**: Cron 语法,用于安排仓库存档清理,例如 `@every 1h`。 +#### Cron - 更新 '.ssh/authorized_principals' 文件 (`cron.resync_all_sshprincipals`) + +- `ENABLED`: **false**: 启用服务。 +- `RUN_AT_START`: **false**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@every 72h**: Cron 语法,用于安排 authorized_principals 更新,例如 `@every 1h`。 + #### Cron - 重新同步所有仓库的 pre-receive、update 和 post-receive 钩子 (`cron.resync_all_hooks`) - `ENABLED`: **false**: 启用服务。 @@ -986,11 +1097,19 @@ Gitea 创建以下非唯一队列: - `SCHEDULE`: **@every 168h**: Cron 语法,用于设置多长时间进行检查。 - `OLDER_THAN`: **8760h**: 早于此表达式的任何操作都将从数据库中删除,建议使用 `8760h`(1 年),因为这是热力图的最大长度。 +#### Cron - 检查 Gitea 新版本 (`cron.update_checker`) + +- `ENABLED`: **true**: 启用服务。 +- `RUN_AT_START`: **false**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@every 168h**: Cron 语法,用于安排任务,例如 `@every 168h`。 +- `HTTP_ENDPOINT`: **https://dl.gitea.com/gitea/version.json**: Gitea 用于检查新版本的端点。 + #### Cron - 从数据库中删除所有旧的系统通知 (`cron.delete_old_system_notices`) - `ENABLED`: **false**: 启用服务。 - `RUN_AT_START`: **false**: 在启动时运行任务(如果启用)。 -- `NO_SUCCESS_NOTICE`: **false**: 设置为 true 以关闭成功通知。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 - `SCHEDULE`: **@every 168h**: Cron 语法,用于设置多长时间进行检查。 - `OLDER_THAN`: **8760h**: 早于此表达式的任何系统通知都将从数据库中删除。 @@ -1002,6 +1121,44 @@ Gitea 创建以下非唯一队列: - `OLDER_THAN`: **168h**: 只会尝试回收早于此时间(默认 7 天)的 LFSMetaObject。 - `LAST_UPDATED_MORE_THAN_AGO`: **72h**: 只会尝试回收超过此时间(默认 3 天)没有尝试过回收的 LFSMetaObject。 - `NUMBER_TO_CHECK_PER_REPO`: **100**: 每个仓库要检查的过期 LFSMetaObject 的最小数量。设置为 `0` 以始终检查所有。 +- `PROPORTION_TO_CHECK_PER_REPO`: **0.6**: 每个仓库至少检查此比例的 LFSMetaObject。(这可能导致检查所有过期的 LFSMetaObject。) + +### Actions 定时任务 + +#### Cron - 重建工单索引 (`cron.rebuild_issue_indexer`) + +- `ENABLED`: **true**: 启用服务。 +- `RUN_AT_START`: **true**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@annually**: Cron 语法,用于设置重建索引的频率。 + +#### Cron - 停止长时间未更新的运行中任务 (`cron.stop_zombie_tasks`) + +- `ENABLED`: **true**: 启用服务。 +- `RUN_AT_START`: **true**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@every 5m**: Cron 语法,用于设置检查的频率。 + +#### Cron - 停止持续更新但长时间未结束的运行中任务 (`cron.stop_endless_tasks`) + +- `ENABLED`: **true**: 启用服务。 +- `RUN_AT_START`: **true**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@every 30m**: Cron 语法,用于设置检查的频率。 + +#### Cron - 取消长时间未被领取的任务 (`cron.cancel_abandoned_jobs`) + +- `ENABLED`: **true**: 启用服务。 +- `RUN_AT_START`: **false**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@every 6h**: Cron 语法,用于设置检查的频率。 + +#### Cron - 启动基于定时的 Actions (`cron.start_schedule_tasks`) + +- `ENABLED`: **true**: 启用服务。 +- `RUN_AT_START`: **false**: 在启动时运行任务(如果启用)。 +- `NOTICE_ON_SUCCESS`: **false**: 设置为 true 以打开成功通知。 +- `SCHEDULE`: **@every 1m**: Cron 语法,用于设置调度任务的频率。 ## Git (`git`) @@ -1023,14 +1180,12 @@ Gitea 创建以下非唯一队列: - `LARGE_OBJECT_THRESHOLD`: **1048576**: (仅限于 Go-Git),不要在内存中缓存大于此大小的对象。(设置为 0 以禁用。) - `DISABLE_CORE_PROTECT_NTFS`: **false** 将`core.protectNTFS`强制设置为 false。 - `DISABLE_PARTIAL_CLONE`: **false** 禁用使用部分克隆进行 git。 +- `DIFF_RENAME_SIMILARITY_THRESHOLD`:**50%** 设置通过 `--find-renames=` 传递给 git 命令的相似度阈值。默认值为 50%,与 git 相同。必须是 0% 到 100% 之间的整数百分比。 ### Git - 超时设置 (`git.timeout`) -- `DEFAULT`: **360**: Git 操作的默认超时时间,单位秒 - `MIGRATE`: **600**: 在迁移外部存储库时的超时时间,单位秒 - `MIRROR`: **300**: 在镜像外部存储库时的超时时间,单位秒 -- `CLONE`: **300**: 在存储库之间进行内部克隆的超时时间,单位秒 -- `PULL`: **300**: 在存储库之间进行内部拉取的超时时间,单位秒 - `GC`: **60**: git 存储库 GC 的超时时间,单位秒 ### Git - 配置选项 (`git.config`) @@ -1080,9 +1235,11 @@ Gitea 创建以下非唯一队列: ## Markup (`markup`) -- `MERMAID_MAX_SOURCE_CHARACTERS`: **5000**: 设置 Mermaid 源的最大大小。(设为-1 代表禁止) +- `MERMAID_MAX_SOURCE_CHARACTERS`: **50000**: 设置 Mermaid 源的最大大小。(设为-1 代表禁止) -gitea 支持外部渲染工具,你可以配置你熟悉的文档渲染工具. 比如一下将新增一个名字为 asciidoc 的渲染工具。 +## Markup 外部渲染(`markup.external-render-name`) + +Gitea 支持使用外部工具进行 Markup 渲染。以下示例将新增一个名为 `asciidoc` 的 Markup 渲染器。 ```ini [markup.asciidoc] @@ -1093,15 +1250,18 @@ RENDER_COMMAND = "asciidoctor --embedded --safe-mode=secure --out-file=- -" IS_INPUT_FILE = false ``` -- ENABLED:**false** 设置是否启动渲染器 -- NEED_POSTPROCESS:**true** 设置为**true**以替换链接/SHA1 等。 -- FILE*EXTENSIONS:\*\*\_empty*\*\* 要由外部命令渲染的文件扩展名列表。多个扩展名需要用逗号分隔。 -- RENDER_COMMAND:用于渲染所有匹配的扩展名的外部命令。 -- IS_INPUT_FILE:**false** 输入不是标准输入,而是一个在`RENDER_COMMAND`之后带有文件参数的文件。 +- ENABLED:**false** 启用 Markup 支持;设置为 **true** 以启用此渲染器。 +- FILE\_EXTENSIONS:**_empty_** 要由外部命令渲染的文件扩展名列表。多个扩展名需要用逗号分隔。 +- RENDER\_COMMAND:用于渲染所有匹配的扩展名的外部命令。 +- IS\_INPUT\_FILE:**false** 输入不是标准输入,而是一个在 `RENDER_COMMAND` 之后带有文件参数的文件。 - RENDER_CONTENT_MODE:**sanitized** 内容将如何呈现。 - - sanitized:对内容进行清理,并在当前页面内呈现,默认仅允许一些 HTML 标签和属性。可以在`[markup.sanitizer.*]`中定义自定义的清理规则。 + - sanitized:对内容进行清理,并在当前页面内呈现,默认仅允许一些 HTML 标签和属性。可以在 `[markup.sanitizer.*]` 中定义自定义的清理规则。 - no-sanitizer:禁用清理程序,在当前页面内呈现内容。这是**不安全**的,如果内容包含恶意代码,可能会导致 XSS 攻击。 - iframe:在单独的独立页面中呈现内容,并通过 iframe 嵌入到当前页面中。iframe 处于禁用同源策略的沙箱模式,并且 JS 代码与父页面安全隔离。 +- RENDER_CONTENT_SANDBOX:**_empty_** 当 RENDER_CONTENT_MODE 为 `iframe` 时应用于 iframe 和 Content-Security-Policy 头的沙箱设置。默认为一组安全的"allow-*"限制(空格分隔)。您也可以根据需要设置或使用"disabled"完全禁用沙箱。设置时请确保没有安全风险: + - 仅 PDF 内容:通常可以安全使用"disabled",并且需要设置为"disabled",因为 PDF 仅在无沙箱时渲染。 + - 包含 JS 的 HTML 内容:如果"RENDER_COMMAND"能保证不存在 XSS,则是安全的,否则需要微调"allow-*"限制。 +- NEED_POST_PROCESS:**false** 是否对渲染后的 HTML 内容进行后处理,包括:解析相对链接和图片源、识别 issue/commit 引用、转义不可见字符、提及用户、渲染永久链接代码块、替换 emoji 短代码等。当 RENDER_CONTENT_MODE 为 `sanitized` 时默认为 true,否则为 false。 两个特殊的环境变量会传递给渲染命令: @@ -1189,6 +1349,7 @@ ALLOW_DATA_URI_IMAGES = true - `LIMIT_SIZE_RUBYGEMS`:**-1**: RubyGems 上传的最大大小(`-1` 表示无限制,格式为 `1000`、`1 MB`、`1 GiB`)。 - `LIMIT_SIZE_SWIFT`:**-1**: Swift 上传的最大大小(`-1` 表示无限制,格式为 `1000`、`1 MB`、`1 GiB`)。 - `LIMIT_SIZE_VAGRANT`:**-1**: Vagrant 上传的最大大小(`-1` 表示无限制,格式为 `1000`、`1 MB`、`1 GiB`)。 +- `LIMIT_SIZE_TERRAFORM_STATE`:**-1**:Terraform state 上传的最大大小(`-1` 表示无限制,格式为 `1000`、`1 MB`、`1 GiB`)。 ## 镜像(`mirror`) @@ -1203,50 +1364,67 @@ ALLOW_DATA_URI_IMAGES = true 用于 lfs 数据的存储配置。当将 `STORAGE_TYPE` 设置为 `xxx` 时,它将从默认的 `[storage]` 或 `[storage.xxx]` 派生。 当派生时,`PATH` 的默认值是 `data/lfs`,`MINIO_BASE_PATH` 的默认值是 `lfs/`。 -- `STORAGE_TYPE`:**local**: lfs 的存储类型,`local` 表示本地磁盘,`minio` 表示 S3 兼容对象存储服务,或者使用 `[storage.xxx]` 中定义的其他名称。 -- `SERVE_DIRECT`:**false**: 允许存储驱动程序重定向到经过身份验证的 URL 以直接提供文件。目前,仅支持通过签名的 URL 提供 Minio/S3,本地不执行任何操作。 +- `STORAGE_TYPE`:**local**: lfs 的存储类型,可以为空、`local`、`minio`、`azureblob` 或在 `[storage.xxx]` 中定义的其他名称。 + + 当 `STORAGE_TYPE` 为空或未配置此项时,所有存储将从 `[storage]`(如已配置)或默认值派生。 + + 当 `STORAGE_TYPE = local` 时,以下为可用配置项 + - `PATH`:**./data/lfs**: 存储 LFS 文件的位置,仅在 `STORAGE_TYPE` 为 `local` 时可用。如果未设置,则回退到 `[server]` 部分中已弃用的 `LFS_CONTENT_PATH` 值。 -- `MINIO_ENDPOINT`:**localhost:9000**: 连接的 Minio 终端点,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_ACCESS_KEY_ID`:Minio 的 accessKeyID,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_SECRET_ACCESS_KEY`:Minio 的 secretAccessKey,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_BUCKET`:**gitea**: 用于存储 lfs 的 Minio 桶,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_LOCATION`:**us-east-1**: 创建桶的 Minio 位置,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_BASE_PATH`:**lfs/**: 桶上的 Minio 基本路径,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_USE_SSL`:**false**: Minio 启用 ssl,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_INSECURE_SKIP_VERIFY`:**false**: Minio 跳过 SSL 验证,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_BUCKET_LOOKUP_TYPE`: **auto**: Minio 的 bucket 查找方式默认为`auto`模式,可将其设置为`dns`(虚拟托管样式)或`path`(路径样式),仅当`STORAGE_TYPE`为`minio`时可用。 + + 当 `STORAGE_TYPE = minio` 时,相关配置详见 [Minio 存储配置](#storage_minio),您也可以如下定义配置来覆盖派生的或默认的值。 + + - `MINIO_BASE_PATH`:**attachments/**: 桶上的 Minio 基本路径,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 + + 当 `STORAGE_TYPE = xxx` 时,配置将从 `[storage.xxx]` 派生,以下配置项可被覆盖。 + +- `PATH`:同上 +- `MINIO_BASE_PATH`:同上 + +## LFS 客户端(`lfs_client`) + +- `BATCH_SIZE`: **20**: 上游镜像每次批量 API 请求的 LFS 指针数量。 +- `BATCH_OPERATION_CONCURRENCY`: **8**: 批量操作中并发上传/下载的数量。 ## 存储 (`storage`) -默认的附件、lfs、头像、仓库头像、仓库归档、软件包、操作日志、artifacts 的存储配置。推荐仅仅配置此 section 并让其它的 section 从此配置项继承。 +`attachments`、`lfs`、`avatars`、`repo-avatars`、`repo-archive`、`packages`、`actions_log`、`actions_artifact` 的默认存储配置。推荐仅配置此部分并让其他部分从此配置继承,前提是所有存储都位于同一父目录或 Minio 桶下。 + +- `STORAGE_TYPE`:**local**: 存储类型,`local` 表示本地磁盘,`minio` 表示 S3 兼容对象存储服务,`azureblob` 表示 Azure Blob 存储服务。 + +### Minio 存储配置(`storage_minio`) -- `STORAGE_TYPE`:**local**: 存储类型,`local` 表示本地磁盘,`minio` 表示 S3,`azureblob` 表示 azure 对象存储。 - `SERVE_DIRECT`:**false**: 允许存储驱动程序重定向到经过身份验证的 URL 以直接提供文件。目前,仅支持通过签名的 URL 提供 Minio/S3,本地不执行任何操作。 -- `MINIO_ENDPOINT`:**localhost:9000**: 连接的 Minio 终端点,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_ACCESS_KEY_ID`:Minio 的 accessKeyID,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 +- `MINIO_ENDPOINT`:**localhost:9000**: Minio 连接终端点,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 +- `MINIO_ACCESS_KEY_ID`:Minio 的 accessKeyID,仅在 `STORAGE_TYPE` 为 `minio` 时可用。如果未提供且 `STORAGE_TYPE` 为 `minio`,将在已知的环境变量(MINIO_ACCESS_KEY_ID、AWS_ACCESS_KEY_ID)、凭据文件(~/.mc/config.json、~/.aws/credentials)以及 EC2 实例元数据中搜索凭据。 - `MINIO_SECRET_ACCESS_KEY`:Minio 的 secretAccessKey,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 +- `MINIO_IAM_ENDPOINT`:用于覆盖 Minio 默认 IAM 终端点解析的首选 IAM 终端点,仅在 `STORAGE_TYPE` 为 `minio` 时可用。如果未提供且 `STORAGE_TYPE` 为 `minio`,将从已知的环境变量(AWS_CONTAINER_AUTHORIZATION_TOKEN、AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE、AWS_CONTAINER_CREDENTIALS_RELATIVE_URI、AWS_CONTAINER_CREDENTIALS_FULL_URI、AWS_WEB_IDENTITY_TOKEN_FILE、AWS_ROLE_ARN、AWS_ROLE_SESSION_NAME、AWS_REGION)中搜索和派生终端点,如果未另行提供则使用 DefaultIAMRoleEndpoint。 - `MINIO_BUCKET`:**gitea**: 用于存储数据的 Minio 桶,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 - `MINIO_LOCATION`:**us-east-1**: 创建桶的 Minio 位置,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_USE_SSL`:**false**: Minio 启用 ssl,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 +- `MINIO_USE_SSL`:**false**: Minio 启用 SSL,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 - `MINIO_INSECURE_SKIP_VERIFY`:**false**: Minio 跳过 SSL 验证,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `MINIO_BUCKET_LOOKUP_TYPE`: **auto**: Minio 的 bucket 查找方式默认为`auto`模式,可将其设置为`dns`(虚拟托管样式)或`path`(路径样式),仅当`STORAGE_TYPE`为`minio`时可用。 +- `MINIO_BUCKET_LOOKUP_TYPE`:**auto**: Minio 的 bucket 查找方式默认为 `auto` 模式;可将其设置为 `dns`(虚拟托管样式)或 `path`(路径样式),仅在 `STORAGE_TYPE` 为 `minio` 时可用。 -- `AZURE_BLOB_ENDPOINT`: **_empty_**: Azure Blob 终端点,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。例如:https://accountname.blob.core.windows.net 或 http://127.0.0.1:10000/devstoreaccount1 -- `AZURE_BLOB_ACCOUNT_NAME`: **_empty_**: Azure Blob 账号名,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。 -- `AZURE_BLOB_ACCOUNT_KEY`: **_empty_**: Azure Blob 访问密钥,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。 -- `AZURE_BLOB_CONTAINER`: **gitea**: 用于存储数据的 Azure Blob 容器名,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。 - -建议的 minio 存储配置如下: +建议的 Minio 存储配置如下: ```ini [storage] STORAGE_TYPE = minio ; Minio endpoint to connect only available when STORAGE_TYPE is `minio` MINIO_ENDPOINT = localhost:9000 -; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio` +; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`. +; If not provided and STORAGE_TYPE is `minio`, will search for credentials in known +; environment variables (MINIO_ACCESS_KEY_ID, AWS_ACCESS_KEY_ID), credentials files +; (~/.mc/config.json, ~/.aws/credentials), and EC2 instance metadata. MINIO_ACCESS_KEY_ID = ; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio` MINIO_SECRET_ACCESS_KEY = +; Preferred IAM Endpoint to override Minio's default IAM Endpoint resolution only available when STORAGE_TYPE is `minio`. +; If not provided and STORAGE_TYPE is `minio`, will search for and derive endpoint from known environment variables +; (AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, +; AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, AWS_ROLE_SESSION_NAME, AWS_REGION), or +; the DefaultIAMRoleEndpoint if not provided otherwise. +MINIO_IAM_ENDPOINT = ; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio` MINIO_BUCKET = gitea ; Minio location to create bucket only available when STORAGE_TYPE is `minio` @@ -1260,6 +1438,18 @@ SERVE_DIRECT = true MINIO_BUCKET_LOOKUP_TYPE = auto ``` +### Azure Blob 存储配置(`storage_azureblob`) + +- `SERVE_DIRECT`:**false**: 允许存储驱动程序重定向到经过身份验证的 URL 以直接提供文件。目前,仅支持通过签名的 URL 提供 Minio/S3,本地不执行任何操作。 +- `AZURE_BLOB_ENDPOINT`:**_empty_**: Azure Blob 连接终端点,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。例如:https://accountname.blob.core.windows.net 或 http://127.0.0.1:10000/devstoreaccount1 +- `AZURE_BLOB_ACCOUNT_NAME`:**_empty_**: Azure Blob 账号名,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。 +- `AZURE_BLOB_ACCOUNT_KEY`:**_empty_**: Azure Blob 访问密钥,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。 +- `AZURE_BLOB_CONTAINER`:**gitea**: 用于存储数据的 Azure Blob 容器名,仅在 `STORAGE_TYPE` 为 `azureblob` 时可用。 + +### 覆盖配置(`storage_override`) + +覆盖可以有 3 个层级。`[LFS]/[attachment]...` >> `[storage.xxx]` >> `[storage]` >> 默认值。 + 默认情况下,每个存储都有其默认的基本路径,如下所示: | storage | default base path | @@ -1273,7 +1463,7 @@ MINIO_BUCKET_LOOKUP_TYPE = auto | actions_log | actions_log/ | | actions_artifacts | actions_artifacts/ | -并且桶(bucket)、基本路径或`SERVE_DIRECT`可以是特殊的或被覆盖的,如果您想要使用不同的设置,您可以: +桶(bucket)、基本路径或 `SERVE_DIRECT` 可以被特别指定或覆盖,如果您想使用不同的设置,可以: ```ini [storage.actions_log] @@ -1282,7 +1472,7 @@ SERVE_DIRECT = true MINIO_BASE_PATH = my_actions_log/ ; default is actions_log/ if blank ``` -如果您想为' lfs '自定义一个不同的存储,如果上面定义了默认存储 +如果您想为 `lfs` 自定义一个不同的存储(在上面已定义默认存储的情况下): ```ini [lfs] @@ -1292,10 +1482,19 @@ STORAGE_TYPE = my_minio STORAGE_TYPE = minio ; Minio endpoint to connect only available when STORAGE_TYPE is `minio` MINIO_ENDPOINT = localhost:9000 -; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio` +; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`. +; If not provided and STORAGE_TYPE is `minio`, will search for credentials in known +; environment variables (MINIO_ACCESS_KEY_ID, AWS_ACCESS_KEY_ID), credentials files +; (~/.mc/config.json, ~/.aws/credentials), and EC2 instance metadata. MINIO_ACCESS_KEY_ID = ; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio` MINIO_SECRET_ACCESS_KEY = +; Preferred IAM Endpoint to override Minio's default IAM Endpoint resolution only available when STORAGE_TYPE is `minio`. +; If not provided and STORAGE_TYPE is `minio`, will search for and derive endpoint from known environment variables +; (AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, +; AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, AWS_ROLE_SESSION_NAME, AWS_REGION), or +; the DefaultIAMRoleEndpoint if not provided otherwise. +MINIO_IAM_ENDPOINT = ; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio` MINIO_BUCKET = gitea ; Minio location to create bucket only available when STORAGE_TYPE is `minio` @@ -1308,27 +1507,31 @@ MINIO_INSECURE_SKIP_VERIFY = false MINIO_BUCKET_LOOKUP_TYPE = auto ``` -### 存储库归档存储 (`storage.repo-archive`) +## 存储库归档存储 (`storage.repo-archive`) -存储库归档存储的配置。当将`STORAGE_TYPE`设置为`xxx`时,它将继承默认的 `[storage]` 或 `[storage.xxx]` 配置。`PATH`的默认值是`data/repo-archive`,`MINIO_BASE_PATH`的默认值是`repo-archive/`。 +存储库归档存储的配置。当将 `STORAGE_TYPE` 设置为 `xxx` 时,它将继承默认的 `[storage]` 或 `[storage.xxx]` 配置。`PATH` 的默认值是 `data/repo-archive`,`MINIO_BASE_PATH` 的默认值是 `repo-archive/`。 -- `STORAGE_TYPE`: **local**: 存储类型,`local`表示本地磁盘,`minio`表示与 S3 兼容的对象存储服务,或者使用定义为`[storage.xxx]`的其他名称。 -- `SERVE_DIRECT`: **false**: 允许存储驱动程序重定向到经过身份验证的 URL 以直接提供文件。目前,只有 Minio/S3 支持通过签名 URL,本地不执行任何操作。 -- `PATH`: **./data/repo-archive**: 用于存储归档文件的位置,仅在`STORAGE_TYPE`为`local`时可用。 -- `MINIO_ENDPOINT`: **localhost:9000**: Minio 端点,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_ACCESS_KEY_ID`: Minio 的 accessKeyID,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_SECRET_ACCESS_KEY`: Minio 的 secretAccessKey,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_BUCKET`: **gitea**: 用于存储归档的 Minio 存储桶,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_LOCATION`: **us-east-1**: 用于创建存储桶的 Minio 位置,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_BASE_PATH`: **repo-archive/**: 存储桶上的 Minio 基本路径,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_USE_SSL`: **false**: 启用 Minio 的 SSL,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_INSECURE_SKIP_VERIFY`: **false**: 跳过 Minio 的 SSL 验证,仅在`STORAGE_TYPE`为`minio`时可用。 -- `MINIO_BUCKET_LOOKUP_TYPE`: **auto**: Minio 的 bucket 查找方式默认为`auto`模式,可将其设置为`dns`(虚拟托管样式)或`path`(路径样式),仅当`STORAGE_TYPE`为`minio`时可用。 +- `STORAGE_TYPE`:**local**: 存储库归档的存储类型,可以为空、`local`、`minio`、`azureblob` 或在 `[storage.xxx]` 中定义的其他名称。 -### 存储库归档 (`repo-archive`) + 当 `STORAGE_TYPE` 为空或未配置此项时,所有存储将从 `[storage]`(如已配置)或默认值派生。 -- `STORAGE_TYPE`: **local**: 存储类型,用于操作日志,`local`表示本地磁盘,`minio`表示与 S3 兼容的对象存储服务,默认为`local`,或者使用定义为`[storage.xxx]`的其他名称。 -- `MINIO_BASE_PATH`: **repo-archive/**: Minio 存储桶上的基本路径,仅在`STORAGE_TYPE`为`minio`时可用。 + 当 `STORAGE_TYPE = local` 时,以下为可用配置项 + + - `PATH`:**./data/repo-archive**: 用于存储归档文件的位置,仅在 `STORAGE_TYPE` 为 `local` 时可用。 + + 当 `STORAGE_TYPE = minio` 时,相关配置详见 [Minio 存储配置](#storage_minio),您可以如下覆盖部分配置。 + + - `MINIO_BASE_PATH`:**repo-archive/**: 桶上的 Minio 基本路径,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 + + 当 `STORAGE_TYPE = xxx` 时,配置将从 `[storage.xxx]` 派生,以下配置项可被覆盖。 + + - `PATH`:同上 + - `MINIO_BASE_PATH`:同上 + +## 存储库归档 (`repo-archive`) + +- `STORAGE_TYPE`:**local**: 存储类型,用于操作日志,`local` 表示本地磁盘,`minio` 表示与 S3 兼容的对象存储服务,默认为 `local`,或者使用定义为 `[storage.xxx]` 的其他名称。 +- `MINIO_BASE_PATH`:**repo-archive/**: Minio 存储桶上的基本路径,仅在 `STORAGE_TYPE` 为 `minio` 时可用。 ## 代理 (`proxy`) @@ -1361,6 +1564,7 @@ PROXY_HOSTS = *.github.com - `ENDLESS_TASK_TIMEOUT`: **3h**: 无尽任务超时时间,指具有运行状态并持续更新,但长时间未结束的任务。 - `ABANDONED_JOB_TIMEOUT`: **24h**: 被遗弃的作业超时时间,指具有等待状态但长时间未被 runner 选中并执行的作业。 - `SKIP_WORKFLOW_STRINGS`: **[skip ci],[ci skip],[no ci],[skip actions],[actions skip]**: 提交者可以在提交消息或 PR 标题中放置的字符串,以跳过执行相应的工作流。 +- `WORKFLOW_DIRS`:**.gitea/workflows,.github/workflows**:以逗号分隔的工作流目录列表,仓库中第一个存在的目录将用于查找 Actions 工作流文件。 `DEFAULT_ACTIONS_URL` 指示 Gitea 操作运行程序应该在哪里找到带有相对路径的操作。 例如,`uses: actions/checkout@v4` 表示 `https://github.com/actions/checkout@v4`,因为 `DEFAULT_ACTIONS_URL` 的值为 `github`。 diff --git a/i18n/zh-cn/docs/version-1.26/administration/customizing-gitea.md b/i18n/zh-cn/docs/version-1.26/administration/customizing-gitea.md new file mode 100644 index 00000000..fafb83c1 --- /dev/null +++ b/i18n/zh-cn/docs/version-1.26/administration/customizing-gitea.md @@ -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: +`Impressum` + +更多信息请参见[添加法律页面](../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`,位于 `` 结束标签之前,例如可用于添加自定义 CSS 文件。 +- `body_outer_pre.tmpl`,位于 `` 起始标签之后。 +- `body_inner_pre.tmpl`,位于顶部导航栏之前,但已处于主容器 `
` 内部。 +- `body_inner_post.tmpl`,位于主容器结束之前。 +- `body_outer_post.tmpl`,位于底部 `