Ubuntu 22.04 安装 Cgit 1.3.1 指南

Ubuntu 22.04 上 Cgit 双方案安装实测:apt 仓库版 1.2.3 快速体验与官方源码编译 1.3.1(内嵌 Git 2.54.0)生产方案,nginx+fcgiwrap CGI 链路、systemd 托管、验证回显与 fcgiwrap socket 残留排障实录。

CgitCgitGit 服务Ubuntu 22.04nginx2026/10/27

Ubuntu 22.04 安装 Cgit 1.3.1 指南

目标:在 Ubuntu 22.04 服务器上从零完成 Cgit 的安装与 nginx + fcgiwrap CGI 链路打通,覆盖 apt 仓库版(1.2.3,快速体验)与官方源码编译版(1.3.1,生产推荐)两种方案,含 systemd 托管、验证回显与真实排障实录。全部命令与输出均在 Ubuntu 22.04 实机实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04 LTS(Jammy),x86_64,内核 5.15+
  • 软件版本:Cgit 1.3.1(源码方案,内置 Git 2.54.0)/ Cgit 1.2.3+git2.25.1-1(apt 仓库方案)
  • Web 链路:nginx 1.18.0 (Ubuntu) + fcgiwrap(FastCGI 承载 CGI)
  • 关键路径:/var/www/htdocs/cgit/cgit.cgi(源码版程序)、/usr/lib/cgit/cgit.cgi(apt 版程序)、/etc/cgitrc(主配置)、/var/lib/git(裸仓库根)、/var/cache/cgit(页面缓存)
  • 监听:nginx 80 端口,浏览器访问 http://<服务器IP>/cgit/
  • 进程托管:systemd(nginx.service、fcgiwrap.socket/fcgiwrap.service)

二、前置条件

  • 一台 Ubuntu 22.04 服务器,root 或 sudo 权限。
  • 可访问外网(下载官方源码包;apt 方案需可用 Ubuntu universe 源)。
  • 磁盘预留约 500MB(源码树 + 编译中间产物约 132MB,装完可清)。
  • 本文所有命令以 root 身份执行(sudo -i 后操作)。

先更新软件包索引:

apt update

输出节选(实测首尾):

Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
Reading package lists... Done

三、版本选型说明

Cgit 在 Ubuntu 22.04 上有两条安装路线,版本差一个大版本号,先看清再选:

维度方案 A:apt 仓库版方案 B:源码编译版
实际版本1.2.3+git2.25.1-1(jammy/universe)1.3.1(上游当前最新稳定版)
内置 Git2.25.1(页面页脚实测)2.54.0(页面页脚实测)
发布日期1.2.3 上游发布于 2022 年1.3.1 上游发布于 2026-05-04
安装耗时约 1 分钟编译约 5–10 分钟(内嵌 Git 全量编译)
程序路径/usr/lib/cgit/cgit.cgi/var/www/htdocs/cgit/cgit.cgi
配置路径/etc/cgitrc(两版共用)/etc/cgitrc(两版共用)
适用快速体验、对内网小仓库够用生产部署、要 1.3 新特性(如暗色模式 CSS 支持基础)

apt 仓库版本实测(2026-10-27 实查):

apt-cache policy cgit
cgit:
  Installed: 1.2.3+git2.25.1-1
  Candidate: 1.2.3+git2.25.1-1
  Version table:
 *** 1.2.3+git2.25.1-1 500
        500 http://archive.ubuntu.com/ubuntu jammy/universe amd64 Packages
        100 /var/lib/dpkg/status
apt-cache show cgit | grep -E '^(Package|Version|Depends)'
Package: cgit
Version: 1.2.3+git2.25.1-1
Depends: libc6 (>= 2.28), liblua5.1-0, zlib1g (>= 1:1.2.0)

⚠️ 注意:jammy 仓库的 cgit 停留在 1.2.3(上游 4 年前的版本),与上游 1.3.1 差两个大版本。1.3 系列修复了错误页 Expires 头、默认分支猜测等问题并更新内嵌 Git 至 2.54。生产环境建议直接上方案 B 源码编译 1.3.1;只想 5 分钟看到界面可用方案 A。两方案的 nginx/fcgiwrap 链路配置完全一致(见六、),仅 SCRIPT_FILENAME 指向的 cgit.cgi 路径不同。

