2010年8月5日 星期四

Gitosis HOWTO

話說git的傳輸協定有許多種, 包括ssh://, http(s)://, git://, file:///, 但若小規模的專案, 透過ssh進行傳輸與驗正式最方便的, 而若是要有集中式的權限管理, 靠gitosis就對了, 以下說明一下安裝過程...

出場角色: git-server, git-client-foo, git-client-bar

在git-server下載gitosis.git
[git-server]$ cd ~
[git-server]$ git clone git://eagain.net/gitosis.git
[git-server]$ cd gitosis
[git-server]$ sudo python setup.py install

在git-server新增git使用者
[git-server]$ sudo useradd git

在git-client-foo上產生foo使用者的公鑰
[git-client-foo]$ ssh-keygen -t rsa

將foo以rsa產生的公鑰(id_rsa.pub)交到git-server, 假設儲存在/tmp下 (via scp/ftp/email...)

在git-server初始化gitosis
[git-server]$ sudo -H -u git gitosis-init < /tmp/id_rsa.pub
Initialized empty Git repository in /home/git/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /home/git/repositories/gitosis-admin.git/

在不同distribution的linux下可能會遇到這樣的問題 (CentOS 5.4, 用source裝的git)
Traceback (most recent call last):
...
File "/usr/lib/python2.4/subprocess.py", line 993, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory

解決方法是將原來的一步拆成兩步, 並且確定git使用者的環境變數有git指令
[git-server]$ sudo -H -u git -s
[git-server]$ gitosis-init < /tmp/id_rsa.pub



在git-server修改權限
[git-server]$ sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update
現在foo@git-client-foo的使用者可以存取git-server的服務了...

測試foo@git-client-foo的登入是否正確
[git-client-foo]$ ssh git@git-server

如果出現錯誤訊息如
PTY allocation request failed on channel 0
ERROR:gitosis.serve.main:Need SSH_ORIGINAL_COMMAND in environment.
Connection to git.server closed.

表示git@git-server的無法以ssh登入shell, 但這是正常的. 但如果無法登入的錯誤訊息如
Agent admitted failure to sign using the key.
git@git-server's password:

則表示git-server和git-client的key交換有問題, 先在git-client檢查是否ssh agent有無啟動
[git-client-foo]$ ps aux|grep agent

在git-client-foo重新啟動ssh agent, 加入私鑰(id_rsa)幫忙代理
[git-client-foo]$ exec ssh-agent /bin/bash
[git-client-foo]$ ssh-add ~/.ssh/id_rsa
Identity added: .ssh/id_rsa (.ssh/id_rsa)

測試在git-client-foo上下載gitosis的repository
[git-client-foo]$ git clone git@git-server:gitosis-admin.git
Cloning into gitosis-admin...
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5 (delta 0), reused 5 (delta 0)
Receiving objects: 100% (5/5), done.

查看一下目錄是否正確
[git-client-foo]$ cd gitosis-admin
[git-client-foo]$ ls
gitosis.conf keydir/

gitosis.conf是用來設定用戶、repository和權限的控制文件, keydir目錄則是保存所有具有讀取權限用戶公鑰的地方

比如我們想建立一個新的群組kernel team, 裡面的成員包括foo@git-client-foo和bar@git-client-bar, 此一群組可讀/寫的project為kernel_source, 另外想建立一個群組一樣是kernel team, 裡面的成員是foobar@git-client-foobar, 此一群組對kernel_source只有唯讀的權限, 參考權限設定如下
[group kernel-team-rw]
writable = kernel_source
members = foo@git-client-foo bar@git-client-bar

[group kernel-team-ro]
readonly = kernel_source
members = foobar@git-client-foobar

[repo kernel_source]
owner = foo@git-client-foo
description = kernel source development

若要印出更多存取過程的訊息, 可在gitosis.conf加入loglevel的等級
[gitosis]
loglevel = DEBUG

在git-client-foo存檔離開後, 先將用戶bar@git-client-bar的公鑰放在keydir目錄下. 而bar的公鑰產生方式與上述相同, 一樣假設先放到/tmp下, 名稱取為bar@git-client-bar.pub(需與gitosis.conf中使用者名稱相同)
[git-client-foo]$ cp /tmp/bar@localhost.localdomain.pub keydir/bar@git-client-bar.pub

修改過得資料需新增至暫存區(staged)並提交(commit)回local repository
[git-client-foo]$ git add .
[git-client-foo]$ git commit -am 'add new project kernel_source and new group kernel-source'
[master 168490e] add new project kernel_source and new group kernel-source
2 files changed, 5 insertions(+), 0 deletions(-)

上傳到git-server以交由git server管理
[git-client-foo]$ git push origin master
Counting objects: 8, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 839 bytes, done.
Total 5 (delta 0), reused 0 (delta 0)
To git@git-server:gitosis-admin.git
928edf2..537d576 master -> master
7f9546c..168490e master -> master

這時候foo@git-client-foo和bar@git-clinet-bar就可以存取kernel_source的repository, 例如
[git-client-bar]$ git clone git@git-server:kernel_source

由於git-server上的kernel_source repository上還是空的, 所以你有可能會出現這樣的警告訊息
Cloning into kernel_souce...
Initialized empty Git repository in /home/git/repositories/kernel_source.git/
warning: You appear to have cloned an empty repository.

在bar@git-clinet-bar下查看, 可以看到多了一目錄kernel_source, 表示已經加入群組無誤
[git-client-bar]$ ls
kernel_source

在bar@git-client-bar新增一文件測試寫入權限, 例如
[git-client-bar]$ cd kernel_source
[git-client-bar]$ vim README
[git-client-bar]$ git add .
[git-client-bar]$ git commit -am 'add README'

在push回git-server之前, 先增加一remote機器的名稱
[git-client-bar]$ git remote add origin git@git-server:kernel_source
[git-client-bar]$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 212 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@git-server:kernel_source
* [new branch] master -> master

以上是小型案子使用gitosis的設定方式, 由於工作模式有很多, 若開發人員不只是公司內部人員, 權限模式會比較複雜, 如果有心瞭解更細部的運作與各種工作模式, 先聽聽Scott ChaconRailsConf 2008做的演講, 而且一定要閱讀全世界講解git寫的最好的投影片, 或者是閱讀pro git的線上英文版, 中文版, 都是非常有幫助的

參考資料:
* How to setup a GIT server with gitosis and gitweb

沒有留言: