歡迎光臨
每天分享高質量文章

搭建自己的 Git 服務器

根據 RhodeCode[1] 在 2016 年做過的一項分析報告 Version Control Systems Popularity in 2016[2],在如今的 VCS(版本控制系統)領域,Git 幾乎已經一統江山,在選擇自己的 VCS 時,有 87% 的人會選擇使用 Git,排在第二名的 SVN 只占 6%,無論是從 Google Trends,還是在 Stack Overflow 上的提問,都可以看到 Git 的爆髮式增長。另外,根據 Eclipse 的社區調查 (Eclipse Community Survey),在 2010 年前後,SVN 的使用率都遠超其他幾款 VCS,從 2010 年開始,SVN 的使用率開始快速下滑,相應的,Git 的使用率快速上升,併在 2014 年超過了 SVN。 
現在,Git 已經成為了程式員的必備技能,越來越多的企業開始採用 Git。在開源的世界里,GitHub 是程式員聚集的狂歡之地,但這並不適合企業的私有專案,雖然 GitHub 也支持創建私有專案,但是搭建一個自己的 Git 服務器在很多時候可能是更好的選擇,這篇博客將介紹並學習幾種搭建 Git 服務器的方法。
Git 支持四種不同的傳輸協議:本地協議(Local)、HTTP(S) 協議、SSH(Secure Shell)協議以及 Git 協議,這四種協議在不同的場合有不同的用途,並且各有利弊,可以根據實際情況來選擇。
一、本地協議

 

本地協議是 Git 最基本的協議,當我們想在本地做一些 Git 實驗時,這將非常有用。我們首先建立兩個目錄:/git/repo 和 ~/working,前者作為遠程版本庫,後者作為本地工作目錄。
  1. [email protected]-stone:~$ sudo mkdir -p /git/repo
  2. [email protected]-stone:~$ sudo git init --bare /git/repo/test.git
  3. 已初始化空的 Git 倉庫於 /git/repo/test.git/
我們在 /git/repo 目錄通過 git init –bare 命令創建一個裸倉庫(bare repository,即一個不包含當前工作目錄的倉庫),只要這一步,我們就可以開始使用了。接著我們在工作目錄 clone 這個版本庫:
  1. [email protected]-stone:~$ cd ~/working/
  2. [email protected]-stone:~/working$ git clone /git/repo/test.git
  3. 正克隆到 'test'...
  4. warning: 您似乎克隆了一個空倉庫。
  5. 完成。
然後我們可以使用 pull、push 就像操作其他的版本庫一樣。
  1. [email protected]-stone:~/working$ cd test/
  2. [email protected]-stone:~/working/test$ touch 1
  3. [email protected]-stone:~/working/test$ touch 2
  4. [email protected]-stone:~/working/test$ git add .
  5. [email protected]-stone:~/working/test$ git commit -m 'first commit'
  6. [master (根提交) 4983f84] first commit
  7. 2 files changed, 0 insertions(+), 0 deletions(-)
  8. create mode 100644 1
  9. create mode 100644 2
  10. [email protected]-stone:~/working/test$ sudo git push
  11. [sudo] aneasystone 的密碼:
  12. 物件計數中: 3, 完成.
  13. Delta compression using up to 8 threads.
  14. 壓縮物件中: 100% (2/2), 完成.
  15. 寫入物件中: 100% (3/3), 205 bytes | 205.00 KiB/s, 完成.
  16. Total 3 (delta 0), reused 0 (delta 0)
  17. To /git/repo/test.git
  18. * [new branch]      master -> master
本地協議不僅在做 Git 實驗時很有用,如果你的團隊有一個共享檔案系統,可以在這個共享檔案系統上創建一個遠程版本庫,團隊成員把這個共享檔案系統掛在本地,就可以直接使用本地協議進行協作開發,完全不需要搭建一臺專門的 Git 服務器。
二、SSH 協議

 

