用 Gitolite 搭建你自己的私有 Git 服务器

AI 生成 + 人工编辑

前段时间写了 使用 Caddy 和容器轻松搭建你的私有 Git 服务器 (Git Over HTTPS),因为我有一个更复杂的需求–推送时创建仓库,所以需要一个更灵活的 Git 服务器,于是我决定研究一下 Gitolite。

为什么选择 Gitolite?

在众多 Git 服务解决方案中,Gitolite 独树一帜。它不是一个像 GitLab 那样的“全家桶”,而是一个专注的“权限管家”。

  • 极致轻量:它只是一系列 Perl 脚本,无需数据库,无需 Web 服务器,对系统资源消耗极低。
  • 安全性:所有用户通过 SSH 公钥认证,他们无法获得服务器的 shell 访问权限。
  • 精细的权限控制:你可以控制到谁能读写哪个仓库的哪个分支,甚至可以禁止某人强制推送或删除分支。
  • 用 Git 管理 Git:所有的用户、仓库和权限配置都存储在一个名为 gitolite-admin 的特殊 Git 仓库中。你只需在自己电脑上 git push,就能完成所有管理操作,酷不酷?

准备好了吗?让我们开始吧!


服务器端初始化

这一部分的操作都在你的服务器上进行,而且只需要做一次。

创建专属 git 用户

出于安全考虑,我们绝不使用 root 用户来运行服务。创建一个专门的 git 用户是最佳实践。

# 创建一个名为 'git' 的用户,并为其创建主目录
sudo useradd -m -s /bin/bash git

# 如果 git 用户已存在则使用以下命令修改其主目录
# sudo mkdir -p /home/git # 如果主目录不存在
# sudo usermod -d /home/git -s /bin/bash git

# (推荐)锁定该用户的密码,强制所有操作都通过 SSH 密钥进行
sudo passwd -l git

安装 Gitolite 并上传你的管理员公钥

我使用 Archlinux,使用包管理器 pacman 安装。其他发行版请自行调整命令。可以参考官方文档 Quick Install

# 更新你的包数据库并安装 gitolite
sudo pacman -Syu gitolite

接下来,你需要将自己设为 Gitolite 的最高管理员。这通过上传你的 SSH 公钥来完成。上传文件的方法有很多, 根据自己的情况选择。下文以上传后路径 /tmp/admin.pub 为例。

初始化 Gitolite

这是最关键的一步。我们将使用刚刚上传的公钥来启动 Gitolite 服务。

在你的服务器上运行:

# 切换到 git 用户身份
sudo -u git -i

# 使用你的公钥作为管理员,初始化 Gitolite
# 部分发行版使用 gitolite3 而不是 gitolite,请参考官方文档
gitolite setup -pk /tmp/admin.pub

# 看到类似 "Initialized..." 的输出后,退出 git 用户
exit

这个命令会自动创建 ~/repositories~/.gitolite 目录,并配置好 gitolite-admin 核心管理仓库。最重要的是,它会接管 ~git/.ssh/authorized_keys 文件。此后,请勿手动编辑此文件!

清理工作

安装完成后,服务器上的临时公钥文件就不再需要了。

sudo rm /tmp/admin.pub

至此,服务器已经像一台准备就绪的精良机器,静待你的指令。


在本地管理一切

从现在开始,你将体验到 Gitolite 设计的精妙之处。所有的管理工作,都在你自己的电脑上,通过 Git 命令完成。

克隆 gitolite-admin 管理仓库

这是你的“中央控制室”。

在你的本地上,找个地方克隆它:

# 将 YOUR_SERVER_IP 替换为你的服务器 IP 地址
git clone git@YOUR_SERVER_IP:gitolite-admin

克隆成功后,你会看到这样一个简洁的结构:

gitolite-admin/
├── conf/
│   └── gitolite.conf  # 权限与仓库的定义文件
└── keydir/
    └── admin.pub      # 所有用户的公钥存放处

实战演练:添加新用户和项目

假设你的团队来了一位新成员 alice,你们要开始一个激动人心的新项目 my-awesome-app

  1. 获取公钥:让 alice 把她的 SSH 公钥文件(如 alice.pub)发给你。
  2. 添加用户:将 alice.pub 文件复制到你本地 gitolite-admin/keydir/ 目录下。
  3. 配置权限:打开 gitolite-admin/conf/gitolite.conf 文件,在末尾添加以下内容:
# ... 已有的配置 ...

# 为新项目 my-awesome-app 创建一个仓库定义
repo my-awesome-app
    # RW+ = 读、写、强制推送权限
    # 将这些权限赋予用户 'alice'
    RW+     =   alice

    # R = 只读权限
    # 管理员 'admin' 拥有只读权限(当然你也可以给自己 RW+)
    R       =   admin

小贴士:Gitolite 会自动将 keydir/ 目录下的文件名(去掉 .pub 后缀)识别为用户名。

提交并推送,让配置生效

是时候施展魔法了。在 gitolite-admin 仓库目录中,执行标准的 Git 流程:

# 将你的所有修改添加到暂存区
git add .

# 提交一个清晰的 commit message
git commit -m "Add user alice and create repo my-awesome-app"

# 推送到服务器!
git push

当你按下回车,Gitolite 的钩子脚本会在服务器上被触发,自动创建 my-awesome-app.git 裸仓库,并应用你刚刚设定的所有权限规则。整个过程行云流水。

通知新伙伴开工

现在,你可以告诉 alice,她的新项目已经准备就绪。她只需在自己的电脑上运行:

git clone git@YOUR_SERVER_IP:my-awesome-app

其他设置

迁移已有仓库

  • 将存储库移动到 /home/git/repositories 目录下

    • 需确保它们都是裸存储库
    • 所有存储库名称都以 .git 结尾
    • 所有文件和目录都由 git 拥有和可写
    • 无论文件从何处获取,都没有留下任何符号链接
  • 在 git 身份下运行以下三个命令:

    gitolite compile
    gitolite setup --hooks-only
    gitolite trigger POST_COMPILE
  • 编辑 conf/gitolite.conf 文件,将新的存储库添加到 gitolite.conf 文件中

允许用户推送时创建仓库

编辑 conf/gitolite.conf 文件,添加以下内容:

repo    [a-zA-Z0-9].*
    C       =   @all
    RW+     =   CREATOR

小贴士: 此处不能直接使用 .*,而是需要使用 [a-zA-Z0-9].*
参考文档

常见问题

Podman 组权限问题

参考文章:Podman Rootless 技巧:利用 --group-add keep-groups 解决卷组权限难题

0%