Ubuntu 22.04 安装 Fossil SCM 2.28 指南
在 Ubuntu 22.04 上以官方二进制、apt、源码三条路线安装 Fossil 2.28,含 systemd 托管、Nginx 反代 HTTPS、SCGI、备份与排障实录。
Ubuntu 22.04 安装 Fossil SCM 2.28 指南
定位:本文在 Ubuntu 22.04(jammy)上完成 Fossil 2.28 的三条安装路线(官方二进制、apt、源码编译),并用 systemd 托管
fossil server,再通过 Nginx 反代提供 HTTPS,覆盖 SCGI 方案、用户与权限、fossil backup备份与 6 类真实排障。所有命令与回显均来自 2026-10-27 的实测环境(Ubuntu 22.04.5 LTS,内核 5.15,systemd 249,Nginx 1.18.0)。
1. 版本结论与准备
- 截至 2026-10-27,Fossil 最新正式版为 2.28(2026-03-11,构建号
52445a27f1)。 - Ubuntu 22.04 官方源自带的
fossil包为 1:2.18-1ubuntu0.1,二进制内部版本2.18 [c47fa2469e] 2022-02-23,落后正式版 10 个发布周期。 - 因此生产环境建议用官方二进制,需要定制编译时走源码路线;apt 路线仅用于"先跑起来"或离线兜底。
实测三条路线的版本对照:
/usr/local/bin/fossil -> 2.28 [52445a27f1] 2026-03-11 11:31:46 UTC # 官方二进制
/usr/bin/fossil -> 2.18 [c47fa2469e] 2022-02-23 13:54:02 UTC # apt 包
/opt/fossil-src/fossil-src/fossil -> 2.28 [52445a27f1] 2026-03-11 ... # 源码编译
注意源码编译出的构建哈希与官方二进制完全一致,说明 2.28 标签可复现;这也意味着源码路线不是"另一套代码",只是换编译参数。
基础准备(root 执行):
apt-get update
apt-get install -y curl ca-certificates nginx sqlite3
useradd --system --home-dir /var/lib/fossil --create-home --shell /usr/sbin/nologin fossil
mkdir -p /var/lib/fossil/repos /var/lib/fossil/backups
chown -R fossil:fossil /var/lib/fossil
2. 路线一:官方二进制(推荐)
官方发布包是单个压缩文件,解包即得可执行文件:
mkdir -p /opt/fossil && cd /opt/fossil
curl -sSL -O https://fossil-scm.org/home/uv/fossil-linux-x64-2.28.tar.gz
ls -lh fossil-linux-x64-2.28.tar.gz
tar xzf fossil-linux-x64-2.28.tar.gz
install -m 0755 fossil /usr/local/bin/fossil
which -a fossil
fossil version
实测回显(节选):
-rw-r--r-- 1 root root 4.0M Oct 27 12:18 fossil-linux-x64-2.28.tar.gz
-rwxrwxr-x 1 1001 1001 10326376 Mar 23 2026 fossil
/usr/local/bin/fossil
This is fossil version 2.28 [52445a27f1] 2026-03-11 11:31:46 UTC
要点:
- 发布包 4,110,148 字节(约 3.9 MiB),解包后的可执行文件 10,326,376 字节(约 9.8 MiB),无外部运行时依赖。
/usr/local/bin在 PATH 中优先于/usr/bin,因此后续即使用 apt 装了 2.18,fossil命令仍是 2.28。- 升级动作:下载新版本、
install -m 0755覆盖、systemctl restart fossil,仓库文件不需要迁移。
3. 路线二:apt(快,但版本旧)
apt-get install -y fossil
/usr/bin/fossil version
apt-cache policy fossil
实测:
Setting up fossil (1:2.18-1ubuntu0.1) ...
This is fossil version 2.18 [c47fa2469e] 2022-02-23 13:54:02 UTC
fossil:
Installed: 1:2.18-1ubuntu0.1
Candidate: 1:2.18-1ubuntu0.1
Version table:
1:2.18-1ubuntu0.1 500
500 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages
结论:apt 包能满足"建仓库、跑 Web、基础命令",但 2.18 缺少 2.19–2.28 间的修复与新特性(例如新版 JSON/搜索/时间线改进),不建议作为生产主版本。若已装 apt 包,不冲突:/usr/local/bin/fossil 会覆盖命令解析,必要时用绝对路径区分。
4. 路线三:源码编译(可控、可复现)
源码 tarball 从官方版本标签取:
mkdir -p /opt/fossil-src && cd /opt/fossil-src
curl -sSL -o fossil-src-2.28.tar.gz \
https://fossil-scm.org/home/tarball/version-2.28/fossil-src.tar.gz
tar xzf fossil-src-2.28.tar.gz
cd fossil-src
./configure --prefix=/opt/fossil-src-2.28
make -j"$(nproc)"
./fossil version
实测关键回显:
CFG_EXIT=0
Checking for system openssl...ok
HTTPS support enabled
Created Makefile from Makefile.in
Created autoconfig.h
MAKE_EXIT=0
This is fossil version 2.28 [52445a27f1] 2026-03-11 11:31:46 UTC
构建依赖:build-essential、tcl-dev(生成部分内嵌资源)、libssl-dev、zlib1g-dev。configure 检测到系统 OpenSSL 后会启用 HTTPS 支持,输出 HTTPS support enabled。
排障实录(源码路线最容易踩的坑):
bash: ./configure: No such file or directory
原因:官方 fossil-src.tar.gz 解包后多一层 fossil-src/ 目录,而很多人习惯在解包目录直接执行 ./configure。实际解包结构:
$ ls
fossil-src
$ cd fossil-src && ls | head
确认 configure 位于 fossil-src/fossil-src/configure 后再执行即可。另外,从国内直连官方源下载 7.3 MB 的 tarball 在 240 秒时只到 6.0 MB(约 25 KB/s),加代理后 3 秒完成;大包下载建议配代理或换镜像,避免误判为源码不可用。
5. 初始化仓库与管理员
printf "q1w2e3r4\nq1w2e3r4\n" | \
runuser -u fossil -- fossil init -A admin \
--project-name "Fossil Demo" \
--project-desc "Fossil 2.28 deployment test" \
/var/lib/fossil/repos/demo.fossil
实测输出(注意最后一行):
project-name: Fossil Demo
project-description: Fossil 2.28 deployment test
project-id: c2cb9fde916f3925b2584cdef6ed9265a810b9d4
server-id: c69808d29e6368e3d87e805d1df3b455388a790a
admin-user: admin (initial remote-access password is "Uwh6nPFiGL")
INIT_EXIT=0
真问题:通过管道喂两次密码并不会被 fossil init 采用;非交互执行时它会生成一个随机初始口令并在输出里打印一次(这里为 Uwh6nPFiGL)。生产脚本必须抓取该行,或立刻用下面的命令重置:
runuser -u fossil -- fossil user password admin q1w2e3r4 \
-R /var/lib/fossil/repos/demo.fossil
runuser -u fossil -- fossil user password reader readerpass \
-R /var/lib/fossil/repos/demo.fossil
runuser -u fossil -- fossil user list -R /var/lib/fossil/repos/demo.fossil
用户列表实测:
admin
anonymous Anon
developer Dev
nobody Nobody
reader Reader
init 会自动创建 anonymous、developer、nobody、reader 四个内置账号;再执行 fossil user new reader ... 会报 user reader already exists。新增普通用户请换名字,例如:
runuser -u fossil -- fossil user new alice alice@example.com 'S3cret!2026' \
-R /var/lib/fossil/repos/demo.fossil
runuser -u fossil -- fossil user capabilities alice \
-R /var/lib/fossil/repos/demo.fossil
仓库文件与目录权限实测:
drwxr-x--- 4 fossil fossil 4096 /var/lib/fossil
drwxr-xr-x 2 fossil fossil 4096 /var/lib/fossil/repos
-rw-r--r-- 1 fossil fossil 217088 /var/lib/fossil/repos/demo.fossil
建议把 /var/lib/fossil 收紧到 750,仓库文件 640,服务进程只以 fossil 用户运行;不要用 root 直接跑 fossil server。
6. systemd 托管 fossil server
/etc/systemd/system/fossil.service:
[Unit]
Description=Fossil SCM server for demo.fossil
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=fossil
Group=fossil
WorkingDirectory=/var/lib/fossil
ExecStart=/usr/local/bin/fossil server /var/lib/fossil/repos/demo.fossil \
--port 8080 --localhost --repolist \
--baseurl https://fossil.example.com
Restart=on-failure
RestartSec=3
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ReadWritePaths=/var/lib/fossil
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now fossil
systemctl status fossil --no-pager -l
实测状态:
● fossil.service - Fossil SCM server for demo.fossil
Loaded: loaded (/etc/systemd/system/fossil.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2026-10-27 12:25:41 UTC; 2s ago
Main PID: 5228 (fossil)
Memory: 1.1M
Oct 27 12:25:41 fossil-2.28-install fossil[5228]: Listening for HTTP requests on TCP port localhost:8080, IPv4 and IPv6
参数说明:
--localhost:只监听127.0.0.1/::1,强制流量经 Nginx,避免 8080 直接暴露公网。--repolist:允许在 URL 中切换同一目录下的其他仓库(多仓场景)。--baseurl https://fossil.example.com:反向代理必配,否则 Fossil 生成的 302/表单地址会带内部端口(详见第 10 节)。- 需要 Fossil 自己终结 TLS 时用
--cert /etc/ssl/fossil.pem(PEM 内需同时含证书链与私钥),但不推荐与 Nginx 混用。
验证本机:
curl -sI http://127.0.0.1:8080/
HTTP/1.0 302 Moved Temporarily
Location: https://fossil.example.com/index
7. Nginx 反代 HTTP 与 HTTPS
7.1 HTTP(80)
/etc/nginx/sites-available/fossil:
server {
listen 80;
server_name _;
client_max_body_size 512m;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_request_buffering off;
}
}
rm -f /etc/nginx/sites-enabled/default
ln -s /etc/nginx/sites-available/fossil /etc/nginx/sites-enabled/fossil
nginx -t
systemctl restart nginx
curl -s http://127.0.0.1/home | grep -o "<title>[^<]*</title>"
实测:
nginx: configuration file /etc/nginx/nginx.conf test is successful
<title>Fossil Demo: Fossil Demo</title>
7.2 HTTPS(443)
自签证书仅用于验证链路,生产请换 Let's Encrypt 或企业 CA:
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-subj "/CN=fossil.example.com" \
-keyout /etc/ssl/private/fossil.key \
-out /etc/ssl/certs/fossil.crt
/etc/nginx/sites-available/fossil-ssl:
server {
listen 443 ssl;
server_name fossil.example.com;
ssl_certificate /etc/ssl/certs/fossil.crt;
ssl_certificate_key /etc/ssl/private/fossil.key;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 512m;
proxy_read_timeout 300s;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_request_buffering off;
}
}
ln -s /etc/nginx/sites-available/fossil-ssl /etc/nginx/sites-enabled/fossil-ssl
nginx -t && systemctl reload nginx
curl -sk -H "Host: fossil.example.com" https://127.0.0.1/home | grep -o "<title>[^<]*</title>"
实测:
<title>Fossil Demo: Fossil Demo</title>
关于 WebSocket:Fossil 的 Web UI 与 sync 均不使用 WebSocket,反代不需要配置 Upgrade/Connection 头。真正需要放宽的是请求体大小与超时:克隆/同步/附件上传都是单个大 POST,默认 client_max_body_size 1m 会在稍大的仓库上直接 413。实测配置为 512m 并关闭请求缓冲(proxy_request_buffering off),克隆冒烟通过:
runuser -u fossil -- fossil clone http://127.0.0.1:8080/demo \
/var/lib/fossil/backups/clone-smoke.fossil
runuser -u fossil -- fossil info -R /var/lib/fossil/backups/clone-smoke.fossil
project-name: Fossil Demo
project-id: c2cb9fde916f3925b2584cdef6ed9265a810b9d4
check-ins: 1
7.3 https-login 实测边界
设置 https-login on 后,经 Nginx 的 HTTP 入口访问 /login 仍返回 200,不会自动 302 到 HTTPS(Fossil 对本地/可信连接有豁免逻辑):
fossil settings https-login on -R /var/lib/fossil/repos/demo.fossil
curl -sI -H "Host: fossil.example.com" http://127.0.0.1/login
HTTP/1.1 200 OK
结论:不要只依赖该开关做强制跳转。生产环境应在 Nginx 的 80 server 块里直接 return 301 https://$host$request_uri;,把 HTTPS 作为唯一入口,https-login 只作为纵深防御。
8. SCGI 方案(可选)
Fossil 也能以 SCGI 模式运行,由 Nginx 通过 Unix/TCP 套接字转发。与 HTTP 模式相比少一层 HTTP 解析,但排查链路更长。实测步骤:
systemd drop-in /etc/systemd/system/fossil.service.d/scgi.conf:
[Service]
ExecStart=
ExecStart=/usr/local/bin/fossil server /var/lib/fossil/repos/demo.fossil \
--scgi --port 9000 --localhost --baseurl https://fossil.example.com
mkdir -p /etc/systemd/system/fossil.service.d
# 写入上面的 scgi.conf
systemctl daemon-reload && systemctl restart fossil
ss -ltnp | grep 9000
实测监听:
LISTEN 0 10 127.0.0.1:9000 0.0.0.0:* users:(("fossil",pid=5451,fd=3))
LISTEN 0 10 [::1]:9000 [::]:* users:(("fossil",pid=5451,fd=4))
Nginx server 块(8443 仅用于验证):
server {
listen 8443 ssl;
server_name fossil.example.com;
ssl_certificate /etc/ssl/certs/fossil.crt;
ssl_certificate_key /etc/ssl/private/fossil.key;
client_max_body_size 512m;
location / {
include scgi_params;
scgi_pass 127.0.0.1:9000;
scgi_param HTTPS on;
scgi_param HTTP_HOST $host;
scgi_param SCRIPT_NAME "";
scgi_param REMOTE_ADDR $remote_addr;
proxy_read_timeout 300s;
}
}
实测:
<title>Fossil Demo: Fossil Demo</title>
== scgi login ==
200 8260
排障要点:SCGI 模式下 HTTP_HOST、HTTPS、REMOTE_ADDR 必须显式传,否则登录跳转与绝对 URL 会错;调通后记得删除 drop-in 并 daemon-reload,否则改回 HTTP 模式时旧参数仍生效。
9. 备份、恢复与日常检查
Fossil 仓库是单个 SQLite 文件,fossil backup 走 SQLite 在线备份 API,可在服务运行中执行,无需停机:
runuser -u fossil -- fossil backup \
/var/lib/fossil/backups/demo-20261027.fossil \
-R /var/lib/fossil/repos/demo.fossil
runuser -u fossil -- fossil info -R /var/lib/fossil/backups/demo-20261027.fossil
实测:
BACKUP_EXIT=0
-rw-r--r-- 1 fossil fossil 212K Oct 27 12:27 demo-20261027.fossil
project-name: Fossil Demo
project-code: c2cb9fde916f3925b2584cdef6ed9265a810b9d4
check-ins: 1
建议的 crontab(fossil 用户):
15 2 * * * /usr/local/bin/fossil backup /var/lib/fossil/backups/demo-$(date +\%Y\%m\%d).fossil -R /var/lib/fossil/repos/demo.fossil
30 2 * * * find /var/lib/fossil/backups -name 'demo-*.fossil' -mtime +30 -delete
恢复:把备份文件复制回仓库路径、chown fossil:fossil、systemctl restart fossil 即可;必要时先 fossil rebuild 重建索引(见 CLI 篇)。
日常检查命令:
systemctl status fossil --no-pager
curl -sI https://fossil.example.com/ | head -1
fossil info -R /var/lib/fossil/repos/demo.fossil | head -5
10. 排障实录
| 现象 | 根因 | 处置 |
|---|---|---|
./configure: No such file or directory | 源码包解包多一层 fossil-src/ | cd fossil-src/fossil-src 再执行 |
fossil 版本仍是 2.18 | apt 包在 /usr/bin 先被解析 | 用 /usr/local/bin/fossil 或调整 PATH |
| 初始化后不知道管理员密码 | 非交互 init 打印随机口令,管道输入无效 | 抓输出中的 initial remote-access password,或 fossil user password admin 重置 |
访问站点 302 跳到 http://内网IP:8080/index | 反代未告知外部地址 | 加 --baseurl https://fossil.example.com |
| 直接访问发布端口无响应 | 服务绑定 127.0.0.1 | 只经 Nginx 访问,8080 不对公网开放 |
| 克隆/推送失败,Nginx 返回 413 | 默认请求体 1 MB 限制 | client_max_body_size 512m + proxy_request_buffering off |
SQLITE_CANTOPEN(14): ... Permission denied | 仓库文件属主/权限不对 | chown fossil:fossil,目录 750、文件 640 |
| SCGI 页面 502 | 未传 HTTP_HOST/HTTPS,或 9000 未监听 | 补 scgi_param,ss -ltnp 核对端口 |
权限故障的真实回显:
SQLITE_CANTOPEN(14): cannot open file at line 46350 of [557aeb4386]
SQLITE_CANTOPEN(14): os_unix.c:46350: (13) open(/tmp/noaccess.fossil) - Permission denied
Database error: [/tmp/noaccess.fossil]: unable to open database file
这类错误在 systemd 下通常表现为服务反复重启,日志里只有一行 SQLITE_CANTOPEN;先核对 User=fossil 与仓库属主,再检查 ProtectSystem=full 是否挡住了自定义数据目录(本方案已用 ReadWritePaths 放行)。
11. 站内延伸阅读
- 认知与选型:本专栏《Fossil SCM 2.28 介绍与选型指南》。
- 参数调优:本专栏《Fossil SCM 2.28 配置参数详解》。
- 命令实战:本专栏《Fossil SCM 2.28 常用 CLI 命令详解》。
12. 实测环境与依据
- 实测日期:2026-10-27;系统 Ubuntu 22.04.5 LTS(jammy),systemd 249,Nginx 1.18.0,OpenSSL 3.0。
- 官方版本依据:https://fossil-scm.org/home/(最新正式版 2.28,2026-03-11)。
- 官方二进制:https://fossil-scm.org/home/uv/fossil-linux-x64-2.28.tar.gz(4,110,148 字节)。
- 官方源码包:https://fossil-scm.org/home/tarball/version-2.28/fossil-src.tar.gz。
- 官方
fossil server选项(--baseurl、--localhost、--scgi、--cert):本机fossil server --help实测输出。