Forgejo 16.0 配置参数详解

Forgejo 16.0 主配置文件 app.ini 逐段详解:DEFAULT/server/database/security/service/mailer/log/session 等九大段关键参数的默认值、取值规则与实测验证效果(注册开关、密码长度、会话持久化、日志级别、页脚版本等)。

ForgejoForgejo2026/10/17

Forgejo 16.0 配置参数详解

‍‍​​‌​> 目标:把 Forgejo 16.0.6 的主配置文件 app.ini 按段拆开讲透——每个关键参数的默认值、取值规则、改动方法,并用真实改动 + 重启 + 行为对比的实测结果验证效果。全部回显在 Ubuntu 22.04 + Forgejo 16.0.6 环境实测采集。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64)
  • Forgejo 版本:16.0.6({"version":"16.0.6+gitea-1.22.0"},实测)
  • 配置文件路径约定:/etc/forgejo/app.ini(二进制/systemd 部署的标准位置;数据与工作路径 /var/lib/forgejo)
  • Web 端口:3100(下文所有 curl 验证基于此端口)
  • 管理员账号:root / q1w2e3r4(实测环境演示账号)

⚠️ 本文所有参数修改实验的验证对象是「改配置 → 重启服务 → 观察行为」的全链路,行为层面的回显(HTTP 状态码、页面文案、日志行)均为实测照抄。

二、前置条件

2.1 找到你的 app.ini

安装向导完成后,app.ini 落在 WORK_PATH 下的 conf/ 目录。按部署形态确认位置:

forgejo --config /etc/forgejo/app.ini --work-path /var/lib/forgejo --version
forgejo version 16.0.6+gitea-1.22.0 (release name 16.0.6) built with GNU Make 4.4.1, go1.26.9 : bindata, timetzdata, sqlite, sqlite_unlock_notify

若不确定服务实际加载的是哪份配置,看 systemd 单元的 ExecStart 行(--config 参数即配置文件路径):

grep ExecStart /etc/systemd/system/forgejo.service
ExecStart=/usr/local/bin/forgejo web --config /etc/forgejo/app.ini --work-path /var/lib/forgejo

2.2 修改与生效流程(实测)

app.ini 为 INI 格式,修改流程固定为三步,本文每个实验都遵循:

# 1. 修改参数(用 sed 精准替换目标键行)
sed -i 's/^APP_NAME = Forgejo$/APP_NAME = DevOps 代码平台/' /etc/forgejo/app.ini
# 2. 重启服务使其生效
systemctl restart forgejo
# 3. 验证行为
curl -s http://localhost:3100/ | grep -o '<title>[^<]*</title>'

实测输出:

APP_NAME = DevOps 代码平台
<title>DevOps 代码平台</title>

⚠️ 修改配置前先备份:cp /etc/forgejo/app.ini /etc/forgejo/app.ini.bak.$(date +%F)。改错键名不会报错(Forgejo 忽略未知键),只会「改了没效果」——排查时先 grep -n '^键名' /etc/forgejo/app.ini 确认键行真的存在。

三、参数查看与修改方式

3.1 默认生成的 app.ini 全貌

安装向导按用户选择生成的 app.ini 实测共 98 行、16 个段。以下为实测文件全文(敏感值已按实测原样保留示例值,生产请自行更换):

APP_NAME = Forgejo
RUN_MODE = prod
APP_SLOGAN =
RUN_USER = git
WORK_PATH = /data/gitea

[repository]
ROOT = /data/git/repositories

[repository.local]
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo

[repository.upload]
TEMP_PATH = /data/gitea/uploads

[server]
APP_DATA_PATH = /data/gitea
DOMAIN = localhost
SSH_DOMAIN = localhost
HTTP_PORT = 3000
ROOT_URL = http://localhost:3100/
DISABLE_SSH = false
SSH_PORT = 3122
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_JWT_SECRET = so5dWSO15kifh94DH22wDg0kHxJwQJjURC8A-Hy7oJ0
OFFLINE_MODE = true

[database]
PATH =
DB_TYPE = postgres
HOST = forgejo-16-db:5432
NAME = forgejo
USER = forgejo
PASSWD = Forgejo2026Db
LOG_SQL = false
SCHEMA = public
SSL_MODE = disable

[indexer]
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve

[session]
PROVIDER_CONFIG = /data/gitea/sessions
PROVIDER = file

[picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars

[attachment]
PATH = /data/gitea/attachments

[log]
MODE = console
LEVEL = info
ROOT_PATH = /data/gitea/log

[security]
INSTALL_LOCK = true
SECRET_KEY =
REVERSE_PROXY_LIMIT = 1
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3OTIyMzc0MDN9.4YrI89Rb5lteCGI-Q71kgjUpCjH7HuRZlx9jy6lGowo
PASSWORD_HASH_ALGO = pbkdf2_hi

[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = false
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = false
DEFAULT_KEEP_EMAIL_PRIVATE = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING = true
NO_REPLY_ADDRESS = noreply.localhost

[lfs]
PATH = /data/git/lfs

[mailer]
ENABLED = false

[openid]
ENABLE_OPENID_SIGNIN = false
ENABLE_OPENID_SIGNUP = false

[cron.update_checker]
ENABLED = false

[repository.pull-request]
DEFAULT_MERGE_STYLE = merge

[repository.signing]
DEFAULT_TRUST_MODEL = committer

[oauth2]
JWT_SECRET = nXw-HCMu4izbuiR4H1OX4WipmaDkZmrvVktx0MahovY

逐段看:文件开头未落段的 5 个键属于 [DEFAULT] 段(INI 语法:第一个 [段名] 之前的键都归 DEFAULT 段);其余 15 个段按「仓库 → 服务 → 数据库 → 会话/图片/附件 → 日志 → 安全 → 业务行为 → 邮件/认证 → 其他」组织。二进制部署时把 /data/gitea 路径整体理解为 /var/lib/forgejo 即可。

3.2 修改的三种途径

途径做法适用
直接编辑文件编辑 app.ini 后重启服务本文采用,持久、可版本化
管理面板管理员登录 → 站点管理 → 配置,可看运行时快照查看不改(面板改不了文件)
环境变量FORGEJO__段__键 注入(见《Forgejo 16.0 Docker Compose 部署指南》第八章)部署编排场景

四、参数总览

16 个段的关键参数速查(默认值列为安装向导生成或官方默认,均实测核对):

段关键参数默认值作用
DEFAULTAPP_NAMEForgejo站点名称
DEFAULTRUN_MODEprod运行模式(dev 会有调试面板)
DEFAULTRUN_USERgit运行进程的 OS 用户名
DEFAULTWORK_PATH(随部署)数据与配置根目录
serverDOMAIN/SSH_DOMAINlocalhost页面展示的域名(影响 clone URL)
serverHTTP_PORT3000进程监听端口
serverROOT_URLhttp://localhost:3000/对外基础 URL
serverSSH_PORT/SSH_LISTEN_PORT22展示端口 / 实际监听端口
serverLFS_START_SERVERtrue启用 Git LFS
serverOFFLINE_MODE安装勾选禁用外联(头像 CDN 等)
databaseDB_TYPEsqlite3(向导选型)sqlite3/mysql/postgres
databaseLOG_SQLfalse打印 SQL 到日志
securityINSTALL_LOCKfalsetrue 锁死安装向导
securityMIN_PASSWORD_LENGTH8最小密码长度
securityPASSWORD_HASH_ALGOpbkdf2_hi口令哈希算法
serviceDISABLE_REGISTRATIONfalse关闭自助注册
serviceSHOW_REGISTRATION_BUTTONtrue登录页显示注册按钮
sessionPROVIDERfilefile/memory/db/redis
logLEVELinfotrace/debug/info/warn/error
mailerENABLEDfalse邮件发送开关
otherSHOW_FOOTER_VERSIONtrue页脚显示版本号
actionsENABLEDtrue(v9+ 默认)Forgejo Actions 总开关

五、核心参数分类详解

5.1 [DEFAULT] 段:全局标识

APP_NAME:站点名,出现在浏览器标题、页脚、邮件头。实测改为「DevOps 代码平台」后首页标题即时变化(回显见 2.2 节)。

RUN_MODE = prod:prod(生产)与 dev(开发)二选一。dev 模式静态资源不打包、页脚出现调试信息,生产必须 prod。

RUN_USER = git:进程运行身份。必须与文件属主一致,改错会导致仓库读写权限错乱——这是 Forgejo 排障高频问题(症状:push 报 permission denied)。

WORK_PATH:数据根。所有相对路径(session、log、indexer 等)都基于它展开,移动数据目录时只需改这一个键加搬目录。

5.2 [server] 段:域名与端口(实测验证 clone URL)

DOMAIN 与 SSH_DOMAIN 决定页面展示的 clone 地址。实测把两者从 localhost 改为 git.example.com 并重启:

sed -i 's/^DOMAIN = localhost$/DOMAIN = git.example.com/' /etc/forgejo/app.ini
sed -i 's/^SSH_DOMAIN = localhost$/SSH_DOMAIN = git.example.com/' /etc/forgejo/app.ini
systemctl restart forgejo
curl -s http://localhost:3100/api/v1/repos/root/hello-forgejo \
  -H "Authorization: token $TOKEN" \
  | python3 -c "import json,sys; r=json.load(sys.stdin); print('clone_url:',r.get('clone_url')); print('ssh_url:',r.get('ssh_url'))"
clone_url: http://localhost:3100/root/hello-forgejo.git
ssh_url: ssh://git@git.example.com:3122/root/hello-forgejo.git

结果解读:ssh_url 立即变为新域名(git.example.com:3122),而 clone_url 不变——因为 ROOT_URL 是显式写死的基础地址。三者职责:DOMAIN/SSH_DOMAIN 管 SSH 地址展示,ROOT_URL 管 HTTP 地址与页面内链接,反代部署时 ROOT_URL 必须填代理后的外部地址。

SSH_PORT 与 SSH_LISTEN_PORT:前者是「告诉用户的端口」(展示用),后者是进程实际监听的端口。实测安装时 SSH_PORT=3122、SSH_LISTEN_PORT=22,API 返回的 ssh_url 端口即为 3122。当用防火墙/代理把内置 22 端口映射为对外 3122 时,正确写法就是这组默认值的形态。

OFFLINE_MODE = true:禁用外联(Gravatar 头像 CDN、更新检查等),内网部署实测安装向导勾选后写入此键,内网环境推荐保持 true。

LFS_START_SERVER = true:Git LFS 服务开关,默认开启。配套 [server] LFS_JWT_SECRET 自动生成,[lfs] PATH 存储目录默认在工作路径下 git/lfs。

5.3 [database] 段:后端与 SQL 日志(实测验证)

DB_TYPE 支持 sqlite3/mysql/postgres;HOST 含端口;SCHEMA 为 PostgreSQL 专用(默认 public);SSL_MODE 内网 disable。

LOG_SQL:把 ORM 执行的 SQL 打进日志,排障利器但很吵。实测 false → true 后重启,日志立即出现 SQL 行(照抄节选):

2026/10/17 19:47:46 models/db/engine.go:266:InitEngineWithMigration() [I] [SQL] SELECT tablename FROM pg_tables WHERE schemaname = $1 [public] - 2.836212ms
2026/10/17 19:47:46 ...dels/db/collation.go:129:preprocessDatabaseCollation() [I] [SQL] SELECT column_name, column_default, is_nullable, data_type, character_maximum_length, description,

⚠️ 实测发现 LOG_SQL=true 产生的 SQL 日志为 [I] 级别——若同时把 [log] LEVEL 调到 warn,SQL 日志会被一起吞掉。两个参数联用时注意级别关系(见 5.7)。

5.4 [security] 段:锁定与口令策略(实测验证)

INSTALL_LOCK:true 后安装向导永久锁死(再访问 / 直接进首页),安装完成自动写入。它同时是「防重装保险丝」——攻击者无法重置你的站点。

MIN_PASSWORD_LENGTH:默认 8。实测改为 12 后重启,注册 8 位密码被拒(表单实测回显):

Password length cannot be less than 12 characters.

改为 12 位密码(Q1w2e3r4long)后注册成功(HTTP 303 重定向首页)。该键是唯一需要手工追加到 [security] 段的常用参数(默认生成文件不含它)。

PASSWORD_HASH_ALGO = pbkdf2_hi:口令哈希,默认已是高强度配置;[security] SECRET_KEY 与 INTERNAL_TOKEN 安装时自动生成,不可随意改(改 SECRET_KEY 会使 2FA、仓库同步凭据等失效)。

5.5 [service] 段:注册与默认行为(实测验证)

DISABLE_REGISTRATION:关闭自助注册。实测 true 时访问注册页 GET /user/sign_up 返回 200 但页面明确显示(照抄):

Registration is disabled. Please contact your site administrator.

同时实测该状态下注册表单不渲染 CSRF 字段,直接 POST 提交会得到 HTTP 403(Forbidden)——不要把 403 误判为系统故障,它是注册被禁后的防护表现。改回 false 后实测注册成功返回 HTTP 303(自动登录并跳转首页),新用户随即出现在用户列表(实测 GET /api/v1/users/regtest2 返回 id: 2)。

SHOW_REGISTRATION_BUTTON:只控制登录页的「注册」按钮显隐,不影响注册接口。实测 false 后登录页 HTML 中 user/sign_up 链接计数为 0:

curl -s http://localhost:3100/user/login | grep -c 'user/sign_up'
0

与 DISABLE_REGISTRATION=true 搭配可实现「完全不暴露注册入口」。

REQUIRE_SIGNIN_VIEW:true 强制登录后才能浏览任何内容(私有化部署常用)。DEFAULT_ALLOW_CREATE_ORGANIZATION=true:新用户默认可建组织。NO_REPLY_ADDRESS=noreply.localhost:系统邮件发件人地址([mailer] 启用后生效)。

5.6 [mailer] 段:邮件发送

默认 ENABLED = false(页面不发任何邮件)。启用模板(生产需换成真实 SMTP 账号):

[mailer]
ENABLED = true
PROTOCOL = smtps
SMTP_ADDR = smtp.example.com
SMTP_PORT = 465
FROM = Forgejo <noreply@example.com>
USER = noreply@example.com
PASSWD = `${SMTP_PASSWORD}`

启用后「注册邮箱确认」「密码找回」「Issue 通知」等邮件功能生效;[service] ENABLE_NOTIFY_MAIL 控制是否给用户发事件通知邮件。本文实测环境无外发 SMTP,未启用,保持 false。

5.7 [log] 段:级别与输出(实测验证)

LEVEL:根日志级别。实测 info → warn 后重启,再发起请求,访问日志完全消失(实测对比:info 时每次请求都有一行 [I] router: completed GET /api/v1/version ... 200 OK,warn 后同请求日志 0 行)。排障时临时调回 info 或 debug 即可看到路由明细。

MODE = console:日志输出目标。console 交给服务管理器统一收集(journalctl -u forgejo);可选 file(落到 ROOT_PATH)与 conn(syslog)。生产推荐 console 交给 systemd/journald 管理。

5.8 [session] 段:会话存储(实测验证 file 与 memory 差异)

PROVIDER:会话存储后端。默认 file,落到 PROVIDER_CONFIG 目录(工作路径下 sessions/)。

实测对比一(file):登录后取到会话 cookie,重启服务,携带同 cookie 访问登录态页面:

curl -s -b /tmp/lg-cookie.txt -o /dev/null -w 'HTTP %{http_code}\n' http://localhost:3100/user/settings

重启前:

HTTP 200

重启后(file 会话落盘,登录态保持):

HTTP 200

实测对比二(改为 memory):同样的「登录 → 重启 → 带 cookie 访问」流程,重启后实测返回:

HTTP 303, redirect=http://localhost:3100/user/login

服务日志同时出现(照抄):

2026/10/17 19:51:55 ...eb/routing/logger.go:109:func1() [I] router: completed GET /user/settings for 192.168.208.1:52770, 303 See Other in 0.1ms @ web/web.go:251(web.init.verifyAuthWithOptions)

结论:memory 重启即全员掉线,只适合一次性测试;生产必须 file(单机)或 db/redis(多副本部署时共享会话)。实测完成后已恢复 PROVIDER = file。

5.9 [indexer] 段:搜索索引

ISSUE_INDEXER_PATH 指向 Issue 全文索引(bleve 引擎)。代码索引由 [indexer] REPO_INDEXER_ENABLED(默认 false)开启,开启后仓库页出现「代码搜索」,大仓库首次建索引耗时明显,建议低峰开启。

5.10 [oauth2]/[openid]/[cron.update_checker] 段

  • [oauth2] JWT_SECRET:OAuth2 Provider 令牌签名密钥,安装时自动生成,勿外泄勿更换
  • [openid] ENABLE_OPENID_SIGNIN/SIGNUP:OpenID 登录/注册开关,默认全关
  • [cron.update_checker] ENABLED:检查新版更新提醒,内网(OFFLINE_MODE=true)自动关闭
  • [actions] ENABLED:Forgejo Actions 总开关,v9 起默认启用(实测 16.0 未写该键即默认开,Actions API 返回 HTTP 200),Runner 注册与 CI 入门见《Forgejo 16.0 运维手册》

5.11 [other] 段:页脚展示(实测验证)

SHOW_FOOTER_VERSION:页脚是否显示版本号。实测 true/false 对照:true 时页脚渲染出(照抄):

Version:

        16.0.6

改回 false 后重启,页面 HTML 中 Version: 计数为 0(grep -c 'Version:' 输出 0)。

⚠️ HTML 里另有一类 ?v=16.0.6~gitea-1.22.0 字样是静态资源 cache-busting 参数(css/js 地址后缀),与页脚版本展示无关,不受该参数控制——实测两者同页共存,勿混淆。

六、生产配置模板

以下为一份面向「50 人团队、8C16G 服务器、PostgreSQL、开启 CI」的生产模板(在默认生成文件基础上增改,路径按二进制部署 /var/lib/forgejo 书写):

APP_NAME = 团队代码平台
RUN_MODE = prod
RUN_USER = git
WORK_PATH = /var/lib/forgejo

[server]
DOMAIN = git.example.com
SSH_DOMAIN = git.example.com
HTTP_PORT = 3000
ROOT_URL = https://git.example.com/
SSH_PORT = 22
SSH_LISTEN_PORT = 22
OFFLINE_MODE = false
LFS_START_SERVER = true

[database]
DB_TYPE = postgres
HOST = 127.0.0.1:5432
NAME = forgejo
USER = forgejo
PASSWD = `${FORGEJO_DB_PASSWORD}`
SCHEMA = public
SSL_MODE = disable
LOG_SQL = false

[security]
INSTALL_LOCK = true
MIN_PASSWORD_LENGTH = 12
PASSWORD_HASH_ALGO = pbkdf2_hi

[service]
DISABLE_REGISTRATION = true
SHOW_REGISTRATION_BUTTON = false
REQUIRE_SIGNIN_VIEW = false

[session]
PROVIDER = file
PROVIDER_CONFIG = /var/lib/forgejo/data/sessions

[log]
MODE = console
LEVEL = info

[mailer]
ENABLED = true
PROTOCOL = smtps
SMTP_ADDR = smtp.example.com
SMTP_PORT = 465
FROM = Forgejo <noreply@example.com>

[other]
SHOW_FOOTER_VERSION = false

逐项说明(与默认值的差异):站点名/域名/ROOT_URL 换生产值;MIN_PASSWORD_LENGTH=12 加固口令(实测拒绝弱密码有效);DISABLE_REGISTRATION + SHOW_REGISTRATION_BUTTON=false 关闭注册入口(实测入口消失);session 保持 file(单机部署实测重启不掉线);LOG_SQL=false 保持安静;SHOW_FOOTER_VERSION=false 隐藏版本指纹(实测页脚 Version 块消失)。适用规模:50-200 活跃用户、千级仓库、启用 Actions;更大的规模请把 session 换 db 并参考官方 config-cheat-sheet 调整队列与缓存段。

七、常见问题

Q1:改了 app.ini 重启后没有任何效果? 按序排查:① grep -n '^键名' 确认键行存在且未拼错段(INI 键必须在其段标题之后);② 确认重启的是正确服务(systemctl status forgejo 显示的 ExecStart 与你改的文件一致);③ 确认没有环境变量在覆盖同名键(FORGEJO__段__键 优先于文件)。

Q2:SECRET_KEY 或 INTERNAL_TOKEN 丢了/改坏了? forgejo generate secret 子命令可重新生成各类密钥(实测 forgejo --help 可见 generate Generate Forgejo's secrets/keys/tokens)。重生成后 INTERNAL_TOKEN 需要用 forgejo admin 系列重刷,普通场景建议从备份恢复原值而不是重新生成。

Q3:忘记管理员密码怎么办?

forgejo admin user change-password --config /etc/forgejo/app.ini --must-change-password=false -u root -p 新密码

(forgejo admin 子命令实测存在,帮助输出含 Perform common administrative operations。)

Q4:改了 DOMAIN 后仓库页面还是旧地址? clone_url 由 ROOT_URL 决定而不是 DOMAIN(5.2 节实测可证)。改域名时两者都要改,并确认反代/防火墙同步。

Q5:LOG_SQL 打开了怎么关? 改回 LOG_SQL = false 重启即可。注意实测发现它与 [log] LEVEL 的联动:LEVEL 在 warn 以上时 SQL 行本就被过滤,两个一起调时先调 LEVEL 再看 SQL 是否达到预期。

八、参考链接