四、方案 A:apt 仓库在线安装(Cgit 1.2.3,快速体验)

本方案适合「先跑起来看看」:一条 apt 命令装好 Cgit 本体,再配 nginx + fcgiwrap 链路即可访问。

4.1 安装 cgit 与链路组件

apt install -y cgit nginx fcgiwrap git

安装完成后确认包内文件布局:

dpkg -L cgit | grep -E 'cgi|css|cgitrc|htdocs' | head -8
/etc/apache2/conf-available/cgit.conf
/etc/cgitrc
/usr/lib/cgit
/usr/lib/cgit/cgit.cgi
/usr/lib/cgit/filters
/usr/lib/cgit/filters/about-formatting.sh
/usr/lib/cgit/filters/commit-links.sh
/usr/lib/cgit/filters/email-gravatar.lua

要点解读:apt 版主程序是 /usr/lib/cgit/cgit.cgi;自带一份 /etc/cgitrc 主配置;附赠 Apache 配置片段 /etc/apache2/conf-available/cgit.conf(本文用 nginx,不用它);过滤器脚本在 /usr/lib/cgit/filters/。

apt 版静态资源(cgit.css/cgit.png 等)默认在 /usr/share/cgit/。为与方案 B 的路径布局统一(/var/www/htdocs/cgit/),建议建一个软链,后续换方案无需改 nginx:

mkdir -p /var/www/htdocs/cgit
ln -sf /usr/share/cgit/cgit.css /var/www/htdocs/cgit/cgit.css
ln -sf /usr/share/cgit/cgit.png /var/www/htdocs/cgit/cgit.png
ln -sf /usr/share/cgit/favicon.ico /var/www/htdocs/cgit/favicon.ico

4.2 验证 apt 版页面(链路配好后)

nginx + fcgiwrap 配置见「六、」,其中 SCRIPT_FILENAME 用 apt 版路径 /usr/lib/cgit/cgit.cgi。配好后实测页面页脚:

curl -s http://127.0.0.1/cgit/ | grep footer
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2026-10-27 10:17:51 +0000</div>

页脚显示 cgit v1.2.3 (git 2.25.1) 即 apt 版链路打通。之后若要升级到 1.3.1,走方案 B 编译安装,把 nginx 的 SCRIPT_FILENAME 改指 /var/www/htdocs/cgit/cgit.cgi 即可,配置其余部分原样复用。

五、方案 B:官方源码编译安装 Cgit 1.3.1(生产推荐)

本方案从上游官方站点下载 cgit-1.3.1 与内嵌 git-2.54.0 源码,编译出最新版 cgit.cgi。Cgit 的构建特点是必须内嵌一份 Git 源码(编译进二进制,直接以库方式调用,这是它快的原因之一),因此是两个源码包。

5.1 安装编译依赖

apt install -y build-essential libssl-dev zlib1g-dev pkg-config xz-utils ca-certificates

💡 技术拓展:Cgit 可选内置 Lua 解释器用于过滤器脚本(email-gravatar.lua 等)。编译时 make NO_LUA=1 裁掉 Lua(本文实测采用,输出可见 * linking without specified Lua support);若要 Lua 支持,需再装 liblua5.1-dev 并去掉 NO_LUA=1。发行版 apt 包默认带 Lua(Depends 里的 liblua5.1-0 即证)。一般浏览场景不需要 Lua 过滤器,裁掉可减少依赖面。

5.2 下载官方源码包(含 SHA256 校验)

Cgit 官方发布在作者自营 Git 站,Git 源码包在 kernel.org:

cd /root
wget https://git.zx2c4.com/cgit/snapshot/cgit-1.3.1.tar.xz
wget https://www.kernel.org/pub/software/scm/git/git-2.54.0.tar.xz

⚠️ 网络说明:git.zx2c4.com 为境外站点,国内服务器下载慢或失败时可走代理(export https_proxy=http://192.168.1.62:7897 后重跑 wget),或从已验证的离线包分发。本文两个包均实测下载成功并完成校验。

下载后必须校验 SHA256(本文实测值,供比对):

sha256sum cgit-1.3.1.tar.xz git-2.54.0.tar.xz
c40fd71e120783d5e57d822208f3e17333cde2cd4baf3e7c8c75630b68afe12a  cgit-1.3.1.tar.xz
f689162364c10de79ef89aa8dbf48731eb057e34edbbd20aca510ce0154681a3  git-2.54.0.tar.xz

5.3 解压并把 Git 源码嵌入 cgit 源码树

Cgit 的 Makefile 约定:Git 源码放在 cgit-1.3.1/git/ 子目录(源码包自带的 git 占位目录需先移除):

tar -xJf cgit-1.3.1.tar.xz
tar -xJf git-2.54.0.tar.xz
rm -rf cgit-1.3.1/git
mv git-2.54.0 cgit-1.3.1/git

验证嵌入成功(Git 版本声明应为 v2.54.0):

grep DEF_VER /root/cgit-1.3.1/git/GIT-VERSION-GEN | head -1
DEF_VER=v2.54.0

5.4 编译

cd /root/cgit-1.3.1
make -j"$(nproc)" NO_LUA=1

编译过程输出节选(实测首尾):

    SUBDIR git
CGIT_VERSION = v1.3.1
    * new CGit build flags
    CC ../cgit.o
    CC ../cache.o
    CC ../cmd.o
    ...(中间为 25 个 .o 编译行,节选)
    CC ../ui-summary.o
    CC ../ui-tag.o
    CC ../ui-tree.o
    * linking without specified Lua support
    LINK ../cgit

LINK ../cgit 出现即编译成功。产物是源码树根部的 cgit 可执行文件(即 cgit.cgi):

ls -la /root/cgit-1.3.1/cgit
-rwxr-xr-x 1 root root 12569592 Oct 27 09:44 /root/cgit-1.3.1/cgit

产物约 12MB(含 debug info 未 strip),内嵌完整 Git 2.54.0 库。

5.5 安装到系统路径

cd /root/cgit-1.3.1
make install NO_LUA=1

实测安装输出(照抄,注意安装路径):

    SUBDIR git
install -m 0755 -d /var/www/htdocs/cgit
install -m 0755 cgit /var/www/htdocs/cgit/cgit.cgi
install -m 0755 -d /var/www/htdocs/cgit
install -m 0644 cgit.css /var/www/htdocs/cgit/cgit.css
install -m 0644 cgit.js /var/www/htdocs/cgit/cgit.js
install -m 0644 cgit.png /var/www/htdocs/cgit/cgit.png
install -m 0644 favicon.ico /var/www/htdocs/cgit/favicon.ico
install -m 0644 robots.txt /var/www/htdocs/cgit/robots.txt
install -m 0755 -d /usr/local/lib/cgit/filters
cp -r filters/* /usr/local/lib/cgit/filters

安装布局解读:

  • 主程序:/var/www/htdocs/cgit/cgit.cgi(ELF 二进制)
  • 静态资源:同目录的 cgit.css / cgit.js / cgit.png / favicon.ico / robots.txt
  • 过滤器:/usr/local/lib/cgit/filters/(about-formatting.sh、email-gravatar.lua 等)
file /var/www/htdocs/cgit/cgit.cgi
/var/www/htdocs/cgit/cgit.cgi: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=32d97df20cfcf8fc6b0642207e0747e842d42f25, for GNU/Linux 3.2.0, with debug_info, not stripped

5.6 建仓库根目录与演示仓库

mkdir -p /var/lib/git /var/cache/cgit
chown -R www-data:www-data /var/cache/cgit
cd /var/lib/git
git init --bare demo-hello.git
Initialized empty Git repository in /var/lib/git/demo-hello.git/

给裸仓库写一条描述与 owner(Cgit 列表页直接读取展示):

echo "cgit 演示仓库" > /var/lib/git/demo-hello.git/description
git -C /var/lib/git/demo-hello.git config gitweb.owner www-data
chown -R www-data:www-data /var/lib/git

⚠️ 注意:缓存目录 /var/cache/cgit 必须归属运行 CGI 的账号(nginx 的 www-data),否则 Cgit 写缓存失败、每请求都全量重渲染,失去 hyperfast 意义。仓库目录同样建议归 www-data(只读浏览场景可读即可,归 www-data 最省事)。

5.7 验证源码版页面

按「六、」配好 nginx(SCRIPT_FILENAME 指 /var/www/htdocs/cgit/cgit.cgi)后:

curl -s http://127.0.0.1/cgit/ | grep footer
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.3.1</a> (<a href='https://git-scm.com/'>git 2.54.0</a>) at 2026-10-27 10:18:21 +0000</div>

页脚 cgit v1.3.1 (git 2.54.0) 即 1.3.1 链路生效。与方案 A 的 v1.2.3 (git 2.25.1) 对比即知两版差异一眼可辨。

六、nginx + fcgiwrap CGI 链路配置(两方案共用)

Cgit 是标准 CGI 程序,nginx 不支持原生 CGI,须由 fcgiwrap 桥接:nginx 把请求按 FastCGI 协议发给 fcgiwrap 的 Unix socket,fcgiwrap fork 执行 cgit.cgi。本节配置对 apt 版/源码版通用,仅 SCRIPT_FILENAME 一行路径不同。

6.1 fcgiwrap 服务(systemd socket 激活)

Ubuntu 的 fcgiwrap 包自带 systemd socket 单元,默认监听 /run/fcgiwrap.socket:

systemctl enable fcgiwrap.socket
systemctl start fcgiwrap.socket
systemctl status fcgiwrap --no-pager
● fcgiwrap.service - Simple CGI Server
     Loaded: loaded (/lib/systemd/system/fcgiwrap.service; indirect; vendor preset: enabled)
     Active: active (running) since Tue 2026-10-27 09:05:49 UTC; 1h 9min ago
TriggeredBy: ● fcgiwrap.socket
   Main PID: 3598 (fcgiwrap)
      Tasks: 1 (limit: 2932)
     Memory: 1016.0K

确认 socket 文件已生成:

ls -la /run/fcgiwrap.socket
srw-rw-rw- 1 root root 0 Oct 27 09:05 /run/fcgiwrap.socket

💡 说明:fcgiwrap 采用「socket 激活」——fcgiwrap.socket 单元先建好 socket 文件,fcgiwrap.service 首个请求到达时才拉起进程。内存占用实测仅约 1MB,极轻。

6.2 nginx 站点配置

新建 /etc/nginx/sites-enabled/cgit(先删掉默认站点 rm -f /etc/nginx/sites-enabled/default):

server {
    listen 80 default_server;
    server_name _;

    # 静态资源(cgit.css / cgit.png / favicon)
    location /cgit-css/ {
        alias /var/www/htdocs/cgit/;
    }

    # CGI 入口:经 fcgiwrap 执行 cgit.cgi
    # PATH_INFO 必须剥离 /cgit 前缀(否则 cgit 把 /cgit/ 当仓库名解析)
    location ~ ^/cgit(/.*)?$ {
        fastcgi_pass unix:/run/fcgiwrap.socket;
        fastcgi_param SCRIPT_FILENAME /var/www/htdocs/cgit/cgit.cgi;
        fastcgi_param PATH_INFO $1;
        include fastcgi_params;
    }

    # /cgit -> /cgit/ 与根路径规整
    location = /cgit { return 301 /cgit/; }
    location = / { return 301 /cgit/; }
}

逐项说明:

  • location /cgit-css/ + alias:cgit.cgi 生成的页面引用 /cgit-css/cgit.css 等静态资源(与 cgitrc 里 css=/cgit-css/cgit.css 对应),由 nginx 直接发文件,不走 CGI。
  • location ~ ^/cgit(/.*)?$:正则捕获 /cgit 之后的全部路径作为 $1。
  • fastcgi_param SCRIPT_FILENAME:固定指向 cgit.cgi 绝对路径——方案 A 用 /usr/lib/cgit/cgit.cgi,方案 B 用 /var/www/htdocs/cgit/cgit.cgi。
  • fastcgi_param PATH_INFO $1:关键。Cgit 靠 PATH_INFO 解析「/仓库名/视图」路由,必须把 /cgit 前缀剥掉,只传剩余部分;不剥前缀会把 cgit 当成仓库名,列表页空白。
  • include fastcgi_params:引入 QUERY_STRING/REQUEST_METHOD 等标准 CGI 参数(Ubuntu 的 fastcgi_params 不含 SCRIPT_FILENAME,不会覆盖上一行,顺序安全)。

校验并加载:

nginx -t
systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

6.3 端到端验证

curl -sI http://127.0.0.1/cgit/
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Tue, 27 Oct 2026 10:13:10 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Last-Modified: Tue, 27 Oct 2026 10:13:10 GMT
Expires: Tue, 27 Oct 2026 10:18:10 GMT

注意 Expires 比 Date 晚 5 分钟——这正是 cgitrc 里 cache-repo-ttl=5 的缓存策略在 HTTP 头上的体现,链路已按缓存架构工作。

七、systemd 托管

nginx 与 fcgiwrap 均由 systemd 托管,逐条设置开机自启(每行一个单元):

systemctl enable nginx
systemctl enable fcgiwrap.socket
systemctl is-active nginx
systemctl is-active fcgiwrap
enabled
enabled
active
active

⚠️ 排障实录(真实事故):若用手工方式启动 fcgiwrap(如 fcgiwrap -s unix:/run/fcgiwrap/fcgiwrap.socket 写进自研启动脚本),机器或进程重启后残留的 socket 文件会让 fcgiwrap 启动即失败,实测报错:

Failed to bind: Address already in use

复现方式:先占用 /tmp/socktest/fcgiwrap.socket 再启动即 100% 复现。规避:启动脚本里执行 fcgiwrap 之前加一行 rm -f /run/fcgiwrap/fcgiwrap.socket;若写成 systemd service,加 ExecStartPre=/bin/rm -f /run/fcgiwrap/fcgiwrap.socket。用 Ubuntu 自带 fcgiwrap.socket 单元(systemd 负责创建/清理 socket)则无此问题——这也是本文推荐托管方式的原因。

八、方案对比与选择建议

维度方案 A:apt 1.2.3方案 B:源码 1.3.1
是否需联网仅需 apt 源需下载两个官方 tar.xz(可走代理/离线包)
编译链不需要需要 build-essential 等
systemd 来源包自带 fcgiwrap.socket同(fcgiwrap 仍用 apt 包托管)
监听端口均走 nginx 80同左
优点1 分钟装好;自动安全更新上游最新特性与修复;内嵌 Git 2.54
缺点版本滞后 4 年需自行跟踪上游升级、重新编译

选择建议:生产环境选方案 B(1.3.1),版本新、安全修复全;临时演示/内网工具站可选方案 A,后续按 4.2→5 的路径平滑升级(只换 SCRIPT_FILENAME 指向,链路配置零改动)。

九、配置说明

主配置 /etc/cgitrc(两版共用;Cgit 启动时由 cgit.cgi 读取,改后无需重启任何进程,下一请求即生效):

# cgit 主配置(注意:scan-path 之前的全局键才会生效到扫描发现的仓库,顺序敏感)
css=/cgit-css/cgit.css
logo=/cgit-css/cgit.png
favicon=/cgit-css/favicon.ico
robots=noindex, nofollow

root-title=Quzuo Git Repositories
root-desc=hyperfast web frontend for git repositories, powered by cgit
root-readme=/var/lib/git/README.md

# 缓存(必须放在 scan-path 之前)
cache-root=/var/cache/cgit
cache-size=1000
cache-dynamic-ttl=10
cache-repo-ttl=5
cache-static-ttl=-1
cache-scanrc-ttl=1

# 快照与特性开关(必须放在 scan-path 之前)
snapshots=tar.gz tar.xz
enable-git-config=1
enable-blame=1
clone-url=https://git.example.com/$CGIT_REPO_URL
enable-index-owner=1
enable-commit-graph=1
enable-log-filecount=1
enable-log-linecount=1
section-from-path=1
virtual-root=/cgit/

# 仓库扫描根目录(递归发现裸仓库)——放在所有全局默认值之后
scan-path=/var/lib/git

关键项解读(完整参数手册见《Cgit 1.3.1 配置参数详解》篇):

  • virtual-root=/cgit/:站点挂载在 /cgit/ 路径下,必须与 nginx location 前缀一致。
  • scan-path=/var/lib/git:递归扫描该目录发现全部裸仓库;顺序敏感——写在它之前的全局键(缓存、特性开关)作为默认值生效到所有扫描发现的仓库,写在其后的不生效,这是 cgitrc 最容易踩的坑。
  • cache-static-ttl=-1:提交详情等永久不变页面缓存永不过期(Cgit 性能核心)。
  • snapshots=tar.gz tar.xz:tag/commit 页提供源码包下载链接。
  • clone-url:仓库页展示的可克隆地址模板,$CGIT_REPO_URL 宏按仓库展开(示例域名 git.example.com 按实际替换)。

十、常见问题(FAQ)

10.1 访问 /cgit/ 列表页空白或 404

现象:nginx 200 但页面无仓库,或路径解析错乱。定位:检查 fastcgi_param PATH_INFO $1; 是否漏配——PATH_INFO 必须剥离 /cgit 前缀;再确认 cgitrc 的 scan-path 目录下确为裸仓库(含 HEAD/objects/refs 的 .git 目录)。解决:按 6.2 配置原样修正后 systemctl reload nginx。

10.2 fcgiwrap 启动报 Failed to bind: Address already in use

现象:手工/脚本启动 fcgiwrap 时报 bind 失败。定位:上次运行残留的 socket 文件未清理(见七、排障实录的复现)。解决:rm -f <socket 路径> 后重启;或在启动脚本/systemd unit 加 ExecStartPre 清理;优先使用发行版自带 fcgiwrap.socket 单元。

10.3 页面有内容但无样式(裸 HTML)

现象:列表页能开但全白无 CSS。定位:/cgit-css/ 静态资源 404——nginx 的 location /cgit-css/ alias 路径与实际静态文件目录不符(apt 版在 /usr/share/cgit/,源码版在 /var/www/htdocs/cgit/)。解决:按 4.1 建软链统一布局,或修正 alias 指向。

10.4 改完 cgitrc 不生效 / 部分仓库不继承设置

现象:在 scan-path 之后追加的全局键不生效。定位:cgitrc 解析顺序敏感,scan-path 之后的键不影响扫描发现的仓库。解决:把全局默认值移到 scan-path 行之前;改 cgitrc 本身无需重启,下一请求即生效(但有缓存时需等 TTL 或清 /var/cache/cgit/*)。

10.5 缓存不生效、每次访问都慢

现象:页脚生成时间每次都变。定位:cache-root 目录不存在或不归 www-data,Cgit 写缓存静默失败。解决:mkdir -p /var/cache/cgit && chown -R www-data:www-data /var/cache/cgit。

10.6 从 apt 1.2.3 升级到源码 1.3.1 要做什么

按方案 B 编译安装到 /var/www/htdocs/cgit/,然后把 nginx 的 SCRIPT_FILENAME 从 /usr/lib/cgit/cgit.cgi 改指 /var/www/htdocs/cgit/cgit.cgi,reload 并清一次缓存(rm -rf /var/cache/cgit/*)即完成。/etc/cgitrc 两版完全兼容,无需改动;apt 包可保留(作回退)或 apt remove cgit(注意别用 purge 误删 /etc/cgitrc)。

十一、卸载与清理

源码版(方案 B)卸载:

rm -rf /var/www/htdocs/cgit /usr/local/lib/cgit
rm -f /etc/nginx/sites-enabled/cgit
systemctl reload nginx

如需连 apt 版一起清(共存过的话):

apt remove -y cgit

数据与缓存按需要去留(演示数据可整体删):

rm -rf /var/cache/cgit
# 仓库数据确认无用后再删:rm -rf /var/lib/git

fcgiwrap / nginx 如不再服务其他站点可一并 apt remove -y fcgiwrap nginx。

十二、参考链接