gitea-selfhost/config/app.ini.template
leora c8d58daabf Review fixes: ALLOWED_HOST_LIST explicit, no password basic auth, bounded storage, rollout order, adversarial e2e
- drop EGRESS_MODE; [security] ALLOWED_HOST_LIST = external (Gitea 28+; [webhook] on 1.23)
- ENABLE_BASIC_AUTHENTICATION = false (tokens still work); e2e clones with the token
- packages and Actions off; attachments and web uploads capped at 4 MB / 3 files
- README: rollout order (edge rate limit first, verify, then captcha off; rollback),
  storage notes (proxy body cap, disk alert, user purge), REGISTER_MANUAL_CONFIRM emergency
  switch, EMAIL_DOMAIN_ALLOWLIST/BLOCKLIST, known gaps (email enumeration, /join reserved names)
- e2e: password basic auth refused (API + git push), token works, 11th repo / org / package
  refused, webhook to 127.0.0.1 not delivered, sign-up burst marked PENDING (edge rule)
2026-10-15 20:40:56 +08:00

133 lines
3.8 KiB
Plaintext

; Gitea app.ini template for gitea-selfhost.
; Rendered by ./kit.sh init into config/app.ini with fresh random secrets.
; Placeholders (dollar + braces) are filled from .env (see .env.example). Do not commit the rendered file.
APP_NAME = ${APP_NAME}
RUN_MODE = prod
WORK_PATH = ${WORK_PATH}
[server]
PROTOCOL = http
DOMAIN = ${DOMAIN}
HTTP_ADDR = ${HTTP_ADDR}
HTTP_PORT = ${HTTP_PORT}
; The public URL people type in the browser (behind your tunnel / reverse proxy).
ROOT_URL = ${ROOT_URL}
; How Gitea reaches itself (hooks, internal API). Always loopback.
LOCAL_ROOT_URL = http://127.0.0.1:${HTTP_PORT}/
APP_DATA_PATH = ${WORK_PATH}/data
; HTTP(S) only: Git over smart HTTP with a username + access token.
DISABLE_SSH = true
START_SSH_SERVER = false
; Never touch the host user's ~/.ssh/authorized_keys.
SSH_CREATE_AUTHORIZED_KEYS_FILE = false
OFFLINE_MODE = true
LFS_START_SERVER = false
[database]
DB_TYPE = sqlite3
PATH = ${WORK_PATH}/data/gitea.db
[repository]
ROOT = ${WORK_PATH}/git/repositories
DEFAULT_BRANCH = main
DEFAULT_PRIVATE = public
; Max repos per regular user (-1 = unlimited). Admins are exempt.
MAX_CREATION_LIMIT = ${MAX_REPOS_PER_USER}
; No importing / mirroring from arbitrary URLs.
DISABLE_MIGRATIONS = true
ENABLE_PUSH_CREATE_USER = false
ENABLE_PUSH_CREATE_ORG = false
[mirror]
; No new pull mirrors either.
DISABLE_NEW_PULL = true
[security]
INSTALL_LOCK = true
SECRET_KEY = ${SECRET_KEY}
INTERNAL_TOKEN = ${INTERNAL_TOKEN}
MIN_PASSWORD_LENGTH = 10
PASSWORD_CHECK_PWN = false
; Outgoing requests (webhooks etc.) may reach public hosts only: no loopback, private or
; link-local addresses (SSRF guard). Gitea >= 28 reads this here; [webhook] ALLOWED_HOST_LIST is
; deprecated there. On Gitea 1.23 put the same line under [webhook] instead.
ALLOWED_HOST_LIST = external
[packages]
; Package registry off: no unbounded blob uploads.
ENABLED = false
[actions]
; Actions off: no runner jobs or artifact storage.
ENABLED = false
[attachment]
; Issue/PR attachments capped at 4 MB, 3 files per upload.
ENABLED = true
MAX_SIZE = 4
MAX_FILES = 3
[repository.upload]
; Web-UI file uploads capped at 4 MB, 3 files.
FILE_MAX_SIZE = 4
MAX_FILES = 3
[oauth2]
JWT_SECRET = ${JWT_SECRET}
[service]
; Public self-registration (set DISABLE_REGISTRATION=true in .env for invite-only).
DISABLE_REGISTRATION = ${DISABLE_REGISTRATION}
SHOW_REGISTRATION_BUTTON = true
; Agent-native: no captcha on sign-up or login. Abuse is limited by the per-user
; defaults (repo cap, no orgs, no migrations/mirrors, webhooks to external hosts only,
; no packages/Actions, small attachments, no password basic auth), not by a challenge.
ENABLE_CAPTCHA = false
REQUIRE_CAPTCHA_FOR_LOGIN = false
; API and git-over-HTTP accept tokens only; password basic auth is refused.
ENABLE_BASIC_AUTHENTICATION = false
; Only turn this on once [mailer] really delivers mail.
REGISTER_EMAIL_CONFIRM = ${REGISTER_EMAIL_CONFIRM}
; Emergency switch: set true to hold new sign-ups until an admin activates them.
REGISTER_MANUAL_CONFIRM = false
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
; Public repos stay browsable without an account.
REQUIRE_SIGNIN_VIEW = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = false
DEFAULT_KEEP_EMAIL_PRIVATE = true
DEFAULT_ENABLE_TIMINGS = false
ENABLE_NOTIFY_MAIL = false
NO_REPLY_ADDRESS = noreply.${DOMAIN}
ENABLE_TIMELINE = true
ENABLE_USER_HEATMAP = false
AUTO_WATCH_NEW_REPOS = false
AUTO_WATCH_ON_CHANGES = false
[mailer]
ENABLED = ${MAILER_ENABLED}
[openid]
ENABLE_OPENID_SIGNIN = false
ENABLE_OPENID_SIGNUP = false
[session]
PROVIDER = file
COOKIE_SECURE = ${COOKIE_SECURE}
[log]
MODE = console
LEVEL = Info
[other]
SHOW_FOOTER_VERSION = false
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
; Large pages so the .profile-last template override orders whole lists, not just one page
[ui]
EXPLORE_PAGING_NUM = 100
[ui.user]
REPO_PAGING_NUM = 100