作者:
<a target="_blank" href="http://www.ossxp.com/">北京群英彙資訊技術有限公司</a>
網址:
<a target="_blank" href="http://www.ossxp.com/">http://www.ossxp.com/</a>
版本:
0.1-1
日期:
2010-10-07 14:52:19
目錄
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#ssh">1 ssh 協定</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id3">1.1 ssh 公鑰認證</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id4">1.2 ssh 主機名稱</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#gitolite">2 gitolite 服務架設</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id5">2.1 安裝 gitolite</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id6">2.1.1 伺服器端建立專用帳号</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id7">2.1.2 gitolite 的安裝/更新</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id8">2.1.3 關于 ssh 主機名稱</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id9">2.1.4 其他的安裝方法</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id10">2.2 管理 gitolite</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#gitolite-admin">2.2.1 管理者克隆 gitolite-admin 管理庫</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id11">2.2.2 增加新使用者</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id12">2.2.3 更改授權</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id13">2.3 gitolite 授權詳解</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id14">2.3.1 授權檔案的基本文法</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id15">2.3.2 定義使用者組和版本庫組</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#acl">2.3.3 版本庫acl</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id16">2.3.4 gitolite 授權機制</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id17">2.4 版本庫授權案例</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id18">2.4.1 對整個版本庫進行授權</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id19">2.4.2 通配符版本庫的授權</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id20">2.4.3 使用者自己的版本庫空間</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id21">2.4.4 對引用的授權:傳統模式</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id22">2.4.5 對引用的授權:擴充模式</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id23">2.4.6 對引用的授權:禁用規則的使用</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id24">2.4.7 使用者分支</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id25">2.4.8 對路徑的寫授權</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id26">2.5 建立新版本庫</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id27">2.5.1 在配置檔案中出現的版本庫,即時生成</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#push">2.5.2 通配符版本庫,管理者通過push建立</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id28">2.5.3 直接在伺服器端建立</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id29">2.6 對 gitolite 的改進</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id30">2.7 gitolite 功能拓展</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id31">2.7.1 版本庫鏡像</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#gitweb-gitdaemon">2.7.2 gitweb 和 gitdaemon 支援</a>
<a target="_blank" href="http://www.ossxp.com/doc/git/gitolite.html#id32">2.7.3 其他功能拓展和參考</a>
如果不是要和他人協同開發,git 根本就不需要架設伺服器。git 在本地可以直接使用本地版本庫的路徑完成 git 版本庫間的操作。
但是如果需要和他人分享版本庫、協作開發,就需要能夠通過特定的網絡協定操作 git 庫。
git 支援的協定很豐富,架設伺服器的選擇也很多,不同的方案有着各自的優缺點。
http git-daemon ssh gitosis, gitolite 服務架設難易度 簡單 中等 複雜 匿名讀取 支援 否* 身份認證 否 版本庫寫操作 企業級授權支援 是否支援遠端建庫
注:
ssh 協定和基于 ssh 的 gitolite 等可以通過空密碼帳号實作匿名通路。
ssh 協定用于為 git 提供遠端讀寫操作,是遠端寫操作的标準服務,在智能http協定出現之前,甚至是寫操作的唯一标準服務。
對于擁有 shell 權限的 ssh 登入帳号,可以直接用下面的 git 指令通路,例如:
說明:
<username> 是伺服器 <server> 上的使用者帳号。
/path/to/repo.git 是伺服器中版本庫的絕對路徑。若用相對路徑則相對于 username 使用者的主目錄而言。
如果采用密碼認證,不能像 https 協定那樣可以在 url 中同時給出登入名和密碼,必須每次連接配接時輸入。
如果采用公鑰認證,則無須輸入密碼。
ssh 協定來實作 git 服務,有如下方式:
其一是用标準的 ssh 帳号通路版本庫。即使用者帳号可以直接登入到伺服器,獲得 shell。
另外的方式是,所有使用者都使用同一個專用的 ssh 帳号通路版本庫。各個使用者通過公鑰認證的方式用此專用 ssh 帳号通路版本庫。而使用者在連接配接時使用的不同的公鑰可以用于區分不同的使用者身份。
gitosis 和 gitolite 就是實作該方式的兩個伺服器軟體。
标準ssh帳号和專用ssh帳号的差別在于:
标準ssh gitosis/gitolite 帳号 每個使用者一個帳号 所有使用者共用同一個帳号 認證方式 密碼或公鑰認證 公鑰認證 使用者是否能直接登入 shell 是 安全性 差 好 管理者是否需要 shell 版本庫路徑 相對路徑或絕對路徑 相對路徑 授權方式 作業系統中使用者組和目錄權限 通過配置檔案授權 對分支進行寫授權 gitolite 對路徑進行寫授權 架設難易度
實際上,标準ssh,也可以用公鑰認證的方式實作所有使用者共用同一個帳号。不過這類似于把一個公共帳号的登入密碼同時告訴給多個人。
在伺服器端(server)建立一個公共帳号,例如 anonymous 。
管理者收集需要通路 git 服務的使用者公鑰。如: user1.pub, user2.pub 。
使用 ssh-copy-id 指令遠端将各個 git 使用者的公鑰加入伺服器(server)的公鑰認證清單中。
如果直接在伺服器上操作,則直接将檔案追加到 authorized_keys 檔案中。
在伺服器端的 anonymous 使用者主目錄下建立 git 庫,就可以實作多個使用者利用同一個系統帳号(git) 通路 git 服務了。
這樣做除了免除了逐一設定帳号,以及使用者無需密碼認證之外,标準ssh部署 git 服務的缺點一個也不少,而且因為使用者之間無法區分,更無法進行針對使用者授權。
下面重點介紹一下 ssh 公鑰認證,因為它們是後面介紹的 gitosis 和 gitolite 伺服器軟體的基礎。
如果你的主目錄下不存在 .ssh 目錄,說明你的 ssh 公鑰/私鑰對尚未建立。可以用這個指令建立:
該指令會在使用者主目錄下建立 .ssh 目錄,并在其中建立兩個檔案:
id_rsa
私鑰檔案。是基于 rsa 算法建立。該私鑰檔案要妥善保管,不要洩漏。
id_rsa.pub
公鑰檔案。和 id_rsa 檔案是一對兒,該檔案作為公鑰檔案,可以公開。
建立了自己的公鑰/私鑰對後,就可以使用下面的指令,實作無密碼登入遠端伺服器,即用公鑰認證取代密碼認證。
說明:
該指令會提示輸入使用者 user 在 server 上的ssh登入密碼。
當此指令執行成功後,再以 user 使用者登入 server 遠端主機時,不必輸入密碼直接登入。
該指令實際上将 .ssh/id_rsa.pub 公鑰檔案追加到遠端主機 server 的 user 主目錄下的 .ssh/authorized_keys 檔案中。
檢查公鑰認證是否生效,運作ssh到遠端主機,正常的話應該直接登入成功。如果要求輸入密碼則表明公鑰認證配置存在問題。如果ssh服務存在問題,可以通過檢視伺服器端的 /var/log/auth.log 進行診斷。
在實際應用中,有時需要使用多套公鑰/私鑰對,例如:
使用預設的公鑰通路 git 帳号,擷取 shell,進行管理者維護工作。
使用單獨建立的公鑰通路 git 帳号,執行 git 指令。
通路 github(免費的git服務托管商)采用其他公鑰。
如何建立指定名稱的公鑰/私鑰對呢?還是用 ssh-keygen 指令,如下:
将 <filename> 替換為有意義的名稱。
會在 ~/.ssh 目錄下建立指定的公鑰/私鑰對。 檔案 <filename> 是私鑰,檔案 <filename>.pub 是公鑰。
将新生成的公鑰添加到遠端主機的 .ssh/authorized_keys 檔案中,建立新的公鑰認證。例如:
這樣,就有兩個公鑰用于登入主機 server,那麼當執行下面的 ssh 登入指令,用到的是那個公鑰呢?
當然是預設公鑰 ~/.ssh/id_rsa.pub 。那麼如何用建立的公鑰連接配接 server 呢?
ssh 的用戶端配置檔案 ~/.ssh/config 可以通過建立主機名稱,在連接配接主機時,使用特定的公鑰。例如 ~/.ssh/config 檔案中的下列配置:
當執行
或者執行
含義為:
登入的 ssh 主機為 bj.ossxp.com 。
登入時使用的使用者名為 git 。
認證時使用的公鑰檔案為 ~/.ssh/jiangxin.pub 。
gitolite 是一款 perl 語言開發的 git 服務管理工具,通過公鑰對使用者進行認證,并能夠通過配置檔案對寫操作進行基于分支和路徑的的精細授權。gitolite 采用的是 ssh 協定并且使用 ssh 公鑰認證,是以需要您對 ssh 非常熟悉,無論是管理者還是普通使用者。是以在開始之前,請确認已經通讀過之前的“ssh 協定”一章。
gitosis 的啟發,開發了這款功能更為強大和易于安裝的軟體。gitolite 的命名,作者的原意是 gitosis 和 lite 的組合,不過因為 gitolite 的功能越來越強大,已經超越了 gitosis,是以作者笑稱 gitolite 可以看作是 github-lite —— 輕量級的 github。
我是在2010年8月才發現 gitolite 這個項目,并嘗試将公司基于 gitosis 的管理系統遷移至 gitolite。在遷移和使用過程中,增加和改進了一些實作,如:通配符版本庫的建立過程,對建立者的授權,版本庫名稱映射等。本文關于 gitolite 的介紹也是基于我改進的 gitosis 的版本。
原作者的版本庫位址:
<a target="_blank" href="http://github.com/sitaramc/gitolite">http://github.com/sitaramc/gitolite</a>
筆者改進後的 gitolite 分支:
<a target="_blank" href="http://github.com/ossxp-com/gitolite">http://github.com/ossxp-com/gitolite</a>
gitolite 的實作機制概括如下:
gitolite 安裝在伺服器( server ) 某個帳号之下,例如 git 帳号。
管理者通過 git 指令檢出名為 gitolite-admin 的版本庫。
管理者将 git 使用者的公鑰儲存在 gitolite-admin 庫的 keydir 目錄下,并編輯 conf/gitolite.conf 檔案為使用者授權。
當管理者對 gitolite-admin 庫的修改送出并 push 到伺服器之後,伺服器上 gitolite-admin 版本庫的鈎子腳本将執行相應的設定工作。
新使用者公鑰自動追加到伺服器端安裝帳号的 .ssh/authorized_keys 中,并設定該使用者的 shell 為 gitolite 的一條指令 gl-auth-command 。
更新伺服器端的授權檔案 ~/.gitolite/conf/gitolite.conf 。
編譯授權檔案 ~/.gitolite/conf/gitolite.conf-compiled.pm 。
使用者可以用 git 指令通路授權的版本庫。
當使用者以 git 使用者登入 ssh 服務時,因為公鑰認證的相關設定,不再直接進入 shell 環境,而是列印伺服器端 git 庫授權資訊後馬上退出。
即使用者不會通過 git 使用者進入伺服器的 shell,也就不會對系統的安全造成威脅。
當管理者授權,使用者可以遠端在伺服器上建立新版本庫。
下面介紹 gitolite 的部署和使用。在下面的示例中,約定:伺服器的名稱為 server ,gitolite 的安裝帳号為 git ,管理者的 id 為 admin 。
gitolite 要求 git 的版本必須是 1.6.2 或以上的版本,并且伺服器要提供 ssh 服務。下面是 gitolite 的安裝過程。
安裝 gitolite,首先要在伺服器端建立專用帳号,所有使用者都通過此帳号通路 git 庫。一般為友善易記,選擇 git 作為專用帳号名稱。
建立使用者 git,并設定使用者的 shell 為可登入的 shell,如 /bin/bash,同時添加同名的使用者組。
有的系統,隻允許特定的使用者組(如 ssh 使用者組)的使用者才可以通過 ssh 協定登入,這就需要将建立的 git 使用者添加到 ssh 使用者組中。
為 git 使用者設定密碼。當整個 git 服務配置完成,運作正常後,建議取消 git 的密碼,隻允許公鑰認證。
管理者在用戶端使用下面的指令,建立無密碼登入:
至此,我們已經完成了安裝 git 服務的準備工作,可以開始安裝 gitolite 服務軟體了。
本節的名字稱為安裝/更新,是因為 gitolite 的安裝和更新可以采用下列同樣的步驟。
gitolite 安裝可以在用戶端執行,而不需要在伺服器端操作,非常友善。安裝 gitolite 的前提是:
已經在伺服器端建立了專有帳号,如 git 。
管理者能夠以 git 使用者身份通過公鑰認證,無密碼方式登入方式登入伺服器。
安裝和更新都可以按照下面的步驟進行:
使用 git 下載下傳 gitolite 的源代碼。
進入 gitolite/src 目錄,執行安裝。
指令 gl-easy-install 的第一個參數 git 是伺服器上建立的專用帳号id,第二個參數 server 是伺服器ip或者域名,第三個參數 admin 是管理者id。
首先顯示版本資訊。
自動建立名為 admin 的私鑰/公鑰對。
gl-easy-install 指令行的最後一個參數即用于設定管理者id,這裡設定為 admin 。
如果公鑰已經存在,會彈出警告。
自動修改用戶端的 .ssh/config 檔案,增加别名主機。
即當通路主機 gitolite 時,會自動用名為 admin.pub 的公鑰,以 git 使用者身份,連接配接伺服器
上傳腳本檔案到伺服器,完成伺服器端軟體的安裝。
自動打開編輯器(vi),編輯 .gitolite.rc 檔案,編輯結束,上傳到伺服器。
以下為預設配置,一般無須改變:
$repo_base="repositories";
用于設定 git 伺服器的根目錄,預設是 git 使用者主目錄下的 repositories 目錄,可以使用絕對路徑。所有 git 庫都将部署在該目錄下。
$repo_umask = 0007; # gets you 'rwxrwx---'
版本庫建立使用的掩碼。即建立立版本庫的權限為 'rwxrwx---'。
$gl_big_config = 0;
如果授權檔案非常複雜,更改此項配置為1,以免産生龐大的授權編譯檔案。
$gl_wildrepos = 1;
預設支援通配符版本庫授權。
該配置檔案為 perl 文法,注意保持檔案格式和文法。退出 vi 編輯器,輸入 ":q" (不帶引号)。
至此完成安裝。
在安裝過程中,gitolite 建立了名為 admin 的公鑰/私鑰對,以名為 admin.pub 的公鑰連接配接伺服器,由 gitolite 提供服務。但是如果直接連接配接伺服器,使用的是預設的公鑰,會直接進入 shell。
那麼如何能夠根據需要選擇不同的公鑰來連接配接 git 伺服器呢?
别忘了我們在前面介紹過的 ssh 主機名稱。實際上剛剛在安裝 gitolite 的時候,就已經自動為我們建立了一個主機名稱。 打開 ~/.ssh/config 檔案,可以看到類似内容,如果對主機名稱不滿意,可以修改。
即:
像下面這樣輸入 ssh 指令,會直接進入 shell,因為使用的是預設的公鑰。
像下面這樣輸入 ssh 指令,則不會進入 shell。因為使用名為 admin.pub 的公鑰,會顯示 git 授權資訊并馬上退出。
上面介紹的是在用戶端遠端安裝 gitolite,是最常用和推薦的方法。當然還可以直接在伺服器上安裝。
首先也要在伺服器端先建立一個專用的帳号,如: git 。
将管理者公鑰複制到伺服器上。
管理者在用戶端執行下面的指令:
伺服器端安裝 gitolite。
推薦采用源碼方式安裝,因為如果以平台自帶軟體包模式安裝 gitolite,其中不包含我們對 gitolite 的改進。 從源碼安裝。
建立目錄。
進入 gitolite/src 目錄,執行安裝。
采用平台自帶的軟體包安裝。 例如在 debian/ubuntu 平台,執行下面指令:
redhat 則使用 yum 指令安裝。
在伺服器端以專用帳号執行安裝腳本。
例如伺服器端的專用帳号為 git。
管理者在用戶端,克隆 gitolite-admin 庫
更新 gitolite:
隻需要執行上面的第3個步驟即可完成更新。
如果修改或增加了新的了鈎子腳本,還需要重新執行第4個步驟。
gitolite 更新有可能要求修改配置檔案: ~/.gitolite.rc 。
當 gitolite 安裝完成後,在伺服器端自動建立了一個用于 gitolite 自身管理的 git 庫: gitolite-admin.git 。
克隆 gitolite-admin.git 庫。别忘了使用ssh主機名稱:
我們可以看出 gitolite-admin 目錄下有兩個目錄 conf/ 和 keydir/ 。
keydir/admin.pub 檔案
目錄 keydir 下初始時隻有一個使用者公鑰,即 amdin 使用者的公鑰。
conf/gitolite.conf 檔案
該檔案為授權檔案。初始内容為:
預設授權檔案中隻設定了兩個版本庫的授權:
gitolite-admin
即本版本庫(gitolite管理版本庫)隻有 admin 使用者有讀寫和強制更新的權限。
testing
預設設定的測試版本庫,設定為任何人都可以讀寫以及強制更新。
增加新使用者,就是允許新使用者能夠通過其公鑰通路 git 服務。隻要将新使用者的公鑰添加到 gitolite-admin 版本庫的 keydir 目錄下,即完成新使用者的添加。
管理者從使用者擷取公鑰,并将公鑰按照 username.pub 格式進行重命名。
使用者可以通過郵件或者其他方式将公鑰傳遞給管理者,切記不要将私鑰誤傳給管理者。如果發生私鑰洩漏,馬上重新生成新的公鑰/私鑰對,并将新的公鑰傳遞給管理者,并申請将舊的公鑰廢棄。
使用者從不同的用戶端主機通路有着不同的公鑰,如果希望使用同一個使用者名進行授權,可以按照[email protected] 方式命名公鑰檔案,和名為 username@pub 的公鑰指向同一個使用者 username 。
gitolite 也支援郵件位址格式的公鑰,即形如 [email protected] 的公鑰。gitolite 能夠很智能的區分是以郵件位址命名的公鑰還是相同使用者在不同主機上的公鑰。如果是郵件位址命名的公鑰,将以整個郵件位址作為使用者名。
管理者進入 gitolite-admin 本地克隆版本庫中,複制新使用者公鑰到 keydir 目錄。
執行 git add 指令,将公鑰添加入版本庫。
執行 git commit,完成送出。
執行 git push,同步到伺服器,才真正完成新使用者的添加。
如果我們這時檢視伺服器端 ~git/.ssh/authorized_keys 檔案,會發現新增的使用者公鑰也附加其中:
在之前執行 git push 後的輸出中,以 remote 辨別的輸出是伺服器端執行 post-update 鈎子腳本的輸出。其中的警告是說新添加的三個使用者在授權檔案中沒有被引用。接下來我們便看看如何修改授權檔案,以及如何為使用者添加授權。
新使用者添加完畢,可能需要重新進行授權。更改授權的方法也非常簡單,即修改 conf/gitolite.conf 配置檔案,送出并 push。
管理者進入 gitolite-admin 本地克隆版本庫中,編輯 conf/gitolite.conf 。
授權指令比較複雜,我們先通過建立新使用者組嘗試一下更改授權檔案。
考慮到之前我們增加了三個使用者公鑰之後,伺服器端發出了使用者尚未在授權檔案中出現的警告。我們就在這個示例中解決這個問題。
例如我們在其中加入使用者組 @team1,将新添加的使用者 jiangxin, dev1, dev2 都歸屬到這個組中。
我們隻需要在 conf/gitolite.conf 檔案的檔案頭加入如下指令。使用者之間用空格分隔。
編輯完畢退出。我們可以用 git diff 指令檢視改動:
我們還修改了版本庫 testing 的授權,将 @all 使用者組改為我們建立立的 @team1 使用者組。
編輯結束,送出改動。
執行 git push ,同步到伺服器,才真正完成授權檔案的編輯。
我們可以注意到,push 後的輸出中沒有了警告。
下面我們看一個不那麼簡單的授權檔案:
在上面的示例中,我們示範了很多授權指令。
第1行,定義了使用者組 @admin,包含兩個使用者 jiangxin 和 wangsheng。
第3-4行,定義了版本庫 gitolite-admin。并指定隻有使用者 jiangxin 才能夠通路,并擁有讀(r)寫(w)和強制更新(+)的權限。
第6行,通過正規表達式定義了一組版本庫,即在 ossxp/ 目錄下的所有版本庫。
第7行,使用者組 @admin 中的使用者,可以在 ossxp/ 目錄下建立版本庫。
建立版本庫的使用者,具有對版本庫操作的所有權限。
第8行,所有使用者都可以讀寫 ossxp 目錄下的版本庫,但不能強制更新。
第9行開始,定義的 testing 版本庫授權使用了引用授權文法。
第11行,使用者組 @admin 對所有的分支和裡程碑擁有讀寫、重置、添加和删除的授權。
第12行,使用者 junio 可以讀寫 master 分支。(還包括名字以 master 開頭的其他分支,如果有的話)。
第13行,使用者 junio 可以讀寫、強制更新、建立以及删除 pu 開頭的分支。
第14行,使用者 pasky 可以讀寫 cogito 分支。 (僅此分支,精确比對)。
在 conf/gitolite.conf 授權檔案中,可以定義使用者組或者版本庫組。組名稱以 @ 字元開頭,可以包含一個或多個成員。成員之間用空格分開。
例如定義管理者組:
組可以嵌套:
除了作為使用者組外,同樣文法也适用于版本庫組。
版本庫組和使用者組的定義沒有任何差別,隻是在版本庫授權指令中處于不同的位置。即位于授權指令中的版本庫位置則代表版本庫組,位于授權指令中的使用者位置則代表使用者組。
一個版本庫可以包含多條授權指令,這些授權指令組成了一個版本庫的權限控制清單(acl)。
例如:
每一個版本庫授權都以一條 repo 指令開始。
指令 repo 後面是版本庫清單,版本之間用空格分開,還可以包括版本庫組。
注意:版本庫名稱不要添加 .git 字尾。在版本庫建立過程中會自動添加 .git 字尾。
repo 指令後面的版本庫也可以用正規表達式定義的 通配符版本庫 。
正規表達式比對時,會自動在 通配符版本庫 的前後加上字首 ^ 和字尾 $ 。這一點和後面将介紹的正則引用(refex)大不一樣。
不過有時候使用了過于簡單的正規表達式如: "myrepo." ,有可能産生歧義,讓 gitolite 誤認為是普通版本庫名稱,在伺服器端自動建立名為 myrepo..git 的版本庫。解決歧義的一個辦法是:在正規表達式的前面插入 ^ 符号,或者在表達式後面添加 $ 符号,形如:"^myrepo.$"。
在 repo 指令之後,是縮進的一條或者多條授權指令。授權指令的文法:
每條指令必須指定一個權限。權限可以用下面的任意一個權限關鍵字:
c, r, rw, rw+, rwc, rw+c, rwd, rw+d, rwcd, rw+cd 。
權限後面包含一個可選的 refex(正則引用)清單。
正規表達式格式的引用,簡稱正則引用(refex),對 git 版本庫的引用(分支,裡程碑等)進行比對。
如果在授權指令中省略正則引用,意味着對全部的 git 引用(分支,裡程碑等)都有效。
正則引用如果不以 refs/ 開頭,會自動添加 refs/heads/ 作為字首。
正則引用如果不以 $ 結尾,意味着後面可以比對任意字元,相當于添加 .*$ 作為字尾。
權限後面也可以包含一個以 name/ 開頭的路徑清單,進行基于路徑的授權。
授權指令以等号(=)為标記分為前後兩段,等号後面的是使用者清單。
使用者之間用空格分隔,并且可以使用使用者組。
不同的授權關鍵字有不同的含義,有的授權關鍵字隻用在 特定 的場合。
c
c 代表建立。僅在 通配符版本庫 授權時可以使用。用于指定誰可以建立和通配符比對的版本庫。
r, rw, 和 rw+
r 為隻讀。rw 為讀寫權限。rw+ 含義為除了具有讀寫外,還可以對 rewind 的送出強制 push。
rwc, rw+c
隻有當授權指令中定義了正則引用(正規表達式定義的分支、裡程碑等),才可以使用該授權指令。其中 c 的含義是允許建立和正則引用比對的引用(分支或裡程碑等)。
rwd, rw+d
隻有當授權指令中定義了正則引用(正規表達式定義的分支、裡程碑等),才可以使用該授權指令。其中 d 的含義是允許删除和正則引用比對的引用(分支或裡程碑等)。
rwcd, rw+cd
隻有當授權指令中定義了正則引用(正規表達式定義的分支、裡程碑等),才可以使用該授權指令。其中 c 的含義是允許建立和正則引用比對的引用(分支或裡程碑等),d 的含義是允許删除和正則引用比對的引用(分支或裡程碑等)。
gitolite 的授權實際分為兩個階段,第一個階段稱為前git階段,即在 git 指令執行前,由 ssh 連結觸發的 gl-auth-command 指令執行的授權檢查。包括:
版本庫的讀。
使用者必須擁有版本庫至少一個分支的下列權限之一: r, rw, 或 rw+ ,則整個版本庫包含所有分支對使用者均可讀。
而版本庫分支實際上在這個階段擷取不到,即版本庫的讀取不能按照分支授權,隻能是版本庫的整體授權。
版本庫的寫。
版本庫的寫授權,則要在兩個階段分别進行檢查。第一階段的檢查是看使用者是否擁有下列權限之一: rw, rw+ 或者c 授權。
第二個階段檢查分支以及是否擁有強制更新。具體見後面的描述。
版本庫的建立。
僅對正規表達式定義的通配符版本庫有效。即擁有 c 授權的使用者,可以建立和對應正規表達式比對的版本庫。同時該使用者也擁有對版本庫的讀寫權限。
對授權的第二個階段的檢查,實際上是通過 update 鈎子腳本進行的。
因為版本庫的讀操作不執行 update 鈎子,是以讀操作隻在授權的第一個階段(前git階段)進行檢查,授權的第二個階段對版本庫的讀授權無任何影響。
鈎子腳本 update 針對 push 操作的各個分支進行逐一檢查,是以第二個階段可以進行針對分支寫操作的精細授權。
在這個階段也可以擷取到要更新的新的和老的 ref 的 sha 摘要,是以也可以進行是否有復原(rewind)的發生,即是否允許強制更新,還可以對分支的建立和删除進行授權檢測。
基于路徑的寫授權,也是在這個階段進行的。
gitolite 的授權非常強大也非常複雜,是以從版本庫授權的實際案例來學習非常行之有效。
授權檔案如下:
使用者 test1 對版本庫具有寫的權限。
第6行定義了 test1 所屬的使用者組 @test 具有隻讀權限。第8行定義了 test1 使用者具有讀寫權限。
gitolite 的實作是讀權限和寫權限分别進行判斷并彙總(并集),進而 test1 使用者具有讀寫權限。
使用者 jiangxin 對版本庫具有寫的權限,并能強制push。
第9行授權指令中的加号(+)含義是允許強制 push。
禁用指令,讓使用者 badboy 對版本庫隻具有讀操作的權限。
第7行的指令以減号(-)開始,是一條禁用指令。禁用指令隻在授權的第二階段起作用,即隻對寫操作起作用,不會對badboy 使用者的讀權限施加影響。
在第8行的指令中, badboy 所在的 @dev 組擁有讀取權限。但禁用規則會對寫操作起作用,導緻 badboy 隻有讀操作權限,而沒有寫操作。
這個授權檔案中的版本庫名稱中使用了正規表達式,比對在 sandbox 下的任意版本庫。
tip
正規表達式末尾的 $ 有着特殊的含義,代表比對字元串的結尾,明确告訴 gitolite 這個版本庫是通配符版本庫。
因為加号 + 既可以作為普通字元出現在版本庫的命名中,又可以作為正規表達式中特殊含義的字元,如果 gitolite 将授權檔案中的通配符版本庫誤判為普通版本庫,就會自動在伺服器端建立該版本庫,這是可能管理者不希望發生的。
在版本庫結尾添加一個 $ 字元,就明确表示該版本庫為正規表達式定義的通配符版本庫。
我修改了 gitolite 的代碼,能正确判斷部分正規表達式,但是最好還是對簡單的正規表達式添加 ^ 作為字首,或者添加$ 作為字尾,避免誤判。
正規表達式定義的通配符版本庫不會自動建立。需要管理者手動建立。
gitolite 原來對通配符版本庫的實作是克隆即建立,但是這樣很容易因為錄入錯誤導緻錯誤的版本庫意外被建立。群英彙改進的 gitolite 需要通過 push 建立版本庫。
以 admin 使用者的身份建立版本庫 sandbox/repos1.git 。
建立完畢後,我們對各個使用者的權限進行測試,會發現:
使用者 admin 對版本庫具有寫的權限。
這并不是因為第6行的授權指令為 @administrators 授予了 c 的權限。而是因為該版本庫是由 admin 使用者建立的,建立者具有對版本庫完全的讀寫權限。
伺服器端該版本庫目錄自動生成的 gl-creator 檔案記錄了建立者 id 為 admin 。
使用者 jiangxin 對版本庫沒有讀寫權限。
雖然使用者 jiangxin 和使用者 admin 一樣都可以在 sandbox/ 下建立版本庫,但是由于 sandbox/repos1.git 已經存在并且不是 jiangxin 使用者建立的,是以 jiangxin 使用者沒有任何權限,不能讀寫。
和之前的例子相同的是:
版本庫的建立者還可以使用 setperms 指令為版本庫添加授權。具體用法參見下面的示例。
使用者可以在自己的名字空間( /usrs/<userid>/ )下,自己建立版本庫。
設定管理者組對任何使用者在 users/ 目錄下建立的版本庫都有隻讀權限。
使用者可以使用 setperms 為自己的版本庫進行二次授權
即在輸入 setperms 指令後,進入一個編輯界面,輸入 ^d(ctrl+d)結束編輯。
也可以使用輸入重定向,先将授權寫入檔案,再用 setperms 指令加載。
使用者可以使用 getperms 檢視對自己版本庫的授權
傳統的引用授權,指的是授權指令中不包含 rwc, rwd, rwcd, rw+c, rw+d, rw+cd 授權關鍵字,隻采用 rw,rw+ 的傳統授權關鍵字。
在隻使用傳統的授權關鍵字的情況下,有如下注意事項:
rewind 必須擁有 + 的授權。
建立引用必須擁有 w 的授權。
删除引用必須擁有 + 的授權。
如果沒有在授權指令中提供引用相關的參數,相當于提供 refs/.* 作為引用的參數,意味着對所有引用均有效。
授權檔案:
第5行,版本庫 test/repo1 ,管理者組使用者 jiangxin 和 admin 可以任意建立和删除引用,并且可以強制 push。
第6行的規則看似隻對 master 和 refs/heads/feature/* 的引用授權,實際上 @dev 可以讀取所有名字空間的引用。這是因為讀取操作無法獲得 ref 相關内容。
即使用者組 @dev 的使用者隻能對 master 分支,以及以 feature/ 開頭的分支進行寫操作,但不能強制 push 和删除。至于其他分支和裡程碑,則隻能讀不能寫。
至于使用者組 @test 的使用者,因為使用了 r 授權指令,是以不涉及到分支的寫授權。
擴充模式的引用授權,指的是該版本庫的授權指令出現了下列授權關鍵字中的一個或多個: rwc, rwd, rwcd,rw+c, rw+d, rw+cd 。
建立引用必須擁有 c 的授權。
删除引用必須擁有 d 的授權。
對于版本庫 test/repo2.git :
使用者組 @administrators 中的使用者,具有建立和删除引用的權限,并且能強制 push。
使用者組 @dev 中的使用者,不能建立引用,但可以删除引用,以及可以強制 push。
使用者組 @test 中的使用者,可以 push 到任何引用,但是不能建立引用,不能删除引用,也不能強制 push。
對于版本庫 test/repo3.git :
使用者組 @dev 中的使用者,可以建立引用,并能夠強制 push,但不能删除引用,
使用者 jiangxin 可以寫任何裡程碑,包括以 v 加上數字開頭的裡程碑。
使用者 dev1, dev2 和 @others 組,隻能寫除了以 v 加上數字開頭之外的其他裡程碑。
其中以 - 開頭的授權指令建立禁用規則。禁用規則隻在授權的第二階段有效,是以不能對使用者的讀取進行限制!
和建立使用者空間(使用了 creator 關鍵字)的版本庫類似,還可以在一個版本庫内,允許管理自己名字空間( user關鍵字)下的分支。在正則引用的參數中出現的 user 關鍵字會被替換為使用者的 id。
使用者組 @administrators 中的使用者,對所有引用具有建立和删除引用的權限,并且能強制 push。
所有使用者都可以在 refs/personal/<userid>/ (自己的名字空間)下建立、删除引用。但是不能修改其他人的引用。
使用者組 @dev 中的使用者,對 master 分支具有讀寫和強制更新的權限,但是不能删除。
gitolite 也實作了對路徑的寫操作的精細授權,并且非常巧妙的是:在實作上增加的代碼可以忽略不計。這是因為 gitolite 把對路徑當作是特殊格式的引用的授權。
在授權檔案中,如果一個版本庫的授權指令中的正則引用字段出現了以 name/ 開頭的引用,則表明該授權指令是針對路徑進行的寫授權,并且該版本庫要進行基于路徑的寫授權判斷。
示例:
第2行,初級程式員 @junior_devs 和進階程式員 @senior_devs 可以對版本庫 foo 進行讀寫操作。
第4行,設定進階程式員 @senior_devs 對所有檔案( name/ )進行寫操作。
第5行和第6行,設定初級程式員 @junior_devs 對除了根目錄的 makefile 檔案外的其他檔案 ,具有寫權限。
gitolite 維護的版本庫位于安裝使用者主目錄下的 repositories 目錄中,即如果安裝使用者為 git ,則版本庫都建立在 /home/git/repositories 目錄之下。可以通過配置檔案 .gitolite.rc 修改預設的版本庫的根路徑。
有多種建立版本庫的方式。一種是在授權檔案中用 repo 指令設定版本庫(未使用正規表達式的版本庫)的授權,當對 gitolite-admin 版本庫執行 git push 操作,自動在服務端建立新的版本庫。另外一種方式是在授權檔案中用正規表達式定義的版本庫,不會即時建立,而是被授權的使用者在遠端建立後push到伺服器上完成建立。
注意,在授權檔案中建立的版本庫名稱不要帶 .git 字尾,在建立版本庫過程中會自動在版本庫後面追加 .git 字尾。
我們嘗試在授權檔案 conf/gitolite.conf 中加入一段新的版本庫授權指令,而這個版本庫尚不存在。新添加到授權檔案中的内容:
然後将授權檔案的修改送出并 push 到伺服器,我們會看到授權檔案中添加新授權的版本庫 testing2 被自動建立。
注意其中帶 remote 辨別的輸出,我們看到版本庫 testing2.git 被自動初始化了。
此外使用版本庫組的文法(即用 @ 建立的組,用作版本庫),也會被自動建立。例如下面的授權檔案片段設定了一個包含兩個版本庫的組 @testing ,當将新配置檔案 push 到伺服器上的時候,會自動建立 testing3.git 和 testing4.git 。
還有一種版本庫文法,是用正規表達式定義的版本庫,這類版本庫因為所指的版本庫并不确定,是以不會自動建立。
通配符版本庫是用正規表達式文法定義的版本庫,所指的非某一個版本庫而是和名稱相符的一組版本庫。首先要想使用通配符版本庫,需要在伺服器端安裝使用者(如 git )使用者的主目錄下的配置檔案 .gitolite.rc 中,包含如下配置:
使用通配符版本庫,可以對一組版本庫進行授權,非常有效。但是版本庫的建立則不像前面介紹的那樣,不會在授權檔案 push 到伺服器時建立,而是擁有版本庫建立授權(c)的使用者手工進行建立。
對于用通配符設定的版本庫,用 c 指令指定能夠建立此版本庫的管理者(擁有建立版本庫的授權)。例如:
管理者 jinagxin 可以建立路徑符合正規表達式 "ossxp/.+" 的版本庫,使用者 dev1 和 dev2 對版本庫具有讀寫(但是沒有強制更新)權限。
使用該方法建立版本庫後,建立者的 uid 将被記錄在版本庫目錄下的 gl-creator 檔案中。該帳号具有對該版本庫最高的權限。該通配符版本庫的授權指令中如果出現 creator 将被建立者的 uid 替換。
本地建庫
使用 git remote 指令添加遠端的源
運作 git push 完成在伺服器端版本庫的建立
克隆即建立,還是push即建立?
gitolite 的原始實作是通配符版本庫的管理者在對不存在的版本庫執行 clone 操作時,自動建立。但是我認為這不是一個好的實踐,會經常因為 clone 的 url 寫錯,導緻在伺服器端建立垃圾版本庫。是以我重新改造了 gitolite 通配符版本庫建立的實作,改為在對版本庫進行 push 的時候進行建立,而 clone 一個不存在的版本庫,會報錯退出。
當版本庫的數量很多的時候,在伺服器端直接通過 git 指令建立或者通過複制建立可能會更友善。但是要注意,在伺服器端手工建立的版本庫和 gitolite 建立的版本庫最大的不同在于鈎子腳本。如果不能為手工建立的版本庫正确設定版本庫的鈎子,會導緻失去一些 gitolite 特有的功能。例如:失去分支授權的功能。
一個由 gitolite 建立的版本庫,hooks 目錄下有三個鈎子腳本實際上連結到 gitolite 安裝目錄下的相應的腳本檔案中:
那麼手工在伺服器上建立的版本庫,有沒有自動更新鈎子腳本的方法呢?
有,就是重新執行一遍 gitolite 的安裝,會自動更新版本庫的鈎子腳本。安裝過程一路按回車即可。
除了鈎子腳本要注意以外,還要確定伺服器端版本庫目錄的權限和屬主。
筆者對 gitolite 進行擴充和改進,涉及到的内容主要包括:
通配符版本庫的建立方式和授權。
原來的實作是克隆即建立(克隆者需要被授予 c 的權限)。同時還要通過另外的授權語句為使用者設定 rw 權限,否則建立者沒有讀和寫權限。
新的實作是通過 push 建立版本庫(push 者需要被授予 c 權限)。不必再為建立者賦予 rw 等權限,建立者自動具有對版本庫最高的授權。
避免通配符版本庫誤判。
通配符版本庫誤判,會導緻在伺服器端建立錯誤的版本庫。新的設計還可以在通配符版本庫的正規表達式前或後添加 ^或 $ 字元,而不會造成授權檔案編輯錯誤。
改變預設配置。
預設安裝即支援通配符版本庫。
版本庫重定向。
gitosis 的一個很重要的功能:版本庫名稱重定向,沒有在 gitolite 中實作。我們為 gitolite 增加了這個功能。
在git伺服器架設的開始,版本庫的命名可能非常随意,例如 redmine 的版本庫直接放在根下,例如: redmine-0.9.x.git, redmine-1.0.x.git, ... 當 redmine 項目越來越複雜,可能就需要将其放在子目錄下進行管理,例如放到ossxp/redmine/ 目錄下。
隻需要在 gitolite 的授權檔案中添加下面一行 map 語句,就可以實作版本庫名稱重定向。使用舊的位址的使用者不必重新檢出,可以繼續使用。
git 版本庫控制系統往往并不需要設計特别的容災備份,因為每一個git使用者就是一個備份。但是下面的情況,就很有必要考慮容災了。
git 版本庫的使用者很少(每個庫可能隻有一個使用者)。
版本庫檢出隻限制在辦公區并且伺服器也在辦公區内(所有雞蛋在一個籃子裡)。
git 版本庫采用集中式的應用模型,需要建立雙機熱備(以便在故障出現時,實作快速的伺服器切換)。
gitolite 提供了伺服器間版本庫同步的設定。原理是:
主伺服器通過配置檔案 ~/.gitolite.rc 中的變量 $env{gl_slaves} 設定鏡像伺服器的位址。
從伺服器通過配置檔案 ~/.gitolite.rc 中的變量 $gl_slave_mode 設定從伺服器模式。
從主伺服器端運作腳本 gl-mirror-sync 可以實作批量的版本庫鏡像。
主伺服器的每一個版本庫都配置 post-receive 鈎子,一旦有送出,即時同步到鏡像版本庫。
在多個伺服器之間設定 git 庫鏡像的方法是:
每個伺服器都要安裝 gitolite 軟體,而且要啟用 post-receive 鈎子。
預設的鈎子在源代碼的 hooks/common 目錄下,名稱為 post-receive.mirrorpush ,要将其改名為 post-receive。否則版本庫的 post-receive 腳本不能生效。
主伺服器配置到從伺服器的公鑰認證,并且配置使用特殊的 shell: gl-mirror-shell 。
這是因為主伺服器在向從伺服器同步版本庫的時候,如果從伺服器版本庫沒有建立,直接通過 ssh 登入到從伺服器,執行建立指令。是以需要通過一個特殊的shell,能夠同時支援 gitolite 的授權通路以及 shell 環境。這個特殊的 shell 就是 gl-mirror-shell 。而且這個 shell,通過特殊的環境變量繞過伺服器的權限檢查,避免因為授權問題導緻同步失敗。
實際應用中,不光主伺服器,每個伺服器都進行類似設定,目的是主從伺服器可能互相切換。
在 gitolite 不同的安裝模式下, gl-mirror-shell 的安裝位置可能不同。下面的指令用于在伺服器端設定其他伺服器通路時使用這個特殊的 shell。
假設在伺服器 foo 上,安裝來自伺服器 bar 和 baz 的公鑰認證。公鑰分别是 bar.pub 和 baz.pub。
對于在用戶端安裝方式部署的 gitolite:
對于在伺服器端安裝方式部署的 gitolite, gl-mirror-shell 直接就可以在路徑中找到。
在 foo 伺服器上設定完畢,可以從伺服器 bar 或者 baz 上遠端執行:
執行指令後退出
進入 shell
在從伺服器上設定配置檔案 ~/.gitolite.rc 。
進行如下設定後,将不允許使用者直接 push 到從伺服器。但是主伺服器仍然可以 push 到從伺服器,是因為主伺服器版本庫在 push 到從伺服器時,使用了特殊的環境變量,能夠跳過從伺服器版本庫的 update 腳本。
在主伺服器上設定配置檔案 ~/.gitolite.rc 。
需要配置到從伺服器的 ssh 連接配接,可以設定多個,用空格分隔。注意使用單引号,避免 @ 字元被 perl 當作數組解析。
在主伺服器端執行 gl-mirror-sync 進行一次完整的資料同步。
需要以 gitolite 安裝使用者身份(如git)執行。例如在伺服器 foo 上執行到從伺服器 bar 的同步。
之後,每當使用者向主版本庫同步,都會通過版本庫的 post-receive 鈎子即時同步到從版本庫。
主從版本庫的切換。
切換非常簡單,就是修改 ~/.gitolite.rc 配置檔案,修改 $gl_slave_mode 設定:主伺服器設定為 0,從伺服器設定為1。
gitolite 和 git-daemon 的整合很簡單,就是在版本庫目錄中建立一個空檔案 git-daemon-export-ok 。
gitolite 和 gitweb 的整合,則提供了兩個方面的内容。一個是可以設定版本庫的描述資訊,用于在 gitweb 的項目清單頁面顯示。另外一個是自動生成項目的清單檔案供 gitweb 參卡,避免 gitweb 使用效率低的目錄遞歸搜尋查找 git 版本庫清單。
可以在授權檔案中設定版本庫的描述資訊,并在 gitolite-admin 管理庫更新時建立到版本庫的 description 檔案中。
第1行,為名為 reponame 的版本庫設定描述。
第1行,同時設定版本庫的屬主名稱,和一行版本庫描述。
對于通配符版本庫,使用這種方法則很不現實。gitolite 提供了 ssh 子指令,供版本庫的建立者使用。
第一條指令用于設定版本庫的描述資訊。
第二條指令顯示版本庫的描述資訊。
至于生成 gitweb 所用的項目清單檔案,預設建立在使用者主目錄下的 projects.list 檔案中。對于所有啟用 gitweb 的 [repo] 小節設定的版本庫,或者通過版本庫描述隐式聲明的版本庫加入到版本庫清單中。
gitolite 源碼的 doc 目錄包含用 markdown 标記語言編寫的手冊,可以直接在 github 上檢視。也可以使用markdown 的文檔編輯工具将 .mkd 文檔轉換為 html 文檔。轉換工具很多,有:rdiscount,
bluefeather, maruku, bluecloth2 等等。
在這些參考文檔中,你可以發現 gitolite 包含的更多的小功能或者秘籍,包括:
版本庫設定。
在授權檔案通過 git config 指令為版本庫進行附加的設定。例如:
多級管理者授權。
可以為不同版本庫設定管理者,操作 gitolite-admin 庫的部分授權檔案。參見: doc/5-delegation.mkd 。
自定義鈎子腳本。
因為 gitolite 占用了幾個鈎子腳本,如果需要對同名鈎子進行擴充,gitolite 提供了級聯的鈎子腳本,将定制放在級聯的鈎子腳本裡。
例如:通過自定義 gitolite-admin 的 post-update.secondary 腳本,以實作無需登入伺服器,更改 .gitolite.rc 檔案。參見: doc/shell-games.mkd 。
關于鈎子腳本的建立和維護,參見: doc/hook-propagation.mkd 。
管理者自定義指令。
通過設定配置檔案中的 $gl_adc_path 變量,在遠端執行該目錄下的可執行腳本,如: rmrepo 。
具體參考: doc/admin-defined-commands.mkd 。
建立匿名 ssh 認證。
允許匿名使用者通路 gitolite 提供的 git 服務。即建立一個和 gitolite 伺服器端帳号同 id 和主目錄的使用者,并設定其的特定 shell,并且允許密碼為空。
具體參考: doc/mob-branches.mkd 。
可以通過名為 @all 的版本庫進行全局的授權。
但是不能在 @all 版本庫中對 @all 使用者組進行授權。
版本庫非常或者使用者非常之多(幾千個)的時候,需要使用 大配置檔案 模式。
因為 gitolite 的授權檔案要先編譯才能生效,而編譯檔案的大小是和使用者以及版本庫數量的乘積成正比的。選擇大配置檔案模式,則不對使用者組和版本庫組進行擴充。
參見: doc/big-config.mkd 。
授權檔案支援包含語句,可以将授權檔案分成多個獨立的單元。
執行外部指令,如 rsync。
subversion 版本庫支援。
如果在同一個伺服器上以 svn+ssh 方式運作 subversion 伺服器,可以使用同一套公鑰,同時為使用者提供 git 和 subversion 服務。
http 密碼檔案維護。通過 htpasswd ssh 子指令實作。