Ubuntu 22.04 安装 GitBucket 4.48.0 指南
在 Ubuntu 22.04 上以裸机 JVM + systemd 方式从 0 到 1 安装 GitBucket 4.48.0:OpenJDK 17 准备、war 获取与校验、前台试跑、systemd 单元与环境变量、H2→PostgreSQL 切换实测(43 张表)、升级备份与卸载排障,含 java -version、启动日志、curl 与 systemctl status 真实回显。
目标:在一台全新的 Ubuntu 22.04 LTS 上完成 GitBucket 4.48.0 从环境准备、war 获取、裸机 JVM 进程运行到 systemd 托管的完整流程,并给出外置 PostgreSQL 切换、升级、卸载的实测记录。
Ubuntu 22.04 安装 GitBucket 4.48.0 指南
GitBucket 是一个 Scala 编写、以单个 gitbucket.war 分发的 Git 托管服务,内嵌 Jetty 与 JGit,启动后自带 Web UI、REST API、仓库与 issue 管理。本文按「基础环境 → 获取 war → 前台试跑 → systemd 托管 → 外置数据库 → 升级/卸载」的顺序,在一台 Ubuntu 22.04 上从 0 到 1 装一遍,所有命令与回显均为 2026-10-27 的实测结果。
一、环境信息
| 项 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.4 LTS(Jammy,x86_64) |
| GitBucket | 4.48.0(2026-09-20 发布) |
| Java | OpenJDK 17.0.20.1(GitBucket 4.42 起要求 Java 17,Java 8/11 无法启动) |
| 运行形态 | 单个 JVM 进程,java -jar gitbucket.war,内嵌 Jetty |
| 程序路径 | /opt/gitbucket/gitbucket.war(69 MB) |
| 数据目录 | /opt/gitbucket/data(由 -Dgitbucket.home 指定) |
| 监听 | 0.0.0.0:8080(HTTP) |
| 系统用户 | gitbucket(--system,不可登录) |
| JVM 堆 | -Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError |
| 初始管理员 | root / root,登录后改为 q1w2e3r4 |
💡 技术拓展:GitBucket 的数据库层是三选一的可插拔设计——内置 H2(默认,文件型,零运维)、PostgreSQL、MySQL。三者的差异集中在并发写入与备份方式上:
| 维度 | H2(默认) | PostgreSQL 15 | MySQL 8 |
|---|---|---|---|
| 存储形态 | 单文件 data.mv.db,随数据目录一起备份 | 独立服务,需 pg_dump/物理备份 | 独立服务,需 mysqldump/XtraBackup |
| 并发写入 | 单写者,团队 > 20 人易锁等待 | MVCC,适合中大型团队 | MVCC,适合中大型团队 |
| 升级风险 | 4.43+ 需手动做 H2 1.x → 2.x 迁移 | 无额外迁移 | 无额外迁移 |
| 运维成本 | 最低 | 中 | 中 |
本文默认走 H2,第六节给出切 PostgreSQL 的实测过程。GitBucket 本身不感知数据库类型,切换只改一个 database.conf 文件。
二、前置条件
- Java 17:必须 17 及以上,低于 17 启动直接抛
UnsupportedClassVersionError; - 端口:8080 空闲;
- 内存:≥ 1 GB 可用(war 解包 + 512 MB 堆 + JGit 工作区);
- 磁盘:≥ 5 GB(仓库数据 + H2 文件 + 插件);
- 可选:
git命令行,用于后续仓库操作验证。
uname -m # x86_64
. /etc/os-release && echo "$PRETTY_NAME" # Ubuntu 22.04.4 LTS
free -h | head -2
df -h /opt | tail -1
ss -ltn | grep 8080 # 无输出 = 端口空闲
实测回显:
x86_64
Ubuntu 22.04.4 LTS
total used free shared buff/cache available
Mem: 18Gi 9.9Gi 2.5Gi 241Mi 6.7Gi 8.6Gi
overlay 295G 89G 191G 32% /
三、安装 Java 17 与获取 gitbucket.war
3.1 安装 OpenJDK 17
sudo apt update
sudo apt install -y openjdk-17-jre-headless
java -version
实测回显:
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
只要 java -version 显示 17 即可;如果系统里同时装了 8/11,用 sudo update-alternatives --config java 切到 17,否则 systemd 拉起时会用错版本。
3.2 创建目录与系统用户
sudo useradd --system --home /opt/gitbucket --shell /usr/sbin/nologin gitbucket
sudo mkdir -p /opt/gitbucket/data
sudo chown -R gitbucket:gitbucket /opt/gitbucket
ls -ld /opt/gitbucket /opt/gitbucket/data
drwxr-xr-x 3 gitbucket gitbucket 4096 Oct 27 12:23 /opt/gitbucket
drwxr-xr-x 6 gitbucket gitbucket 4096 Oct 27 12:29 /opt/gitbucket/data
数据目录只放 data 一层,war 直接放在 /opt/gitbucket/gitbucket.war,与 systemd 单元的 WorkingDirectory=/opt/gitbucket 对齐。
3.3 下载 war 包
cd /opt/gitbucket
sudo -u gitbucket curl -L -o gitbucket.war \
https://github.com/gitbucket/gitbucket/releases/download/4.48.0/gitbucket.war
⚠️ 网络说明:本环境实测直连
github.com的 Release 下载 12 秒无任何响应(curl: (28) Connection timed out,HTTP 码 000),必须走代理:
# 实测可用:代理 192.168.1.62:7897
sudo -u gitbucket curl -x http://192.168.1.62:7897 -L -o gitbucket.war \
https://github.com/gitbucket/gitbucket/releases/download/4.48.0/gitbucket.war
下载完成后核对体积与文件类型:
ls -lh /opt/gitbucket/gitbucket.war
file /opt/gitbucket/gitbucket.war
-rw-r--r-- 1 gitbucket gitbucket 69M Oct 27 12:17 /opt/gitbucket/gitbucket.war
/opt/gitbucket/gitbucket.war: Zip archive data, at least v2.0 to extract
war 是标准 zip 归档,69 MB 属于正常范围(含内嵌 Jetty、H2 与 4 个内置插件)。若只有几 MB 或百来 KB,基本是下载到了 HTML 错误页,用 file 一看便知。
四、方案 A:前台/后台直接运行(快速验证)
适用场景:首次验证、调试参数。生产请用第五节 systemd 托管。
4.1 前台启动
sudo -u gitbucket /usr/bin/java \
-Dgitbucket.home=/opt/gitbucket/data \
-Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError \
-jar /opt/gitbucket/gitbucket.war \
--port=8080
首次启动会建库、解包内置插件、初始化 43 张表,全过程约 4 秒(实测 12:25:54 起进程、12:25:57 完成插件初始化)。日志节选:
12:23:43.601 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
12:23:43.978 [main] INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn0: url=jdbc:h2:/opt/gitbucket/data/data user=SA
12:23:43.981 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
12:23:44.013 [main] INFO g.core.servlet.InitializeListener - Check version
12:23:44.013 [main] INFO g.core.servlet.InitializeListener - Start schema update
12:23:46.641 [main] INFO g.core.servlet.InitializeListener - Extract bundled plugins...
12:23:46.667 [main] INFO g.core.servlet.InitializeListener - Extract to /opt/gitbucket/data/plugins/gitbucket-notifications-plugin-1.11.0.jar
12:23:46.668 [main] INFO g.core.servlet.InitializeListener - Extract to /opt/gitbucket/data/plugins/gitbucket-gist-plugin-4.26.0.jar
12:23:46.668 [main] INFO g.core.servlet.InitializeListener - Extract to /opt/gitbucket/data/plugins/gitbucket-emoji-plugin-4.6.0.jar
12:23:46.674 [main] INFO g.core.servlet.InitializeListener - Extract to /opt/gitbucket/data/plugins/gitbucket-pages-plugin-1.11.0.jar
12:23:47.643 [Thread-9] INFO g.core.plugin.PluginWatchThread - Start PluginWatchThread: /opt/gitbucket/data/plugins
12:23:47.649 [main] INFO o.scalatra.servlet.ScalatraListener - The cycle class name from the config: ScalatraBootstrap
12:23:47.656 [main] INFO o.scalatra.servlet.ScalatraListener - Initializing life cycle class: ScalatraBootstrap
日志里 HikariPool-1 - Added connection conn0: url=jdbc:h2:/opt/gitbucket/data/data 这一行同时说明两件事:数据目录被正确解析到 /opt/gitbucket/data(否则会落到 ~/.gitbucket),且默认 H2 生效。
4.2 启动后验证
curl -s -D- -o /dev/null http://localhost:8080/
HTTP/1.1 200 OK
Date: Tue, 27 Oct 2026 12:51:58 GMT
Set-Cookie: JSESSIONID=node01cdg3dgo0rc8r18q8txe7wneoi13.node0; Path=/; HttpOnly
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 8505
Set-Cookie: JSESSIONID + 200 就代表 Jetty 与 Scalatra 路由已就绪;此时抓首页能看到 <title>GitBucket</title>。
登录页表单实测只有三个字段(userName、password、隐藏的 hash),没有 CSRF token,可直接用 curl 验证账号:
curl -s -c /tmp/c.txt -o /dev/null -w "login=%{http_code} -> %{redirect_url}\n" \
-d "userName=root&password=root&hash=" http://localhost:8080/signin
login=302 -> http://localhost:8080/signin;jsessionid=node01oezn4s7upuj8a3fjppw7fsnm19.node0
302 且带 jsessionid 即登录成功,Cookie 已写入 /tmp/c.txt。
4.3 后台临时运行(不建 systemd)
sudo -u gitbucket nohup /usr/bin/java \
-Dgitbucket.home=/opt/gitbucket/data \
-Xms512m -Xmx512m \
-jar /opt/gitbucket/gitbucket.war --port=8080 \
> /opt/gitbucket/gitbucket.out 2>&1 &
disown
ps -ef | grep '[g]itbucket.war'
这种方式重启机器即失效、崩溃也不拉起,仅用于验证,长期运行务必走下一节。
五、方案 B:systemd 托管(生产推荐)
5.1 环境变量文件
JVM 参数放在 EnvironmentFile 里,升级 war 时不必改单元文件:
sudo tee /etc/default/gitbucket > /dev/null <<'EOF'
JAVA_OPTS="-Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError"
GITBUCKET_HOME=/opt/gitbucket/data
EOF
5.2 单元文件
sudo tee /etc/systemd/system/gitbucket.service > /dev/null <<'EOF'
[Unit]
Description=GitBucket 4.48.0
After=network.target postgresql.service
[Service]
Type=simple
User=gitbucket
Group=gitbucket
EnvironmentFile=/etc/default/gitbucket
WorkingDirectory=/opt/gitbucket
ExecStart=/bin/sh -c "exec /usr/bin/java $JAVA_OPTS -jar /opt/gitbucket/gitbucket.war --port=8080"
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
几点说明:
ExecStart用/bin/sh -c "exec ..."包一层,才能让$JAVA_OPTS展开;exec保证 java 取代 sh 成为主进程,systemctl stop才能把信号直接送到 JVM。After=network.target postgresql.service:不切外置库时可删掉postgresql.service。LimitNOFILE=65536:每个 git push/fetch 都占文件句柄,默认 1024 在大仓库并发下会报Too many open files。- 堆固定 512 MB,
-XX:+ExitOnOutOfMemoryError让 OOM 时进程退出而不是僵死,由 systemd 的Restart=on-failure拉起。
5.3 启动与状态验证
sudo systemctl daemon-reload
sudo systemctl enable --now gitbucket
systemctl is-active gitbucket
systemctl status gitbucket --no-pager -l
实测回显:
active
● gitbucket.service - GitBucket 4.48.0
Loaded: loaded (/etc/systemd/system/gitbucket.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2026-10-27 12:25:53 UTC; 25min ago
Main PID: 6745 (java)
Tasks: 42 (limit: 2932)
Memory: 423.8M
CPU: 16.040s
CGroup: /system.slice/gitbucket.service
└─6745 /usr/bin/java -Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError -jar /opt/gitbucket/gitbucket.war --port=8080
Main PID: 6745 (java) 说明主进程就是 JVM(不是被 sh 包着),Memory: 423.8M 与 512 MB 堆上限相符。
端口与 HTTP:
ss -ltn | grep 8080
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8080/
LISTEN 0 50 *:8080 *:*
HTTP 200
5.4 堆参数是否真的生效
systemctl status 只显示进程命令行,再补一条 jps -v 交叉确认 JVM 实际拿到了参数:
sudo -u gitbucket jps -v
6745 war -Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError
7116 Jps -Dapplication.home=/usr/lib/jvm/java-17-openjdk-amd64 -Xms8m -Djdk.module.main=jdk.jcmd
💡 技术拓展:
jps -v第一列显示的war是 jar 的 manifest 里没有Main-Class时 JVM 的兜底显示(GitBucket 用的是 Jetty 的 launcher 式入口),不代表进程异常。要确认是 GitBucket,看-jar /opt/gitbucket/gitbucket.war参数或ps -ef | grep gitbucket.war即可。
5.5 日志
journalctl -u gitbucket -n 20 --no-pager
journalctl -u gitbucket -f # 实时追踪
首次启动的日志会包含 Started GitBucket 4.48.0.、Hikari 建池、插件解包三段(见 4.1 节回显)。注意:日志开头的
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
是 GitBucket 自身依赖里 SLF4J 绑定缺失导致的告警,不影响业务日志(业务日志由 logback 输出到 journald),可以忽略。
5.6 日常运维命令
sudo systemctl stop gitbucket
sudo systemctl restart gitbucket
sudo systemctl disable gitbucket
journalctl -u gitbucket --since "10 min ago"
六、切换到外置 PostgreSQL(实测)
默认 H2 支撑小团队够用;仓库数上百、并发写入变多后建议换 PostgreSQL。切换只需在 $GITBUCKET_HOME 下放一个 HOCON 格式的 database.conf。
6.1 准备数据库
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;"
6.2 写 database.conf
sudo tee /opt/gitbucket/data/database.conf > /dev/null <<'EOF'
db {
url = "jdbc:postgresql://127.0.0.1:5432/gitbucket"
user = "gitbucket"
password = "gb_pg_2026"
maximumPoolSize = 10
}
EOF
sudo chown gitbucket:gitbucket /opt/gitbucket/data/database.conf
6.3 重启并验证
sudo systemctl restart gitbucket
journalctl -u gitbucket --since "2 min ago" --no-pager | grep -E "Hikari|postgres"
实测回显:
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
Added connection org.postgresql.jdbc.PgConnection 即已连上 PostgreSQL。建表结果可反查:
sudo -u postgres psql -d gitbucket -tAc "select count(*) from information_schema.tables where table_schema=(select current_schema())"
43
43 张表与 H2 初始化时一致,说明 schema 迁移完成。
⚠️ 实测真问题:日志里的
driverClassName=org.postgresql.Driver2 was not found是 GitBucket 4.48.0 在 HikariCP 里写死了org.postgresql.Driver2这个不存在的类名导致的告警。它只是 WARN——HikariCP 会退回直接实例化org.postgresql.Driver,连接照常建立,可忽略;但如果你的监控把 WARN 当故障,需要给它单独配忽略规则。⚠️ 另一个坑:
database.conf里的密码是明文,database.conf必须chown gitbucket:gitbucket且权限收到600,否则同机其他用户可读。
6.4 MySQL 8 的等价配置
db {
url = "jdbc:mysql://127.0.0.1:3306/gitbucket?characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true"
user = "gitbucket"
password = "q1w2e3r4"
maximumPoolSize = 10
}
MySQL 需要提前 CREATE DATABASE gitbucket CHARACTER SET utf8mb4,且 JDBC 串必须带 characterEncoding=UTF-8,否则中文仓库名/issue 会乱码。
6.5 从 H2 迁移已有数据
换库不是改配置就完事,历史数据要迁:
- 停服务
sudo systemctl stop gitbucket; - 备份整个数据目录
sudo cp -a /opt/gitbucket/data /opt/gitbucket/data.bak; - 用 H2 工具把数据导成 SQL:
java -cp /opt/gitbucket/gitbucket.war org.h2.tools.Script -url jdbc:h2:/opt/gitbucket/data/data -user sa -password sa -script /tmp/dump.sql; - 把
dump.sql里的 H2 方言(CREATE CACHED TABLE、IDENTITY等)改成 PostgreSQL/MySQL 方言后导入; - 起服务并核对仓库数量、issue 数量。
⚠️ H2 1.x → 2.x 的升级迁移(4.42 及更早升级到 4.43+ 仍用内置 H2 时必须做)不在本节范围,见第十节 Q3。
七、验收清单
安装完成后按下面五项逐条确认,全部通过即可交付:
systemctl is-active gitbucket # active
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/ # 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/api/v3 # 200
sudo -u gitbucket jps -v | grep gitbucket.war # 带 -Xms512m -Xmx512m
sudo ls /opt/gitbucket/data # data.mv.db repositories plugins
实测回显(逐条):
active
200
200
6745 war -Xms512m -Xmx512m -XX:+ExitOnOutOfMemoryError
activity.log data.mv.db database.conf gist plugins repositories tmp
data.mv.db 是 H2 数据文件(切 PostgreSQL 后该文件不再增长,可保留作回滚用),repositories 下是实际 git 仓库,plugins 下是自动解包的 4 个内置插件。
登录 Web UI 后第一件事:右上角 Settings → Account 把 root 的密码从默认 root 改成 q1w2e3r4,并新建一个日常使用的普通账号,避免长期用管理员账号做 git 操作。
八、升级
# 1. 停服务 + 备份数据目录(H2 场景必须停服后再拷,避免拷到半个事务)
sudo systemctl stop gitbucket
sudo cp -a /opt/gitbucket/data /opt/gitbucket/data.backup.$(date +%Y%m%d-%H%M%S)
# 2. 换 war
sudo -u gitbucket curl -x http://192.168.1.62:7897 -L -o /opt/gitbucket/gitbucket.war.new \
https://github.com/gitbucket/gitbucket/releases/download/4.48.0/gitbucket.war
sudo -u gitbucket mv /opt/gitbucket/gitbucket.war.new /opt/gitbucket/gitbucket.war
# 3. 起服务 + 验证
sudo systemctl start gitbucket
sleep 5
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8080/
journalctl -u gitbucket --since "1 min ago" --no-pager | grep -E "Check version|schema update"
4.48.0 升级注意点:4.47.0/4.48.0 带大表迁移,首次启动会在 Start schema update 处停留较久(实测 2.6 秒),期间不要 kill 进程;升级前必须备份数据目录,降级只能靠回滚备份。
九、卸载与清理
sudo systemctl stop gitbucket
sudo systemctl disable gitbucket
sudo rm -f /etc/systemd/system/gitbucket.service /etc/default/gitbucket
sudo systemctl daemon-reload
sudo rm -rf /opt/gitbucket
sudo userdel gitbucket
systemctl status gitbucket 2>&1 | head -2
Unit gitbucket.service could not be found.
若只是换机器迁移,不要 rm -rf,改为 tar -czf gitbucket-data.tar.gz -C /opt/gitbucket data 打包带走,新机器解压到同路径即可。
十、常见问题
Q1:启动后 curl 不是 200,而是 Connection refused?
A:先看 journalctl -u gitbucket -n 100。三类原因:(1)端口被占,改 --port=8081 并同步 ss -ltn 确认;(2)Java 版本低于 17,java -version 核对;(3)数据目录权限不对,sudo chown -R gitbucket:gitbucket /opt/gitbucket。另注意首次启动建库约 4 秒,脚本里 curl 前至少 sleep 5。
Q2:root 账号登录不了?
A:默认 root/root,实测 POST /signin 返回 302 即成功。若改过密码又忘了,可停服后用 H2 Shell 改:java -cp /opt/gitbucket/gitbucket.war org.h2.tools.Shell -url jdbc:h2:/opt/gitbucket/data/data -user sa -password sa,在 ACCOUNT 表里重置。4.47.0+ 有「最后一个管理员不可删除」约束,所以不能靠删账号绕过。
Q3:从 H2 1.x 升级到 4.43+ 后启动报 H2 错误?
A:4.43+ 内置 H2 2.x,旧库必须手动迁移:用 h2-1.4.199.jar 的 Script 工具导出 SQL,再用 h2-2.3.232.jar 的 RunScript 导入,参考 https://www.h2database.com/html/migration-to-v2.html。GitBucket 的自动 schema update 依赖数据库本身能起来,库起不来它也无能为力。
Q4:systemd 启动报 ExecStart=... $JAVA_OPTS ... 参数没生效?
A:systemd 不会展开 ExecStart 里的变量,除非显式走 shell。本文单元用 /bin/sh -c "exec ... $JAVA_OPTS" 正是为此;若写成 ExecStart=/usr/bin/java $JAVA_OPTS -jar ...,$JAVA_OPTS 会被当成一个名为 $JAVA_OPTS 的畸形参数传给 JVM,启动即失败。
Q5:怎么让 GitBucket 跑在 80/443?
A:80 端口给 java 进程加 capability:sudo systemctl edit gitbucket 加 AmbientCapabilities=CAP_NET_BIND_SERVICE;443 需 HTTPS,启动参数追加 --connectors=http,https --secure_port=443 --key_store_path=/opt/gitbucket/keystore.jks --key_store_password=... --key_manager_password=...,keystore 用 keytool -genkeypair 生成。
Q6:git clone 提示 remote: Repository not found 但网页能看到仓库?
A:GitBucket 的 HTTP 克隆路径是 http://<host>:8080/<owner>/<repo>.git,少了 .git 后缀或 owner 大小写不对都会 404;私有仓库还需要用 用户名:密码 或 Personal Access Token 做 Basic Auth。
十一、参考链接
- GitBucket 介绍与选型:《GitBucket 4.48.0 介绍与选型指南》
- JettyLauncher 源码(
--启动参数与环境变量解析的权威实现):https://github.com/gitbucket/gitbucket/blob/master/src/main/java/JettyLauncher.java - GitBucket README 安装章节:https://github.com/gitbucket/gitbucket#installation
- 4.48.0 Release Notes:https://gitbucket.github.io/gitbucket-news/gitbucket/2026/09/20/gitbucket-4.48.0.html
- H2 1.x → 2.x 迁移指南:https://www.h2database.com/html/migration-to-v2.html