本地協議雖然簡單,但是一般來說並不適用,因為你無法控制用戶對共享檔案系統的操作,用戶擁有 push 權限也就意味著用戶對遠程目錄擁有完整的 Shell 權限,他們有可能會無意甚至有意的修改或刪除 Git 內部檔案,損壞 Git 倉庫。
更安全的做法是使用專門的 Git 服務器,如果你有一臺可以使用 SSH 連接的服務器,搭建 Git 服務將會非常簡單。首先我們要確保服務器上運行著 SSH 服務(sshd),大多數 Linux 服務器版本都預設包含了該服務,如果沒有,可以先安裝 openssh-server。然後在服務器上創建 Git 遠程版本庫:
  1. [email protected]:~# mkdir -p /git/repo
  2. [email protected]:~# git init --bare /git/repo/test.git
  3. 已初始化空的 Git 倉庫於 /git/repo/test.git/
然後在本地 clone 這個版本庫:
  1. [email protected]-stone:~/working$ git clone ssh://[email protected]/git/repo/test.git
  2. 正克隆到 'test'...
  3. [email protected]'s password:
  4. warning: 您似乎克隆了一個空倉庫。
可以看到和使用本地協議幾乎一樣,不同的地方在於,在 clone 的時候需要在 URL 前面加上 ssh://[email protected],你也可以使用 scp 式的寫法:
  1. $ git clone [email protected]:/git/repo/test.git
另外一點不同的地方是,每次 pull、push 的時候都需要輸入遠程服務器的 root 密碼。很顯然,讓每個 Git 用戶都使用 root 來訪問服務器是一種很不安全的做法,有幾種方法可以解決這個問題:
  • 最顯而易見的方法是為每個 Git 用戶創建一個獨立的賬號,並分別為他們分配對倉庫的讀寫權限,這種方法行的通,但是對賬號的管理非常麻煩,在團隊人員不是很多的時候可以嘗試,但是並不推薦;

  • 另一種方法是配置 SSH 服務器使用某個已有的認證系統來管理用戶,比如 LDAP,這在很多企業中是很常見的,這樣可以省去用 adduser 手工管理服務器賬號的麻煩;

  • 還有一種方法是只創建一個賬號,比如叫做 Git,他對倉庫具有讀寫權限,大家都使用這個賬號來訪問倉庫。這種方法的好處是用戶管理起來比較簡單,而且可以使用後面介紹的 authorized_keys 檔案對用戶的公鑰進行管理。

 

下麵我們嘗試下第三種方法。首先在服務器上創建一個名叫 Git 的賬號:
  1. [email protected]:~# adduser git
  2. Adding user `git' ...
  3. Adding new group `git' (1000) ...
  4. Adding new user `git' (1000) with group `git' ...
  5. Creating home directory `/home/git' ...
  6. Copying files from `/etc/skel' ...
  7. Enter new UNIX password:
  8. Retype new UNIX password:
  9. passwd: password updated successfully
  10. Changing the user information for git
  11. Enter the new value, or press ENTER for the default
  12.    Full Name []: git
  13.    Room Number []:  
  14.    Work Phone []:
  15.    Home Phone []:
  16.    Other []:
  17. Is the information correct? [Y/n] Y
再設置一下 Git 倉庫的權限(預設情況下,Git 倉庫的權限為 rwxr-xr-x,只有創建者 root 有寫的權限,也就意味著使用 Git 賬號只能 clone pull,不能 push):
  1. # chmod a+w -R /git/repo/test.git
我們這裡非常粗暴的使用 chmod a+w 將 Git 倉庫設置為對所有人可寫,這裡可以想一想,如果我們希望設置某些用戶對倉庫具有隻讀的權限,該怎麼做呢?
然後就可以在本地愉快的進行 Git 操作了:
  1. $ git clone [email protected]:/git/repo/test.git
