; 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