把全部用戶的公鑰保存在 authorized_keys 文件的作法,只能湊和一陣子,當用戶數量達到幾百人的規模時,管理起來就會十分痛苦。每次改刪用戶都必須登陸服務器不去說,這種作法還缺乏必要的權限管理 — 每一個人都對全部項目擁有完整的讀寫權限。python
幸虧咱們還能夠選擇應用普遍的 Gitosis 項目。簡單地說,Gitosis 就是一套用來管理 authorized_keys 文件和實現簡單鏈接限制的腳本。有趣的是,用來添加用戶和設定權限的並不是經過網頁程序,而只是管理一個特殊的 Git 倉庫。你只須要在這個特殊倉庫內作好相應的設定,而後推送到服務器上,Gitosis 就會隨之改變運行策略,聽起來就很酷,對吧?git
Gitosis 的安裝算不上傻瓜化,但也不算太難。用 Linux 服務器架設起來最簡單 — 如下例子中,咱們使用裝有 Ubuntu 8.10 系統的服務器。web
Gitosis 的工做依賴於某些 Python 工具,因此首先要安裝 Python 的 setuptools 包,在 Ubuntu 上稱爲 python-setuptools:shell
$ apt-get install python-setuptools
接下來,從 Gitosis 項目主頁克隆並安裝:
安全
$ git clone git://eagain.net/gitosis.git $ cd gitosis $ sudo python setup.py install
這會安裝幾個供 Gitosis 使用的工具。默認 Gitosis 會把 /home/git 做爲存儲全部 Git 倉庫的根目錄,這沒什麼很差,不過咱們以前已經把項目倉庫都放在/opt/git 裏面了,因此爲方便起見,咱們能夠作一個符號鏈接,直接劃轉過去,而沒必要從新配置:服務器
$ ln -s /opt/git /home/git/repositories
Gitosis 將會幫咱們管理用戶公鑰,因此先把當前控制文件更名備份,以便稍後從新添加,準備好讓 Gitosis 自動管理authorized_keys 文件:ssh
$ mv /home/git/.ssh/authorized_keys /home/git/.ssh/ak.bak
接下來,若是以前把 git 用戶的登陸 shell 改成 git-shell 命令的話,先恢復 ‘git’ 用戶的登陸 shell。改過以後,你們仍然沒法經過該賬號登陸(譯註:由於authorized_keys 文件已經沒有了。),不過不用擔憂,這會交給 Gitosis 來實現。因此如今先打開 /etc/passwd 文件,把這行:iphone
git:x:1000:1000::/home/git:/usr/bin/git-shell
改回:工具
git:x:1000:1000::/home/git:/bin/sh
好了,如今能夠初始化 Gitosis 了。你能夠用本身的公鑰執行 gitosis-init 命令,要是公鑰不在服務器上,先臨時複製一份:post
$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub Initialized empty Git repository in /opt/git/gitosis-admin.git/ Reinitialize
這樣該公鑰的擁有者就能修改用於配置 Gitosis 的那個特殊 Git 倉庫了。接下來,須要手工對該倉庫中的 post-update 腳本加上可執行權限:
$ sudo chmod 755 /opt/git/gitosis-admin.git/hooks/post-update
基本上就算是好了。若是設定過程沒出什麼差錯,如今能夠試一下用初始化 Gitosis 的公鑰的擁有者身份 SSH 登陸服務器,應該會看到相似下面這樣:
$ ssh git@gitserver PTY allocation request failed on channel 0 fatal: unrecognized command 'gitosis-serve schacon@quaternion'
說明 Gitosis 認出了該用戶的身份,但因爲沒有運行任何 Git 命令,因此它切斷了鏈接。那麼,如今運行一個實際的 Git 命令 — 克隆 Gitosis 的控制倉庫:
# 在你本地計算機上 $ git clone git@gitserver:gitosis-admin.git
這會獲得一個名爲 gitosis-admin 的工做目錄,主要由兩部分組成:
$ cd gitosis-admin $ find . ./gitosis.conf ./keydir ./keydir/scott.pub
gitosis.conf 文件是用來設置用戶、倉庫和權限的控制文件。keydir 目錄則是保存全部具備訪問權限用戶公鑰的地方— 每人一個。在keydir 裏的文件名(好比上面的 scott.pub)應該跟你的不同 — Gitosis 會自動從使用gitosis-init 腳本導入的公鑰尾部的描述中獲取該名字。
看一下 gitosis.conf 文件的內容,它應該只包含與剛剛克隆的 gitosis-admin 相關的信息:
$ cat gitosis.conf [gitosis] [group gitosis-admin] writable = gitosis-admin members = scott
它顯示用戶 scott — 初始化 Gitosis 公鑰的擁有者 — 是惟一能管理 gitosis-admin 項目的人。
如今咱們來添加一個新項目。爲此咱們要創建一個名爲 mobile 的新段落,在其中羅列手機開發團隊的開發者,以及他們擁有寫權限的項目。因爲 ‘scott’ 是系統中的惟一用戶,咱們把他設爲惟一用戶,並容許他讀寫名爲iphone_project 的新項目:
[group mobile] writable = iphone_project members = scott
修改完以後,提交 gitosis-admin 裏的改動,並推送到服務器使其生效:
$ git commit -am 'add iphone_project and mobile group' [master]: created 8962da8: "changed name" 1 files changed, 4 insertion
在新工程 iphone_project 裏首次推送數據到服務器前,得先設定該服務器地址爲遠程倉庫。但你不用事先到服務器上手工建立該項目的裸倉庫— Gitosis 會在第一次遇到推送時自動建立:
$ git remote add origin git@gitserver:iphone_project.git $ git push origin master Initialized empty Git repository in /opt/gi
請注意,這裏不用指明完整路徑(實際上,若是加上反而沒用),只須要一個冒號加項目名字便可 — Gitosis 會自動幫你映射到實際位置。
要和朋友們在一個項目上協同工做,就得從新添加他們的公鑰。不過此次不用在服務器上一個一個手工添加到~/.ssh/authorized_keys 文件末端,而只需管理keydir 目錄中的公鑰文件。文件的命名將決定在 gitosis.conf 中對用戶的標識。如今咱們爲 John,Josie 和 Jessica 添加公鑰:
$ cp /tmp/id_rsa.john.pub keydir/john.pub $ cp /tmp/id_rsa.josie.pub keydir/josie.pub $ cp /tmp/id_rsa.jessica.pub keydir/je
而後把他們都加進 ‘mobile’ 團隊,讓他們對 iphone_project 具備讀寫權限:
[group mobile] writable = iphone_project members = scott john josie jessica
若是你提交併推送這個修改,四個用戶將同時具備該項目的讀寫權限。
Gitosis 也具備簡單的訪問控制功能。若是想讓 John 只有讀權限,能夠這樣作:
[group mobile] writable = iphone_project members = scott josie jessica [group mobile_ro] readonly = iphone_project members = john
如今 John 能夠克隆和獲取更新,但 Gitosis 不會容許他向項目推送任何內容。像這樣的組能夠隨意建立,多少不限,每一個均可以包含若干不一樣的用戶和項目。甚至還能夠指定某個組爲成員之一(在組名前加上@ 前綴),自動繼承該組的成員:
[group mobile_committers] members = scott josie jessica [group mobile] writable = iphone_project members = @mobile_committers
若是遇到意外問題,試試看把 loglevel=DEBUG 加到 [gitosis] 的段落(譯註:把日誌設置爲調試級別,記錄更詳細的運行信息。)。若是一不當心搞錯了配置,失去了推送權限,也能夠手工修改服務器上的/home/git/.gitosis.conf 文件 — Gitosis 實際是從該文件讀取信息的。它在獲得推送數據時,會把新的 gitosis.conf 存到該路徑上。因此若是你手工編輯該文件的話,它會一直保持到下次向 gitosis-admin 推送新版本的配置內容爲止。
對於提供公共的,非受權的只讀訪問,咱們能夠拋棄 HTTP 協議,改用 Git 本身的協議,這主要是出於性能和速度的考慮。Git 協議遠比 HTTP 協議高效,於是訪問速度也快,因此它能節省不少用戶的時間。
重申一下,這一點只適用於非受權的只讀訪問。若是建在防火牆以外的服務器上,那麼它所提供的服務應該只是那些公開的只讀項目。若是是在防火牆以內的 服務器上,可用於支撐大量參與人員或自動系統(用於持續集成或編譯的主機)只讀訪問的項目,這樣能夠省去逐一配置 SSH 公鑰的麻煩。
但無論哪一種情形,Git 協議的配置設定都很簡單。基本上,只要以守護進程的形式運行該命令便可:
git daemon --reuseaddr --base-path=/opt/git/ /opt/git/
這裏的 --reuseaddr 選項表示在重啓服務前,不等以前的鏈接超時就當即重啓。而 --base-path 選項則容許克隆項目時沒必要給出完整路徑。最後面的路徑告訴 Git 守護進程容許開放給用戶訪問的倉庫目錄。假若有防火牆,則須要爲該主機的 9418 端口設置爲容許通訊。
以守護進程的形式運行該進程的方法有不少,但主要還得看用的是什麼操做系統。在 Ubuntu 主機上,能夠用 Upstart 腳本達成。編輯該文件:
/etc/event.d/local-git-daemon
加入如下內容:
start on startup stop on shutdown exec /usr/bin/git daemon \ --user=git --group=git \ --reuseaddr \ --base-path=/opt/git/ \ /
出於安全考慮,強烈建議用一個對倉庫只有讀取權限的用戶身份來運行該進程 — 只須要簡單地新建一個名爲 git-ro 的用戶(譯註:新建用戶默認對倉庫文件不具有寫權限,但這取決於倉庫目錄的權限設定。務必確認git-ro 對倉庫只能讀不能寫。),並用它的身份來啓動進程。這裏爲了簡化,後面咱們仍是用以前運行 Gitosis 的用戶 ‘git’。
這樣一來,當你重啓計算機時,Git 進程也會自動啓動。要是進程意外退出或者被殺掉,也會自行重啓。在設置完成後,不重啓計算機就啓動該守護進程,能夠運行:
initctl start local-git-daemon
而在其餘操做系統上,能夠用 xinetd,或者 sysvinit 系統的腳本,或者其餘相似的腳本 — 只要能讓那個命令變爲守護進程並可監控。
接下來,咱們必須告訴 Gitosis 哪些倉庫容許經過 Git 協議進行匿名只讀訪問。若是每一個倉庫都設有各自的段落,能夠分別指定是否容許 Git 進程開放給用戶匿名讀取。好比容許經過 Git 協議訪問 iphone_project,能夠把下面兩行加到gitosis.conf 文件的末尾:
[repo iphone_project] daemon = yes
在提交和推送完成後,運行中的 Git 守護進程就會響應來自 9418 端口對該項目的訪問請求。
若是不考慮 Gitosis,單單起了 Git 守護進程的話,就必須到每個容許匿名只讀訪問的倉庫目錄內,建立一個特殊名稱的空文件做爲標誌:
$ cd /path/to/project.git $ touch git-daemon-export-ok
該文件的存在,代表容許 Git 守護進程開放對該項目的匿名只讀訪問。
Gitosis 還能設定哪些項目容許放在 GitWeb 上顯示。先打開 GitWeb 的配置文件 /etc/gitweb.conf,添加如下四行:
$projects_list = "/home/git/gitosis/projects.list"; $projectroot = "/home/git/repositories"; $export_ok = "git-daemon-export
接下來,只要配置各個項目在 Gitosis 中的 gitweb 參數,便能達成是否容許 GitWeb 用戶瀏覽該項目。好比,要讓 iphone_project 項目在 GitWeb 裏出現,把repo 的設定改爲下面的樣子:
[repo iphone_project] daemon = yes gitweb = yes
在提交併推送過以後,GitWeb 就會自動開始顯示 iphone_project 項目的細節和歷史。