到這裡似乎一切都很正常,但是幾次實操之後你就會發現,每次 Git 操作都要輸入一次密碼,這也太麻煩了,能不能“免密提交代碼”呢?首先我們要知道,只要能通過 SSH 登陸到服務器,我們就能操作 Git,所以如果 SSH 能支持免密登陸,我們就可以“免密提交代碼”。還好,SSH 支持公鑰認證,這種認證方式無需密碼登陸。在 Linux 操作系統中,每個用戶都可以擁有自己的一個或多個密鑰對(公鑰和私鑰成對出現),這些密鑰一般情況會儲存在 ~/.ssh 目錄下,在開始之前,我們先確認下自己是否已經生成過公鑰了,可以看下這個目錄下是否有 iddsa.pub 或 idrsa.pub 這樣的檔案,如果沒有,我們通過 ssh-keygen 來生成:
  1. [email protected]-stone:~/.ssh$ ssh-keygen
  2. Generating public/private rsa key pair.
  3. Enter file in which to save the key (/home/aneasystone/.ssh/id_rsa):
  4. Enter passphrase (empty for no passphrase):
  5. Enter same passphrase again:
  6. Your identification has been saved in /home/aneasystone/.ssh/id_rsa.
  7. Your public key has been saved in /home/aneasystone/.ssh/id_rsa.pub.
  8. The key fingerprint is:
  9. SHA256:4Ulpufuhs/AgDMb0VXnqMUTw6bD/HrAOI2z9c1cod9I [email protected]-stone
  10. The key's randomart image is:
  11. +---[RSA 2048]----+
  12. |      .oo.       |
  13. |       oo+.      |
  14. |  .   o.Oo       |
  15. | o . . B++       |
  16. |  + . ..So   o   |
  17. | . + . ..+. + E  |
  18. |    * * + oo +   |
  19. |   . o Oo+.o.    |
  20. |        **+.     |
  21. +----[SHA256]-----+
這樣我們在 ~/.ssh 目錄生成了兩個檔案,idrsa 是你的私鑰,idrsa.pub 是你的公鑰。關於私鑰和公鑰的原理以及 RSA 加密演算法等內容可以參考我之前寫過的一篇介紹 HTTPS 和證書[3]的文章。
我們假設你的 Git 服務器是由專門的服務器管理員負責維護和管理,當你生成你的公鑰之後,就可以給服務器管理員發送一封申請 Git 服務的郵件,並附上你的公鑰。服務器管理員在收到你的申請之後,如果同意了,就可以進行下麵的操作:
首先將公鑰檔案拷貝到服務器上:
  1. # scp id_rsa.pub [email protected]:/home/git
將公鑰檔案的內容追加到 Git 賬戶的 authorizedkeys 檔案中(要註意的是,如果是第一次操作,/home/git 目錄下是沒有 .ssh 目錄的,需要手工創建 .ssh 目錄和 authorizedkeys 檔案):
  1. [email protected]:/home/git# cat id_rsa.pub >> /home/git/.ssh/authorized_keys
後續如果有其他的用戶申請 Git 服務,都可以按照這個步驟操作。一旦完成這個操作,服務器管理員將會回覆你的郵件,通知你 Git 服務已經開通,這個時候你再進行 Git 操作就可以不用輸入密碼了。關於 SSH 的使用,更詳細的步驟可以參考 GitHub 上的這篇指南:Connecting to GitHub with SSH[4]。
作為服務器管理員,關於 SSH 還有一點需要考慮,那就是 SSH 的安全問題。在上面介紹本地協議時,我們說這種方式無法控制用戶對 Git 倉庫的操作,無法防止用戶有意或無意的損壞 Git 倉庫,使用 SSH 協議一樣存在這樣的問題,用戶能通過 SSH 拉取和提交代碼,也就意味著用戶可以通過 SSH 連接到服務器,對 Git 倉庫進行任何操作,這是一件很讓人擔心的事情。
因此,我們還需要對 Git 賬號做一些限制。預設情況下,我們新建賬號的登陸 shell 是 /bin/bash,這個配置在 /etc/passwd 檔案中:
  1. git:x:1000:1000:git,,,:/home/git:/bin/bash
可以使用 chsh 命令修改用戶的登陸 shell,讓他不能通過 SSH 訪問服務器,怎麼修改呢?我們可以看一下 /etc/shells 檔案,這裡定義了所有可以使用的登陸 shell,你可以將 /bin/bash 改成這裡的任何一個:
  1. [email protected]:~# cat /etc/shells
  2. # /etc/shells: valid login shells
  3. /bin/sh
  4. /bin/dash
  5. /bin/bash
  6. /bin/rbash
很顯然,這些 shell 並不是我們想要的,有沒有一個 shell 只允許用戶進行 Git 操作,而不允許其他操作呢?還好,Git 的軟體包提供了一個名叫 git-shell 的登陸 shell,我們可以把他加進去,一般情況下位於 /usr/bin/git-shell。我們使用 chsh 修改 Git 的登陸 shell:
  1. [email protected]:~# chsh git
  2. Changing the login shell for git
  3. Enter the new value, or press ENTER for the default
  4.    Login Shell [/bin/bash]: /usr/bin/git-shell
這樣當用戶 Git 通過 SSH 連接服務器時,就會直接被拒絕了。
三、Git 協議

 

SSH 協議解決了用戶直接操作 Git 倉庫的權限問題,但是如果我們希望對除倉庫維護者之外的所有人都開放 Git 倉庫的只讀權限,這在開源專案中和企業內部往往是很常見的,任何人都可以去查看倉庫的代碼,這時管理員需要給每一個用戶配置 SSH 密鑰是非常麻煩的。雖然也可以使用變通的方法來達到這個效果,但是很繁瑣,下麵是具體的步驟:
  • 使用 g+w 設置 Git 倉庫的權限,讓倉庫創建者所在的用戶組具有寫權限,而不是所有人都有寫權限(這一步通常也可以在 git init 的時候加上 –shared 引數);

  • 然後將 Git 賬號加到倉庫創建者的用戶組;

  • 再創建一個 git_ro 賬戶,這個賬戶對倉庫只有隻讀權限;

  • 最後為 gitro 賬戶創建一個密鑰對,把 gitro 的私鑰公開出來供所有人使用。

可以看到使用 SSH 協議最終都逃不過授權這一步,而且公開私鑰的做法也不是很優雅。實際上,Git 提供了另一種方式來讓這個操作更簡單,那就是 Git 協議。使用 Git 協議必須要在服務器上運行 Git 守護行程,Git 命令自帶了一個 daemon 引數:
  1. [email protected]:~# git daemon --reuseaddr --base-path=/git/repo/ /git/repo/
上面的各個引數可以 參考 git-daemon[5] 的文件。git-daemon 會監聽 9418 端口,如果你的服務器有防火牆,需要將該端口添加到白名單,如果你使用的是阿裡雲服務器,需要像下麵這樣添加一個安全組規則: 
為了讓所有的用戶都可以訪問我們的倉庫,還需要在倉庫目錄下創建一個名為 git-daemon-export-ok 的檔案:
  1. [email protected]:~# cd /git/repo/test.git/
  2. [email protected]:/git/repo/test.git/# touch git-daemon-export-ok
