GitBucket 4.48.0 配置参数详解
把 GitBucket 4.48.0 的配置拆成启动参数、JVM 系统属性、环境变量、gitbucket.conf 与 database.conf 五类载体,逐项给出默认值、作用域与实测结论,覆盖 H2→MySQL/PostgreSQL 切换、LDAP/OIDC、SMTP、反向代理与 base URL、JVM 内存与 GC、日志,含端口/数据目录/base_url 优先级与引号陷阱的真实回显。
目标:把 GitBucket 4.48.0 的配置拆成启动参数、系统属性、环境变量、gitbucket.conf、database.conf 五类载体,逐项给出默认值、作用域与实测结论,覆盖数据库切换、LDAP/OIDC、SMTP、反向代理与 base URL、JVM 内存与 GC、日志。
GitBucket 4.48.0 配置参数详解
GitBucket 的配置分散在四个地方:JVM 启动参数(--port 这类)、JVM 系统属性(-Dgitbucket.xxx)、环境变量(GITBUCKET_XXX)、以及 $GITBUCKET_HOME 下的 gitbucket.conf 与 database.conf。它们不是一套统一的优先级,而是两条不同的优先级链:启动参数类是「命令行 > 环境变量 > 系统属性」,业务设置类是「系统属性 > 环境变量 > 配置文件」。搞混这两条链,就会出现「明明写了配置却不生效」的排查地狱。
本文所有回显来自 2026-10-27 在 GitBucket 4.48.0 部署实例上的实测,实例为 Ubuntu 22.04 + OpenJDK 17.0.20.1 + systemd 托管,数据目录 /opt/gitbucket/data,监听 8080;对比实验在 8091–8104 端口上以独立数据目录启动,互不干扰。
一、配置载体与优先级
1.1 五类配置载体
| 载体 | 形式 | 生效范围 | 典型用途 |
|---|---|---|---|
| Jetty 启动参数 | --port=8080、--prefix=/gitbucket | 进程级,只影响 Web 监听 | 端口、监听地址、HTTPS、URL 前缀 |
| JVM 系统属性 | -Dgitbucket.port=8080、-Dgitbucket.base_url=... | 进程级 | 与命令行同名的兜底,或业务设置 |
| 环境变量 | GITBUCKET_PORT=8080、GITBUCKET_BASE_URL=... | 进程级 | systemd EnvironmentFile、批量部署 |
gitbucket.conf | $GITBUCKET_HOME/gitbucket.conf(HOCON 文件) | 实例级,业务设置默认值 | 站点 URL、SMTP、LDAP、OIDC、上传限制 |
database.conf | $GITBUCKET_HOME/database.conf(HOCON 文件) | 实例级,仅数据库 | 数据库 URL、账号、连接池 |
1.2 两条优先级链(实测)
启动参数类(端口为例):
# 只给环境变量
GITBUCKET_PORT=8098 java -Dgitbucket.home=/tmp/hG -jar gitbucket.war
# ss -ltn | grep 8098 → LISTEN(环境变量生效)
# 环境变量 + 命令行
GITBUCKET_PORT=8098 java -Dgitbucket.home=/tmp/hG -jar gitbucket.war --port=8099
# ss -ltn → 只有 8099 在听(命令行覆盖环境变量)
# 环境变量 + 系统属性
GITBUCKET_PORT=8098 java -Dgitbucket.home=/tmp/hG -Dgitbucket.port=8100 -jar gitbucket.war
# ss -ltn → 只有 8098 在听(环境变量覆盖系统属性)
实测三次监听的端口分别是 8098 / 8099 / 8098,结论:命令行 > 环境变量 > -Dgitbucket.port。系统属性在这一链里排最后,和很多 Java 程序的直觉相反。
业务设置类(base_url 为例):
# 只在 gitbucket.conf 写 base_url = https://gitbucket.example.com
curl -D- -d "userName=root&password=root&hash=" http://127.0.0.1:8093/signin | grep -i Location
# Location: https://gitbucket.example.com/;jsessionid=node0hmn...
# 再加环境变量 GITBUCKET_BASE_URL=http://env.example.com
# Location: http://env.example.com/;jsessionid=node0q6h...
# 再加系统属性 -Dgitbucket.base_url=http://sys.example.com
# Location: http://sys.example.com/;jsessionid=node011x...
结论:系统属性 > 环境变量 > gitbucket.conf。这一链由 ConfigUtil.getConfigValue(key) 实现:先读系统属性 gitbucket.<key>,再读环境变量 GITBUCKET_<KEY 大写、点号转下划线>,都没有才回落到配置文件。
💡 技术拓展:
ConfigUtil的键转换是机械式大写替换——base_url→GITBUCKET_BASE_URL,useSMTP→GITBUCKET_USESMTP(不是GITBUCKET_USE_SMTP),smtp.host→GITBUCKET_SMTP_HOST(点号变下划线,但驼峰不拆)。写环境变量前先用-D实测一次,比猜命名规则可靠。
1.3 一句话记忆法
- 想让进程换端口/换前缀:改命令行或环境变量,别指望
-D。 - 想让站点行为变化(URL、邮件、认证):改
gitbucket.conf,需要临时覆盖就用环境变量或-D。
二、GITBUCKET_HOME 的解析顺序
所有数据、配置、插件都挂在 GITBUCKET_HOME 下。它的解析顺序实测为:
- JVM 系统属性
-Dgitbucket.home; - 环境变量
GITBUCKET_HOME; - 默认
~/.gitbucket。
三次实测(看 Hikari 建池时的 JDBC URL 即可确认实际目录):
# 同时给系统属性与环境变量
GITBUCKET_HOME=/tmp/hB java -Dgitbucket.home=/tmp/hA -jar gitbucket.war --port=8091
# 13:01:27 [main] INFO HikariPool-1 - Added connection conn0: url=jdbc:h2:/tmp/hA/data user=SA
# → 系统属性优先
# 只给环境变量
GITBUCKET_HOME=/tmp/hB java -jar gitbucket.war --port=8092
# 13:01:38 [main] INFO HikariPool-1 - Added connection conn0: url=jdbc:h2:/tmp/hB/data user=SA
# → 环境变量生效
# 两者都不给
java -jar gitbucket.war --port=8102
# 13:07:40 [main] INFO HikariPool-1 - Added connection conn0: url=jdbc:h2:/root/.gitbucket/data user=SA
# → 默认目录是 ~/.gitbucket,不是 ~/gitbucket
~/.gitbucket 这个默认值容易踩坑:以 systemd 的 User=gitbucket 运行且没有设环境变量时,数据会落到 /opt/gitbucket/.gitbucket(系统用户 home)而不是你以为的 /opt/gitbucket/data。安装时务必显式指定。
目录结构(/opt/gitbucket/data 实测):
/opt/gitbucket/data/
├── activity.log # 活动流水(JSON Lines)
├── data.mv.db # H2 数据库文件
├── database.conf # 数据库连接配置(首次启动自动生成)
├── gist/ # Gist 数据
├── plugins/ # 插件 jar(首次启动自动解包 4 个内置插件)
├── repositories/ # 裸 git 仓库
├── tmp/ # Jetty 临时目录
└── gitbucket.conf # 业务设置默认值(手工创建,默认不存在)
gitbucket.conf 默认不存在,需要自己创建;database.conf 在第一次启动时自动生成。
三、gitbucket.conf 的语法与全量键
3.1 语法:HOCON 外壳,字符串取值不带引号
gitbucket.conf 是 HOCON 文件,但取值不以 Typesafe Config 的方式解析,而是按原始字符串交给业务层。最直接的后果:值加了引号会连引号一起被当成内容。
实测:写 base_url = "https://gitbucket.example.com"(带引号)后,登录直接 500:
13:02:06.937 [qtp20132171-19] ERROR g.c.controller.PreProcessController - Catch unhandled error in request: Request(POST http://127.0.0.1:8093/signin)
java.net.URISyntaxException: Illegal character in scheme name at index 0: "https://gitbucket.example.com"
at java.base/java.net.URI$Parser.fail(URI.java:2976)
at gitbucket.core.controller.Context.<init>(ControllerBase.scala:354)
at gitbucket.core.controller.ControllerBase.context(ControllerBase.scala:100)
at gitbucket.core.controller.PreProcessControllerBase.$anonfun$$init$$5(PreProcessController.scala:32)
把引号去掉后立刻正常:
base_url = https://gitbucket.example.com
curl -D- -d "userName=root&password=root&hash=" http://127.0.0.1:8093/signin | grep -i Location
# Location: https://gitbucket.example.com/;jsessionid=node0hmnbu0u4sh6v1ly1ww9nx0wsc0.node0
⚠️ 与
database.conf对比:database.conf是真正的 Typesafe Config 解析,必须带引号(默认生成的文件就是url = "jdbc:h2:${DatabaseHome}")。两个文件同目录、同为 HOCON,引号规则却相反,这是 GitBucket 4.48.0 最容易踩的坑之一。
3.2 常用键与默认值
下表的默认值取自一个全新数据目录的实例(首启后打开 Administration → System settings 读取表单值),未改任何配置。
| 键 | 默认值 | 说明 |
|---|---|---|
base_url | 空 | 站点对外根 URL,反代/HTTPS 场景必须写,影响重定向、webhook、邮件链接 |
information | 空 | 登录页公告(支持 Markdown) |
allow_account_registration | false | 是否允许自助注册 |
allow_reset_password | false | 是否允许「忘记密码」重置 |
reset_password_token_expiration | 10 | 重置令牌有效期(分钟) |
allow_anonymous_access | true | 匿名可读公开仓库 |
is_create_repository_option_public | true | 新建仓库时「公开」选项默认勾选 |
allow_create_repository_by_clone | false | 允许从远程克隆创建仓库 |
repository_operation_create/delete/rename/transfer/fork | 均 true | 允许普通用户执行的仓库操作 |
limitVisible_repositories(表单名 basicBehavior.limitVisibleRepositories) | false | 仅展示有权限的仓库 |
compare_no_check_by_default | false | 比较页默认不跑 CI 检查 |
gravatar | false | 使用 Gravatar 头像 |
notification | false | 开启站内通知(需同时配 SMTP) |
showMailAddress | false | 公开显示邮箱 |
default_branch | main | 新建仓库默认分支名 |
show_full_name | false | 页面展示用户全名 |
upload.maxFileSize | 3145728 | 普通上传上限(字节,3 MB) |
upload.timeout | 30000 | 普通上传超时(ms) |
upload.largeMaxFileSize | 3145728 | 大文件上传上限(字节) |
upload.largeTimeout | 30000 | 大文件上传超时(ms) |
repository_viewer_max_files | 0 | 单次展示的变更文件数上限,0 = 不限 |
repository_viewer_max_diff_files | 100 | 差异页最多渲染的文件数 |
repository_viewer_max_diff_lines | 1000 | 差异页最多渲染的行数 |
webhook.block_private_address | false | 禁止 webhook 指向内网地址(SSRF 防护,生产建议开) |
webhook.whitelist | 空 | webhook 地址白名单(逗号分隔) |
skinName | 空 | 皮肤名,空为默认 |
userDefinedCss | 空 | 自定义 CSS |
upload.maxFileSize 的 3145728 字节(3 MB)在 4.48.0 默认值下偏小,上传 release 附件或大 patch 时很容易触发 413,生产建议按 104857600(100 MB)调大。
3.3 键名与后台表单的对应关系
后台表单的字段名是嵌套结构(smtp.host、ldap.baseDN、webhook.blockPrivateAddress),而配置文件里既有平铺键也有嵌套键。实测确认的对应关系:
| 后台表单字段 | 配置文件键 |
|---|---|
baseUrl | base_url |
basicBehavior.allowAnonymousAccess | allow_anonymous_access |
basicBehavior.repositoryOperation.create | repository_operation_create |
smtp.host | smtp.host |
ldap.bindPassword | ldap.bind_password |
oidc.clientID | oidc.client_id |
webhook.blockPrivateAddress | webhook.block_private_address |
ssh.enabled | ssh |
规律:配置文件里用蛇形命名,后台表单用驼峰,两者不是逐字对应。写配置文件时以本文表格的键名为准。
3.4 配置文件值的可见性验证
在全新实例的 gitbucket.conf 写入一组值后,打开后台能直接看到回填结果(说明配置文件确实作为默认值被读取):
useSMTP = true
smtp.host = 127.0.0.1
smtp.port = 2525
smtp.user = noreply@example.com
smtp.from_address = noreply@example.com
smtp.from_name = GitBucket Notify
curl -s -b e.txt http://127.0.0.1:8096/admin/system | grep -E 'id="(smtpHost|smtpPort|fromAddress|fromName)"'
表单回显(节选):
smtpHost = 127.0.0.1
smtpPort = 2525
fromAddress = noreply@example.com
fromName = GitBucket Notify
useSMTP checked: True
⚠️ 实测真问题:后台「System settings」页面的保存接口
POST /admin/system,用脚本按表单字段原样提交时返回 400(无响应体、无异常日志),只有浏览器端 JS 组装完整字段才能保存成功。自动化部署不要试图用 curl 改后台设置,直接写gitbucket.conf+ 环境变量。
四、数据库配置(database.conf)
4.1 文件与键
database.conf 首次启动自动生成,内容逐字如下:
db {
url = "jdbc:h2:${DatabaseHome}"
user = "sa"
password = "sa"
# connectionTimeout = 30000
# idleTimeout = 600000
# maxLifetime = 1800000
# minimumIdle = 10
# maximumPoolSize = 10
}
${DatabaseHome} 是 GitBucket 内置变量,解析为 $GITBUCKET_HOME/data。可用键:
| 键 | 默认值 | 说明 |
|---|---|---|
db.url | jdbc:h2:${DatabaseHome} | JDBC URL |
db.user / db.password | sa / sa | 数据库账号 |
db.jdbcDriver | 按 URL 推断 | 驱动类名,一般不用写 |
db.slickDriver | 按 URL 推断 | Slick profile |
db.liquiDriver | 按 URL 推断 | Liquibase 方言 |
db.connectionTimeout | 30000 | 取连接超时(ms) |
db.idleTimeout | 600000 | 空闲连接回收(ms) |
db.maxLifetime | 1800000 | 连接最大存活(ms) |
db.minimumIdle | 10 | 最小空闲连接数 |
db.maximumPoolSize | 10 | 最大连接数 |
内置驱动(war 内 WEB-INF/lib):h2-2.5.250.jar、postgresql-42.7.13.jar、mariadb-java-client-2.7.15.jar。没有 mysql-connector-j,MySQL 连接靠 MariaDB 驱动兼 容 jdbc:mysql:// 前缀(Connector/J 2.x 支持该前缀,3.x 需要 permitMysqlScheme)。
4.2 切 PostgreSQL(实测)
sudo apt install -y postgresql-15
sudo -u postgres psql -c "CREATE USER gitbucket WITH PASSWORD 'gb_pg_2026';"
sudo -u postgres psql -c "CREATE DATABASE gitbucket OWNER gitbucket;"
db {
url = "jdbc:postgresql://127.0.0.1:5432/gitbucket"
user = "gitbucket"
password = "gb_pg_2026"
maximumPoolSize = 10
}
重启后日志:
12:25:54.796 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
12:25:54.803 [main] WARN c.z.hikari.util.DriverDataSource - Registered driver with driverClassName=org.postgresql.Driver2 was not found, trying direct instantiation.
12:25:55.103 [main] INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@2b4786dd
建表结果:
sudo -u postgres psql -d gitbucket -tAc "select count(*) from information_schema.tables where table_schema='public'"
# 43
43 张表(42 张业务表 + versions 之外的 Liquibase 辅助表随版本略有差异),说明 schema 迁移完成。
⚠️ 实测真问题:
driverClassName=org.postgresql.Driver2 was not found是 GitBucket 4.48.0 自己把驱动类名写成了org.postgresql.Driver2(多了一个2)。HikariCP 捕获异常后回落为直接实例化,连接仍能建立,但每次启动都会打一条 WARN。监控若把 WARN 计为故障,需要单独放行。
4.3 切 MySQL(配置说明,本环境无实例未实测)
db {
url = "jdbc:mysql://127.0.0.1:3306/gitbucket?characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true"
user = "gitbucket"
password = "q1w2e3r4"
maximumPoolSize = 10
}
注意点:
characterEncoding=UTF-8必带,否则中文仓库名、issue 会乱码;- MySQL 端要
CREATE DATABASE gitbucket CHARACTER SET utf8mb4; - 驱动是 MariaDB 2.x,若遇到
Unknown database之外的表征错误,先在db.jdbcDriver显式写org.mariadb.jdbc.Driver试。
4.4 H2 版本与迁移
war 内置 H2 2.5.250。从 4.42 及更早升级且继续用 H2 的实例,必须手工迁移 1.x → 2.x(导出 SQL → 改方言 → 导入),否则新版本启动即报 H2 语法/文件格式错误。切了 PostgreSQL/MySQL 的实例不受影响。
五、LDAP 认证
5.1 键与默认值
| 键 | 默认值 | 说明 |
|---|---|---|
ldap_authentication | false | 总开关 |
ldap.host | 空 | LDAP 服务地址 |
ldap.port | 空(389) | 端口 |
ldap.bindDN | 空 | 绑定账号 DN |
ldap.bind_password | 空 | 绑定密码 |
ldap.baseDN | 空 | 用户搜索基准 DN |
ldap.username_attribute | 空(uid) | 登录名属性 |
ldap.fullname_attribute | 空(cn) | 全名属性 |
ldap.mail_attribute | 空(mail) | 邮箱属性 |
ldap.additional_filter_condition | 空 | 附加过滤条件 |
ldap.tls / ldap.ssl | false | StartTLS / LDAPS |
ldap.keystore | 空 | LDAPS 信任库路径 |
5.2 实测
配置(base_url 与 LDAP 同文件):
ldap_authentication = true
ldap.host = 127.0.0.1
ldap.port = 389
ldap.bindDN = cn=admin,dc=example,dc=com
ldap.bind_password = ldappass
ldap.baseDN = ou=people,dc=example,dc=com
ldap.username_attribute = uid
后台表单回填确认配置已读取:
ldapHost = 127.0.0.1
ldapPort = 389
ldapBaseDN = ou=people,dc=example,dc=com
ldapAuthentication checked: True
本机 389 端口没有 LDAP 服务,用任意账号登录:
curl -s -o /dev/null -w "login=%{http_code} -> %{redirect_url}\n" \
-d "userName=ldapuser&password=badpass&hash=" http://127.0.0.1:8097/signin
# login=302 -> http://127.0.0.1:8097/signin;jsessionid=node0rmya...
日志:
13:05:15.018 [qtp20132171-20] INFO gitbucket.core.util.LDAPUtil$ - LDAPException: Unable to connect to server 127.0.0.1:389 (91) Connect Error
java.net.ConnectException: Connection refused
13:05:15.018 [qtp20132171-20] INFO g.core.service.AccountService - LDAP error: System LDAP authentication failed.
13:05:15.489 [qtp20132171-16] INFO g.core.service.AccountService - Failed to authenticate: ldapuser
结论:开启 LDAP 后所有登录都会先走 LDAP(包括本地 root),LDAP 不可达就一律失败。所以务必先留一个本地管理员账号、或准备好 LDAP 排障窗口,不要在远程 LDAP 没通的情况下打开开关然后重启。
⚠️ 提示:LDAP 错误只打到 INFO 级别、不带 HTTP 错误码(登录失败仍是 302 回登录页),只从浏览器看不出是「密码错」还是「LDAP 连不上」,排障必须看服务端日志。
六、OIDC / OAuth 登录
6.1 键与默认值
| 键 | 默认值 | 说明 |
|---|---|---|
oidc_authentication | false | 总开关 |
oidc.issuer | 空 | 提供发现文档的 issuer URL |
oidc.client_id | 空 | 客户端 ID |
oidc.client_secret | 空 | 客户端密钥 |
oidc.jws_algorithm | 空(默认 RS256) | ID Token 签名算法 |
6.2 实测
oidc_authentication = true
oidc.issuer = http://127.0.0.1:9999
oidc.client_id = gitbucket-client
oidc.client_secret = s3cr3t
登录页出现了入口:
curl -s http://127.0.0.1:8097/signin | grep -o -E "(/signin/oidc|Sign in with[^<]*)"
# /signin/oidc
# Sign in with OpenID Connect
后台表单回填:
oidcIssuer = http://127.0.0.1:9999
oidcClientID = gitbucket-client
oidcAuthentication checked: True
结论:OIDC 开关与 issuer 配置在登录页渲染阶段就生效,不需要等用户点击;issuer 地址不通时按钮仍在,点击才会报错。生产对接 Keycloak/Auth0 时,oidc.issuer 必须是带 https:// 且能被服务端访问到的 discovery 根地址。
七、邮件(SMTP)
7.1 键与默认值
| 键 | 默认值 | 说明 |
|---|---|---|
useSMTP | false | 总开关,关闭时所有通知静默丢弃 |
smtp.host | 空 | SMTP 服务器 |
smtp.port | 空(25) | 端口 |
smtp.user | 空 | 认证账号 |
smtp.password | 空 | 认证密码 |
smtp.ssl | false | 直连 SSL(465) |
smtp.starttls | false | StartTLS(587) |
smtp.from_address | 空 | 发件地址 |
smtp.from_name | 空 | 发件人显示名 |
7.2 实测:完整收发链路
起一个本地假 SMTP(监听 2525,打印每行命令),配置写入 gitbucket.conf,然后用后台「Test mail」接口发送:
curl -s -b e.txt -X POST \
-d "smtp.host=127.0.0.1&smtp.port=2525&smtp.user=noreply@example.com&smtp.password=smtppass&smtp.ssl=false&smtp.starttls=false&smtp.fromAddress=noreply@example.com&smtp.fromName=GitBucket+Notify&testAddress=admin@example.com" \
http://127.0.0.1:8096/admin/system/sendmail
# Test mail has been sent to: admin@example.com
SMTP 会话实录:
CMD|EHLO gb-b1
CMD|MAIL FROM:<noreply@example.com>
CMD|RCPT TO:<admin@example.com>
CMD|DATA
DATA|Date: Tue, 27 Oct 2026 13:04:50 +0000 (UTC)
DATA|From: GitBucket Notify <noreply@example.com>
DATA|To: admin@example.com
DATA|Message-ID: <822637135.1.1793106290562@gb-b1>
DATA|Subject: Test message from GitBucket
DATA|MIME-Version: 1.0
DATA|Content-Type: multipart/mixed;
DATA| boundary="----=_Part_0_1261056815.1793106290493"
DATA|
DATA|------=_Part_0_1261056815.1793106290493
DATA|Content-Type: text/plain; charset=UTF-8
DATA|Content-Transfer-Encoding: 7bit
DATA|
DATA|This is a test message from GitBucket.
DATA|------=_Part_0_1261056815.1793106290493--
DATA|.
CMD|QUIT
结论:不需要真正发到外部邮箱,/admin/system/sendmail 用表单里提交的 SMTP 参数即时发信,是验证 SMTP 配置的最快方式。注意它不落库——只验证参数,不改保存的配置。
7.3 常见坑
useSMTP = false时通知全部静默丢弃,日志无报错,表现为「有 issue 但没人收到邮件」;- 465 端口要
smtp.ssl = true且starttls = false;587 端口反过来; smtp.from_address必填,很多 SMTP 服务(如企业邮局)会校验发件人与认证账号一致;- 算术:
notification = true只是开启站内通知,邮件还需要useSMTP = true才算完整。
八、反向代理与 base URL
8.1 base_url 必须与外部访问地址一致
GitBucket 生成绝对链接(重定向、webhook payload、邮件里的链接、RSS)都用 base_url。反代到 HTTPS 域名时必须显式配置,否则用户会被重定向回 http://内网IP:8080。
base_url = https://git.example.com
实测生效表现(登录成功后 302 的目标即 base_url):
Location: https://gitbucket.example.com/;jsessionid=node0hmn...
8.2 反代到子路径:prefix + base_url 组合
--prefix=/gitbucket 让所有路由挂在子路径下,实测:
java -jar gitbucket.war --port=8094 --prefix=/gitbucket
curl -s -o /dev/null -w "prefix/signin=%{http_code} " http://127.0.0.1:8094/gitbucket/signin
curl -s -o /dev/null -w "root/signin=%{http_code}\n" http://127.0.0.1:8094/signin
# prefix/signin=200 root/signin=404
组合配置:
base_url = https://git.example.com/gitbucket
再加 --prefix=/gitbucket。两者路径必须一致,只配一个会出现「页面能开、静态资源和重定向全错」的半残状态。
8.3 反代要点
X-Forwarded-Proto https必须透传,否则 GitBucket 认为自己是 http;client_max_body_size按upload.maxFileSize设置,默认 3 MB 的上传上限在反代层先被 1 MB 的 nginx 默认值拦住;proxy_read_timeout要覆盖大仓库 clone 时间;- HTTPS 由反代终结时,GitBucket 自身仍监听 http 即可,不必配 keystore。
8.4 SSH 的对外地址
SSH 若启用(ssh = true),要给客户端一个可连的地址:ssh.publicAddress.host / ssh.publicAddress.port。这两项与 base_url 无关,反代不会自动推导,必须单独配。
九、JVM 内存与 GC
9.1 参数位置
生产实例把 JVM 参数集中在 systemd 的环境变量文件里,改参数不动单元文件:
cat /etc/default/gitbucket
# JAVA_OPTS="-Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError"
# GITBUCKET_HOME=/opt/gitbucket/data
ExecStart=/bin/sh -c "exec /usr/bin/java $JAVA_OPTS -jar /opt/gitbucket/gitbucket.war --port=8080"
9.2 堆大小实测
-Xms512m -Xmx512m固定堆,进程常驻内存 423 MB 左右(systemctl status的Memory: 423.8M);- 集群/多实例部署时按「实例数 × 512 MB」预留,另加 150–250 MB 的元空间与线程栈开销;
- 堆不建议低于 256 MB:H2 建库 + 插件加载 + Liquibase 迁移会短时吃满小堆,表现为启动阶段频繁 Full GC 甚至
OutOfMemoryError: Metaspace。
jps -v 交叉验证:
6745 war -Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError 的用意是 OOM 时直接退出交给 systemd 重启,而不是留一个僵死但「还在监听」的进程。
9.3 GC 实测
4.48.0 在 JDK 17 上默认 G1。打开 GC 日志:
java -Xms256m -Xmx256m -Xlog:gc -jar gitbucket.war --port=8093
[0.004s][info][gc] Using G1
[0.917s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 21M->2M(256M) 3.917ms
[1.045s][info][gc] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 46M->2M(256M) 1.842ms
启动阶段两次 Young GC 都在 4 ms 内,256 MB 堆启动无压力。内存更大的宿主可以把 -XX:MaxGCPauseMillis 设为 100–200 ms 优化停顿,但 GitBucket 这类 IO 型应用收益有限,不建议盲调。
💡 技术拓展:JVM 收集器选型上,GitBucket 属于「低分配速率 + 大量小对象 + 长连接」的服务,G1 是默认也是合理选择。ZGC 需要更大堆且对小堆收益不明显;SerialGC 在单核小内存环境下反而更省;ParallelGC 吞吐高但停顿不可控,不适合 Web 交互。除非有明确的停顿指标,保持 G1 即可。
9.4 systemd 层的第二道闸
MemoryMax=512M
MemoryHigh=384M
MemoryHigh 是软限(超过后节流),MemoryMax 是硬限(超过后 OOM kill)。若设置了 MemoryMax=512M 且堆也是 512 MB,JVM 会因为元空间/栈开销被 systemd 杀掉——两者要留 30% 余量,例如堆 512 MB + MemoryMax=768M。
十、日志
10.1 输出去向
systemd 托管时全部进 journald:
journalctl -u gitbucket -n 20 --no-pager
journalctl -u gitbucket -f
启动日志开头的三条告警是 4.48.0 的固有现象:
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
业务日志实际由 logback 输出,这三条只说明 SLF4J 的绑定探测没找到 provider,不影响日志完整性,不必修。
10.2 调整日志级别
GitBucket 用 logback,可通过外部配置文件覆盖(不动 war):
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n</pattern></encoder>
</appender>
<logger name="gitbucket" level="DEBUG"/>
<root level="INFO"><appender-ref ref="STDOUT"/></root>
</configuration>
java -Dlogback.configurationFile=/opt/gitbucket/logback-debug.xml -jar gitbucket.war --port=8095
grep -c " DEBUG " /tmp/t8.log # 1
grep -m1 " DEBUG " /tmp/t8.log
# 13:03:23.532 [main] DEBUG g.c.s.Database$ - load database connection pool
实测 DEBUG 级别在启动阶段只多出 1 行(load database connection pool),说明 GitBucket 4.48.0 本身的 DEBUG 日志很少;排查 SQL 或认证细节主要靠 INFO 级别的业务日志。
10.3 活动流水 activity.log
$GITBUCKET_HOME/activity.log 是 JSON Lines 格式的审计流水,独立于运行日志,按行追加、不会自动轮转:
{"userName":"root","repositoryName":"demo","activityUserName":"root","activityType":"create_repository","message":"[user:root] created [repo:root/demo]","activityDate":"2026-10-27T12:29:43.408Z","activityId":"5b1e3109-7a97-4986-8bfb-88e5445f3575"}
{"userName":"root","repositoryName":"demo","activityUserName":"root","activityType":"create_branch","message":"[user:root] created branch [branch:root/demo#main] at [repo:root/demo]","activityDate":"2026-10-27T12:29:52.974Z","activityId":"f79ab798-ab6c-4ee5-946a-7b113ba56bcf"}
生产环境要给它配 logrotate(按天切分 + 保留 14 天),否则长期运行会持续膨胀。
十一、实测结论汇总
| 待验证的问题 | 实测结果 |
|---|---|
-Dgitbucket.home vs GITBUCKET_HOME | 系统属性优先,其次环境变量,默认 ~/.gitbucket |
| 端口的三层优先级 | 命令行 > 环境变量 > -Dgitbucket.port |
| base_url 的三层优先级 | -Dgitbucket.base_url > GITBUCKET_BASE_URL > gitbucket.conf |
| gitbucket.conf 值加引号 | 引号被当作内容,base_url 直接 500(URISyntaxException) |
| database.conf 值加引号 | 必须加引号(Typesafe Config 解析) |
| gitbucket.conf 的默认值是否回填后台 | 是,SMTP/LDAP/OIDC 各项均能在表单看到 |
| 后台设置能否用 curl 保存 | 不能,POST /admin/system 缺字段返回 400 |
| LDAP 开关打开后本地账号能否登录 | 不能,所有登录先走 LDAP |
| OIDC 开关是否影响登录页 | 是,出现 /signin/oidc 入口 |
| SMTP 配置是否真的发信 | 是,实测完整 SMTP 会话 |
| prefix 是否隔离路由 | 是,/gitbucket/signin 200、/signin 404 |
| PostgreSQL 切换 | 成功,43 张表,伴随 Driver2 WARN |
--save_sessions / --disable_cache / --disable_news_feed | 启动参数存在(JettyLauncher 解析),未在本轮逐一验证 |
十二、常见问题
Q1:配置写了却不生效?
A:先判断属于哪条链。换端口/前缀/监听地址 → 命令行 > 环境变量 > -D;改站点行为 → -D > 环境变量 > gitbucket.conf。用 ps -ef | grep gitbucket.war 看实际命令行,用 journalctl 看 Hikari 的 JDBC URL 确认数据目录,两头对齐再改。
Q2:改了 gitbucket.conf 一定要重启吗?
A:要。配置在启动时读取,运行中不会热加载。systemctl restart gitbucket 后再验证。
Q3:base_url 一填就 500?
A:检查引号。base_url = https://x 对,base_url = "https://x" 错。日志里会出现 java.net.URISyntaxException: Illegal character in scheme name at index 0。
Q4:数据目录跑偏到 ~/.gitbucket?
A:没设 -Dgitbucket.home 也没设 GITBUCKET_HOME,用的默认值。systemd 下检查 EnvironmentFile 是否被正确 EnvironmentFile= 引用、变量名是否拼错。
Q5:Driver2 那条 WARN 要不要处理?
A:不用,是 GitBucket 4.48.0 内部把 org.postgresql.Driver 写成了 org.postgresql.Driver2,HikariCP 会回落并成功连接。监控侧加白名单即可。
Q6:开了 LDAP 之后自己也登不进去了?
A:LDAP 不可达时所有登录失败。停服务临时把 ldap_authentication = false 改回、重启,用本地管理员修好 LDAP 配置再开。
Q7:邮件发了但收不到?
A:先确认 useSMTP = true,再用后台 Test mail 验证。测试接口不落库,能发出说明参数对;发不出就看 smtp.host/port/ssl/starttls 四件套是否与服务商要求一致。
Q8:反代后页面样式丢失、跳转到内网地址?
A:base_url 没配或配错,且 X-Forwarded-Proto 没透传。配 base_url = https://对外域名,nginx 加 proxy_set_header X-Forwarded-Proto https。
十三、参考链接
- 裸机安装:《Ubuntu 22.04 安装 GitBucket 4.48.0 指南》
- 介绍与选型:《GitBucket 4.48.0 介绍与选型指南》
- JettyLauncher 源码(启动参数与环境变量解析):https://github.com/gitbucket/gitbucket/blob/master/src/main/java/JettyLauncher.java
- 4.48.0 Release Notes:https://gitbucket.github.io/gitbucket-news/gitbucket/2026/09/20/gitbucket-4.48.0.html