用 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
。
- 获取公钥:让
alice
把她的 SSH 公钥文件(如alice.pub
)发给你。 - 添加用户:将
alice.pub
文件复制到你本地gitolite-admin/keydir/
目录下。 - 配置权限:打开
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].*
。
参考文档