至此,所有人都可以通過 Git 協議來克隆或拉取專案原始碼了(註意上面指定了 base-path 引數為 /git/repo/,所以 URL 可以直接寫 git://myserver/test.git):
  1. [email protected]-stone:~/working$ git clone git://myserver/test.git
一般情況下,服務器管理員還會做一些其他的配置,譬如在服務器重啟時讓 Git 守護行程自動啟動,這有很多種方式可以實現,可以參考《Pro Git[6]》 Git 守護行程這一節的內容。
四、HTTP(S) 協議

 

我們一般通過 Git 協議進行無授權訪問,通過 SSH 協議進行授權訪問,如果你的專案是內部專案,只針對部分授權用戶,那使用 SSH 協議就足夠了,但是如果既需要授權訪問也需要無授權訪問,可能需要 SSH 協議和 Git 協議搭配使用,這在維護上成本很高。這時就到了我們的壓軸戲 —— HTTP 協議出場的時候了,它同時支持上面兩種訪問方式。
通過 HTTP 協議訪問 Git 服務是目前使用最廣泛的方式,它支持兩種樣式:舊版本的 Dumb HTTP 和 新版本的 Smart HTTP,Dumb HTTP 一般很少使用,下麵除非特殊說明,所說的 HTTP 協議都是 Smart HTTP。使用 HTTP 協議的好處是可以使用各種 HTTP 認證機制,比如用戶名/密碼,這比配置 SSH 密鑰要簡單的多,對普通用戶來說也更能接受。如果擔心資料傳輸安全,也可以配置 HTTPS 協議,這和普通的 Web 服務是一樣的。
下麵我們就來嘗試搭建一個基於 HTTP 協議的 Git 服務器。《Pro Git》上提供了一個基於 Apache 的配置示例,如果你是使用 Apache 作為 Web 服務器,可以參考之,我們這裡使用 Nginx 來作為 Web 服務器,其原理本質上是一樣的,都是通過 Web 服務器接受 HTTP 請求,並將請求轉發到 Git 自帶的一個名為 git-http-backend 的 CGI 腳本。
首先我們安裝所需的軟體:
  1. # apt-get install -y git-core nginx fcgiwrap apache2-utils
其中,Nginx 作為 Web 服務器,本身是不能執行外部 CGI 腳本的,需要通過 FcgiWrap來中轉,就像使用 php-fpm 來執行 PHP 腳本一樣。apache2-utils 是 Apache 提供的一個 Web 服務器的工具集,包含了一些有用的小工具,譬如下麵我們會用到的 htpasswd 可以生成 Basic 認證檔案。
啟動 Nginx 和 FcgiWrap,並訪問 http://myserver 測試 Web 服務器是否能正常訪問:
  1. # service nginx start
  2. # service fcgiwrap start
然後我們打開並編輯 Nginx 的配置檔案(/etc/nginx/sites-available/default):
  1. location / {
  2.        include fastcgi_params;
  3.        fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
  4.        fastcgi_param GIT_HTTP_EXPORT_ALL "";
  5.        fastcgi_param GIT_PROJECT_ROOT /git/repo;
  6.        fastcgi_param PATH_INFO $uri;
  7.        fastcgi_param REMOTE_USER $remote_user;
  8.        fastcgi_pass unix:/var/run/fcgiwrap.socket;
  9. }
這裡通過 fastcgi_param 設置了一堆的 FastCGI 引數,如下:
  • SCRIPT_FILENAME:指定 CGI 腳本 git-http-backend 的位置,表示每次 HTTP 請求會被轉發到該 CGI 腳本;

  • GITHTTPEXPORTALL:git-http-backend 預設只能訪問目錄下有 git-daemon-export-ok 檔案的 Git 倉庫,和上面介紹的 Git 協議是一樣的,如果指定了 GITHTTPEXPORTALL,表示允許訪問所有倉庫;

  • GITPROJECTROOT:Git 倉庫的根目錄;

  • REMOTE_USER:如果有認證,將認證的用戶信息傳到 CGI 腳本;

改完之後我們重啟 Nginx,並通過 HTTP 協議 clone 倉庫:
  1. [email protected]-stone:~/working$ git clone http://myserver/test.git
4.1 開啟身份認證
到這裡一切 OK,但是當我們 push 代碼的時候,卻會報下麵的 403 錯誤:
  1. [email protected]-stone:~/working/test$ git push origin master
  2. fatal: unable to access 'http://myserver/test.git/': The requested URL returned error: 403
為瞭解決這個錯誤,我們可以在 git-http-backend 的官網文件上找到這樣的一段描述:
By default, only the upload-pack service is enabled, which serves git fetch-pack and git ls-remote clients, which are invoked from git fetch, git pull, and git clone. If the client is authenticated, the receive-pack service is enabled, which serves git send-pack clients, which is invoked from git push.
第一次讀這段話可能會有些不知所云,這是因為我們對這裡提到的 upload-pack、fetch-pack、receive-pack、send-pack 這幾個概念還沒有什麼認識。但是我們大抵可以猜出來,預設情況下,只有認證的用戶才可以 push 代碼,如果某個 Git 倉庫希望所有用戶都有權限 push 代碼,可以為相應的倉庫設置 http.receivepack:
  1. [email protected]:/# cd /git/repo/test.git/
  2. [email protected]:/git/repo/test.git# git config http.receivepack true
當然最好的做法還是對 push 操作開啟認證,官網文件上有一個 lighttpd 的配置我們可以借鑒:
  1. $HTTP["querystring"] =~ "service=git-receive-pack" {
  2.    include "git-auth.conf"
  3. }
  4. $HTTP["url"] =~ "^/git/.*/git-receive-pack$" {
  5.    include "git-auth.conf"
  6. }
這個配置看上去非常簡單,但是想要理解為什麼這樣配置,就必須去瞭解下 Git 的內部原理。正如上面 git-http-backend 文件上的那段描述,當 Git 客戶端執行 git fetch,git pull,and git clone 時,會呼叫 upload-pack 服務,當執行 git push 時,會呼叫 receive-pack 服務,為了更清楚的說明這一點,我們來看看 Nginx 的訪問日誌。
執行 git clone:
  1. [27/Nov/2018:22:18:00] "GET /test.git/info/refs?service=git-upload-pack HTTP/1.1" 200 363 "-" "git/1.9.1"
  2. [27/Nov/2018:22:18:00] "POST /test.git/git-upload-pack HTTP/1.1" 200 306 "-" "git/1.9.1"
執行 git pull:
  1. [27/Nov/2018:22:20:25] "GET /test.git/info/refs?service=git-upload-pack HTTP/1.1" 200 363 "-" "git/1.9.1"
  2. [27/Nov/2018:22:20:25] "POST /test.git/git-upload-pack HTTP/1.1" 200 551 "-" "git/1.9.1"
執行 git push:
  1. [27/Nov/2018:22:19:33] "GET /test.git/info/refs?service=git-receive-pack HTTP/1.1" 401 204 "-" "git/1.9.1"
  2. admin [27/Nov/2018:22:19:33] "GET /test.git/info/refs?service=git-receive-pack HTTP/1.1" 200 193 "-" "git/1.9.1"
  3. admin [27/Nov/2018:22:19:33] "POST /test.git/git-receive-pack HTTP/1.1" 200 63 "-" "git/1.9.1"
可以看到執行 clone 和 pull 請求的接口是一樣的,先請求 /info/refs?service=git-upload-pack,然後再請求 /git-upload-pack;而 push 是先請求 /info/refs?service=git-receive-pack,然後再請求 /git-receive-pack,所以在上面的 lighttpd 的配置中我們看到了兩條記錄,如果要對 push 做訪問控制,那麼對這兩個請求都要限制。關於 Git 傳輸的原理可以參考 《Pro Git》的 Git 內部原理 – 傳輸協議這一節。
我們依葫蘆畫瓢,Nginx 配置檔案如下:
  1. location @auth {
  2.        auth_basic "Git Server";
  3.        auth_basic_user_file /etc/nginx/passwd;
  4.        include fastcgi_params;
  5.        fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
  6.        fastcgi_param GIT_HTTP_EXPORT_ALL "";
  7.        fastcgi_param GIT_PROJECT_ROOT /git/repo;
  8.        fastcgi_param PATH_INFO $uri;
  9.        fastcgi_param REMOTE_USER $remote_user;
  10.        fastcgi_pass unix:/var/run/fcgiwrap.socket;
  11. }
  12. location / {
  13.        error_page 418 = @auth;
  14.        if ( $query_string = "service=git-receive-pack" ) {  return 418; }
  15.        if ( $uri ~ "git-receive-pack$" ) { return 418; }
  16.        include fastcgi_params;
  17.        fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
  18.        fastcgi_param GIT_HTTP_EXPORT_ALL "";
  19.        fastcgi_param GIT_PROJECT_ROOT /git/repo;
  20.        fastcgi_param PATH_INFO $uri;
  21.        fastcgi_param REMOTE_USER $remote_user;
  22.        fastcgi_pass unix:/var/run/fcgiwrap.socket;
  23. }
其中相同的配置我們也可以用 include 指令放在一個共用的配置檔案里,這樣我們就實現了在 push 的時候需要填寫用戶名和密碼了。我們通過 Nginx 的 authbasicuser_file 指令來做身份認證,用戶名和密碼儲存在 /etc/nginx/passwd 檔案中,這個檔案可以使用上面提到的 apache2-utils 包里的 htpasswd 來生成:
  1. [email protected]:/# htpasswd -cb /etc/nginx/passwd admin 123456
另外,在 push 的時候,有時候可能會遇到 unpack failed: unable to create temporary object directory 這樣的提示錯誤:
  1. [email protected]-stone:~/working/test$ git push origin master
  2. Counting objects: 3, done.
  3. Writing objects: 100% (3/3), 193 bytes | 0 bytes/s, done.
  4. Total 3 (delta 0), reused 0 (delta 0)
  5. error: unpack failed: unable to create temporary object directory
  6. To http://myserver/test.git
  7. ! [remote rejected] master -> master (unpacker error)
  8. error: failed to push some refs to 'http://myserver/test.git'
這一般情況下都是由於 Git 倉庫目錄的權限問題導致的,在這裡 Git 倉庫的根目錄 /git/repo 是 root 創建的,而運行 nginx 和 fcgiwrap 的用戶都是 www-data,我們可以把 Git 倉庫目錄設置成對所有人可讀可寫,也可以像下麵這樣將它的擁有者設置成 www-data 用戶:
  1. [email protected]:/# chown -R www-data:www-data /git/repo
4.2 憑證管理
上面我們站在管理員的角度解決了用戶身份認證的問題,但是站在用戶的角度,每次提交代碼都要輸入用戶名和密碼是一件很痛苦的事情。在上面介紹 SSH 協議時,我們可以使用 SSH 協議自帶的公鑰認證機制來省去輸入密碼的麻煩,那麼在 HTTP 協議中是否存在類似的方法呢?答案是肯定的,那就是 Git 的憑證儲存工具:credential.helper。
譬如像下麵這樣,將用戶名和密碼信息儲存在快取中:
  1. $ git config --global credential.helper cache
這種方式預設只保留 15 分鐘,如果要改變保留的時間,可以通過 –timeout 引數設置,或者像下麵這樣,將密碼儲存在檔案中:
  1. $ git config --global credential.helper store
這種方式雖然可以保證密碼不過期,但是要記住的是,這種方式密碼是以明文的方式儲存在你的 home 目錄下的。可以借鑒操作系統自帶的憑證管理工具來解決這個問題, 比如 OSX Keychain 或者 Git Credential Manager for Windows。更多的內容可以參考《Pro Git》憑證儲存這一節。
除此之外,還有一種更簡單粗暴的方式:
  1. [email protected]-stone:~/working$ git clone http://admin:[email protected]/test.git
五、綜合對比

 

這一節對 Git 的四大協議做一個綜合對比。
本地協議
  • 優點:架設簡單,不依賴外部服務,直接使用現有檔案和網絡權限,常用於共享檔案系統

  • 缺點:共享檔案系統的配置和使用不方便,且無法保護倉庫被意外損壞,傳輸性能較低

SSH 協議
  • 優點:架設簡單,所有資料經過授權加密,資料傳輸很安全,傳輸性能很高

  • 缺點:不支持匿名訪問,配置 SSH 的密鑰對小白用戶有一定的門檻

Git 協議
  • 優點:對開放的專案很適用,無需授權,傳輸性能最高

  • 缺點:缺乏授權機制,架設較麻煩,企業一般不會預設開放 9418 端口需要另行添加

HTTP/S 協議
  • 優點:同時支持授權訪問和無授權訪問,傳輸性能較高,配合 HTTPS 也可以實現資料安全

  • 缺點:架設 HTTP 服務較麻煩,認證憑證不好管理

六、更高級的工具

 

上面介紹的是搭建 Git 服務器最基本的方法,如果你只是希望能找一個版本控制系統來替代現有的 SVN,這也許就足夠了。但如果你希望你的版本控制系統能擁有一個更友好的 UI 界面,能更好的管理你的用戶和權限,能支持更現代的 Pull Request 功能以及能和 CI/CD 系統更緊密的聯繫起來,你就需要一個更高級的工具,你可以試試 GitWeb、Gitolite、GitLab、Gogs、Gitea,當然,如果你願意,你也可以把代碼放在那些流行的代碼托管平臺上,比如 GitHub 等等。
相關鏈接:
  1. https://rhodecode.com/

  2. https://rhodecode.com/insights/version-control-systems-2016

  3. http://www.aneasystone.com/archives/2016/04/java-and-https.html

  4. https://help.github.com/articles/connecting-to-github-with-ssh/

  5. https://git-scm.com/docs/git-daemon

  6. https://git-scm.com/book/zh/v2

     

原文鏈接:https://www.aneasystone.com/archives/2018/12/build-your-own-git-server.html

赞(0)

分享創造快樂