跳转到内容
新建笔记

自托管 Git:SSH 与裸仓库

自托管 Git 的最小组成是一个存储提交的裸仓库、一个能访问它的服务账户,以及明确的 SSH 权限。它不等于在自己电脑上初始化普通仓库。

普通仓库包含工作区,适合编辑和构建;裸仓库主要保存 Git 对象与引用,适合充当集中收发端。不要把部署网站的工作目录直接当作任意用户可以推送的 Git 服务器。

下面是假设已由管理员创建 git 服务账户,并将 /srv/git 的写权限交给该账户之后,以该账户执行的示例:

终端窗口
git init --bare --initial-branch=main /srv/git/project.git

路径、账户、主机名都应替换为自己的环境;示例没有替你开放服务器访问权限。裸仓库初始没有提交,main 会在首次成功推送后出现。

客户端连接与首次推送

跳转到“客户端连接与首次推送”

先通过受信渠道核对服务器 SSH 主机指纹。每位使用者配置自己的公钥,私钥留在客户端;不要在笔记或远程 URL 中粘贴密码和私钥。

终端窗口
# 客户端新项目
git init -b main project
cd project
# 创建并检查文件后,再选择性 add 和 commit
git remote add origin git@example.com:/srv/git/project.git
git push -u origin main

已有 origin 时,先 git remote -v 检查,再决定新增其他别名或 remote set-url。从已有服务器项目开始则用:

终端窗口
git clone git@example.com:/srv/git/project.git

服务器仓库的默认 HEAD 可在裸仓库中通过 git symbolic-ref HEAD refs/heads/main 设置;这是服务器侧操作。客户端的 git remote set-head origin main 只改本地跟踪别名,两者不同。

权限与认证应如何分层

跳转到“权限与认证应如何分层”
层次需要确认的内容
SSH 主机身份known_hosts 中的服务器指纹正确
用户认证客户端私钥与服务端授权公钥对应
文件权限接收推送的账户能写裸仓库,但不能任意改其他应用目录
操作授权SSH 登录成功不代表用户只能做 Git;需要按方案限制 shell 或命令
协作管理分支保护、审查、审计和用户撤权需单独设计

Git 官方示例介绍了 git-shell 和共享访问的限制方式。多人协作若需要逐用户授权、合并请求和审计,更适合使用有这些能力的托管平台,不要仅共享一把私钥。

把 SSH 地址换成 http://.../project.git 不会自动得到 HTTP Git 服务;服务器必须配置相应 HTTP 后端或托管应用。也不要用全盘 chmod 777、宽泛所有权修改或全局信任所有仓库来修权限。

首次推送后,在新的客户端目录 clone,并比较 git rev-parse HEAD 与 git ls-remote --heads origin main。再验证无权限用户不能推送。备份应覆盖裸仓库、必要配置和受保护的授权资料,不能只备份某次检出的源文件。

参考:Pro Git:在服务器上搭建 Git、git-init、git-shell。