Gitosis 是早期基於 SSH 公鑰授權的 Git 服務端工具,雖已停止維護(現多用 Gitolite 或 Gitea/GitLab),但其輕量、無數據庫、純文件系統管理的特性仍適合中小團隊或嵌入式設備。本文記錄 CentOS 上完整部署流程、權限配置語法與 Hook 自動部署實戰。
# 1. 安裝 Python Setuptools (Gitosis 依賴)
yum install -y python-setuptools git python-devel
# 2. 獲取 Gitosis 源碼 (官方已遷移至 GitHub)
git clone https://github.com/tv42/gitosis.git
cd gitosis
python setup.py install
# 1. 創建專用 git 用戶
useradd -r -s /bin/bash -m -d /home/git git
# 2. 生成管理員 SSH 金鑰對 (在管理員工作站)
ssh-keygen -t ed25519 -C "git-admin@company" -f ~/.ssh/git_admin
# 輸出: ~/.ssh/git_admin (私鑰) ~/.ssh/git_admin.pub (公鑰)
# 3. 初始化 Gitosis 倉庫 (在服務器以 git 用戶)
su - git
gitosis-init < /path/to/git_admin.pub
# 輸出: Initialized empty Git repository in /home/git/repositories/gitosis-admin.git/
# 在管理員工作站
git clone git@git-server:gitosis-admin.git
cd gitosis-admin
# 結構:
# gitosis.conf # 權限配置文件
# keydir/ # 公鑰目錄,文件名 = 用戶名.pub
[gitosis]
# 管理員組 (擁有 gitosis-admin 寫權限)
[group gitosis-admin]
writable = gitosis-admin
members = admin@workstation
# 項目組範例
[group project-alpha]
writable = alpha-repo beta-repo
members = alice@dev bob@dev charlie@ops
[group project-beta]
writable = gamma-repo
members = david@dev eve@qa
# 只讀權限
[group readonly]
readonly = alpha-repo beta-repo
members = intern@tmp
writable:該組擁有推送權限的倉庫列表(空格分隔),倉庫會自動創建於 /home/git/repositories/。readonly:僅允許 git clone/fetch/pull。members:用戶列表,必須與 keydir/ 下公鑰文件名(不含 .pub)完全一致。# 1. 用戶生成金鑰並發送公鑰給管理員
ssh-keygen -t ed25519 -C "alice@dev"
# 2. 管理員放入 keydir 並改名
cp alice.pub gitosis-admin/keydir/alice@dev.pub
# 3. 修改 gitosis.conf 添加用戶到對應組
vim gitosis-admin/gitosis.conf
# 4. 提交推送生效
cd gitosis-admin
git add .
git commit -m "Add alice@dev to project-alpha"
git push origin master
# 服務端自動更新 authorized_keys、創建倉庫目錄
# 克隆
git clone git@git-server:alpha-repo.git
cd alpha-repo
# 推送代碼
echo "# Alpha Project" > README.md
git add .
git commit -m "Init"
git push origin master
場景:推送到 master 分支自動部署至 Nginx 靜態站點目錄。
# 在服務器項目倉庫裸倉庫中
cd /home/git/repositories/alpha-repo.git/hooks
cat > post-receive <<'EOF'
#!/bin/bash
# post-receive hook: 自動部署靜態站點
TARGET="/home/wwwroot/alpha.example.com"
GIT_DIR="/home/git/repositories/alpha-repo.git"
BRANCH="master"
while read oldrev newrev refname; do
if [ "$refname" = "refs/heads/$BRANCH" ]; then
echo "Deploying $BRANCH to $TARGET"
git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
# 可選: 構建步驟 (npm run build, hugo, jekyll 等)
# 可選: 重載 Nginx
# systemctl reload nginx
fi
done
EOF
chmod +x post-receive
注意:Hook 以 git 用戶運行,需確保目標目錄寫權限:chown -R git:git /home/wwwroot/alpha.example.com。
| 現象 | 原因 | 解決 |
|---|---|---|
ERROR:gitosis.serve.main:Repository read access denied | 公鑰文件名與 members 不匹配、或公鑰未添加 | 檢查 keydir/用戶名.pub 存在、gitosis.conf members 拼寫一致、推送生效 |
fatal: 'repo.git' does not appear to be a git repository | 倉庫未自動創建 | 確認組配置 writable = repo、推送配置、服務端 /home/git/repositories/ 權限 |
| 推送後 Hook 不執行 | Hook 文件無執行權限、或 shebang 錯誤 | chmod +x hooks/post-receive、首行 #!/bin/bash |
| SSH 連接被拒絕 | 防火牆、SELinux、sshd 配置 | 開放 22 埠、setsebool -P gitosis_can_network 1、檢查 /var/log/secure |
Gitosis 2010 年後無更新,缺乏現代特性(保護分支、MR/PR、Web UI、LDAP/OIDC、審計日誌)。建議新項目直接部署: