Ubuntu 搭建簡單的git server

簡介

Git 可使用四種主要的協議來傳輸資料:html

  1. 本地協議(Local):
      最基本的就是 本地協議(Local protocol), 其中的遠程版本庫就是硬盤內的另外一個目錄。 這常見於團隊每個成員都對一個共享的文件系統(例如一個掛載的 NFS)擁有訪問權,或者比較少見的多人共用同一臺電腦的狀況。 後者並不理想,由於你的全部代碼版本庫若是長存於同一臺電腦,更可能發生災難性的損失。
      若是你使用共享文件系統,就能夠從本地版本庫克隆(clone)、推送(push)以及拉取(pull)。 像這樣去克隆一個版本庫或者增長一個遠程到現有的項目中,使用版本庫路徑做爲 URL。 例如,克隆一個本地版本庫,能夠執行以下的命令:
    shell git clone /opt/git/project.git 或 git clone file:///opt/git/project.git
       若是在 URL 開頭明確的指定 file://,那麼 Git 的行爲會略有不一樣。 若是僅是指定路徑,Git 會嘗試使用硬連接(hard link)或直接複製所須要的文件。
       若是指定 file://,Git 會觸發平時用於網路傳輸資料的進程,那一般是傳輸效率較低的方法。 指定 file:// 的主要目的是取得一個沒有外部參考(extraneous references)或對象(object)的乾淨版本庫副本– 一般是在從其餘版本控制系統導入後或一些相似狀況(參見 Git 內部原理 for maintenance tasks)須要這麼作。 在此咱們將使用普通路徑,由於這樣一般更快。
       要增長一個本地版本庫到現有的 Git 項目,能夠執行以下的命令:
    shell git remote add local_proj /opt/git/project.git
       而後,就能夠像在網絡上同樣從遠端版本庫推送和拉取更新了。
       優勢: 基於文件系統的版本庫的優勢是簡單,而且直接使用了現有的文件權限和網絡訪問權限。 若是你的團隊已經有共享文件系統,創建版本庫會十分容易。 只須要像設置其餘共享目錄同樣,把一個裸版本庫的副本放到你們均可以訪問的路徑,並設置好讀/寫的權限,就能夠了, 咱們會在 在服務器上搭建 Git 討論如何導出一個裸版本庫。
       這也是快速從別人的工做目錄中拉取更新的方法。 若是你和別人一塊兒合做一個項目,他想讓你從版本庫中拉取更新時,運行相似 git pull /home/john/project 的命令比推送到服務再取回簡單多了。
       缺點: 這種方法的缺點是,一般共享文件系統比較難配置,而且比起基本的網絡鏈接訪問,這不方便從多個位置訪問。 若是你想從家裏推送內容,必須先掛載一個遠程磁盤,相比網絡鏈接的訪問方式,配置不方便,速度也慢。
       值得一提的是,若是你使用的是相似於共享掛載的文件系統時,這個方法不必定是最快的。 訪問本地版本庫的速度與你訪問數據的速度是同樣的。 在同一個服務器上,若是容許 Git 訪問本地硬盤,通常的經過 NFS 訪問版本庫要比經過 SSH 訪問慢。
       最終,這個協議並不保護倉庫避免意外的損壞。 每個用戶都有「遠程」目錄的完整 shell 權限,沒有方法能夠阻止他們修改或刪除 Git 內部文件和損壞倉庫。linux

  2. HTTP 協議:
       Git 經過 HTTP 通訊有兩種模式。 在 Git 1.6.6 版本以前只有一個方式可用,十分簡單而且一般是隻讀模式的。 Git 1.6.6 版本引入了一種新的、更智能的協議,讓 Git 能夠像經過 SSH 那樣智能的協商和傳輸數據。 以後幾年,這個新的 HTTP 協議由於其簡單、智能變的十分流行。 新版本的 HTTP 協議通常被稱爲「智能」 HTTP 協議,舊版本的通常被稱爲「啞」 HTTP 協議。 咱們先了解一下新的「智能」 HTTP 協議。
       智能(Smart) HTTP 協議: 「智能」 HTTP 協議的運行方式和 SSH 及 Git 協議相似,只是運行在標準的 HTTP/S 端口上而且可使用各類 HTTP 驗證機制,這意味着使用起來會比 SSH 協議簡單的多,好比可使用 HTTP 協議的用戶名/密碼的基礎受權,免去設置 SSH 公鑰。
       智能 HTTP 協議或許已是最流行的使用 Git 的方式了,它即支持像 git:// 協議同樣設置匿名服務,也能夠像 SSH 協議同樣提供傳輸時的受權和加密。 並且只用一個 URL 就能夠都作到,省去了爲不一樣的需求設置不一樣的 URL。 若是你要推送到一個須要受權的服務器上(通常來說都須要),服務器會提示你輸入用戶名和密碼。 從服務器獲取數據時也同樣。
       事實上,相似 GitHub 的服務,你在網頁上看到的 URL (好比,https://github.com/schacon/simplegit[]),和你在克隆、推送(若是你有權限)時使用的是同樣的。
       啞(Dumb) HTTP 協議: 若是服務器沒有提供智能 HTTP 協議的服務,Git 客戶端會嘗試使用更簡單的「啞」 HTTP 協議。 啞 HTTP 協議裏 web 服務器僅把裸版本庫看成普通文件來對待,提供文件服務。 啞 HTTP 協議的優美之處在於設置起來簡單。 基本上,只須要把一個裸版本庫放在 HTTP 根目錄,設置一個叫作 post-update 的掛鉤就能夠了(見 Git 鉤子)。 此時,只要能訪問 web 服務器上你的版本庫,就能夠克隆你的版本庫。 下面是設置從 HTTP 訪問版本庫的方法:
    shell cd /var/www/htdocs/ git clone --bare /path/to/git_project gitproject.git cd gitproject.git mv hooks/post-update.sample hooks/post-update chmod a+x hooks/post-update
       這樣就能夠了。 Git 自帶的 post-update 掛鉤會默認執行合適的命令(git update-server-info),來確保經過 HTTP 的獲取和克隆操做正常工做。 這條命令會在你經過 SSH 向版本庫推送以後被執行;而後別人就能夠經過相似下面的命令來克隆:
    shell git clone https://example.com/gitproject.git
       這裏咱們用了 Apache 裏設置了經常使用的路徑 /var/www/htdocs,不過你可使用任何靜態 web 服務器 —— 只須要把裸版本庫放到正確的目錄下就能夠。 Git 的數據是以基本的靜態文件形式提供的(詳情見 Git 內部原理)。
       一般的,會在能夠提供讀/寫的智能 HTTP 服務和簡單的只讀的啞 HTTP 服務之間選一個。 極少會將兩者混合提供服務。
       優勢: 咱們將只關注智能 HTTP 協議的優勢。不一樣的訪問方式只須要一個 URL 以及服務器只在須要受權時提示輸入受權信息,這兩個簡便性讓終端用戶使用 Git 變得很是簡單。 相比 SSH 協議,可使用用戶名/密碼受權是一個很大的優點,這樣用戶就沒必要須在使用 Git 以前先在本地生成 SSH 密鑰對再把公鑰上傳到服務器。 對非資深的使用者,或者系統上缺乏 SSH 相關程序的使用者,HTTP 協議的可用性是主要的優點。 與 SSH 協議相似,HTTP 協議也很是快和高效。
       你也能夠在 HTTPS 協議上提供只讀版本庫的服務,如此你在傳輸數據的時候就能夠加密數據;或者,你甚至可讓客戶端使用指定的 SSL 證書。
       另外一個好處是 HTTP/S 協議被普遍使用,通常的企業防火牆都會容許這些端口的數據經過。
       缺點: 在一些服務器上,架設 HTTP/S 協議的服務端會比 SSH 協議的棘手一些。 除了這一點,用其餘協議提供 Git 服務與 「智能」 HTTP 協議相比就幾乎沒有優點了。
       若是你在 HTTP 上使用需受權的推送,管理憑證會比使用 SSH 密鑰認證麻煩一些。 然而,你能夠選擇使用憑證存儲工具,好比 OSX 的 Keychain 或者 Windows 的憑證管理器。 參考 憑證存儲 如何安全地保存 HTTP 密碼。git

  3. SSH(Secure Shell)協議
       架設 Git 服務器時經常使用 SSH 協議做爲傳輸協議。 由於大多數環境下已經支持經過 SSH 訪問 —— 即時沒有也比較很容易架設。 SSH 協議也是一個驗證受權的網絡協議;而且,由於其廣泛性,架設和使用都很容易。
       經過 SSH 協議克隆版本庫,你能夠指定一個 ssh:// 的 URL:
    shell git clone ssh://user@server/project.git
       或者使用一個簡短的 scp 式的寫法:
    shell git clone user@server:project.git
       你也能夠不指定用戶,Git 會使用當前登陸的用戶名。
       優點: 用 SSH 協議的優點有不少。 首先,SSH 架設相對簡單 —— SSH 守護進程很常見,多數管理員都有使用經驗,而且多數操做系統都包含了它及相關的管理工具。 其次,經過 SSH 訪問是安全的 —— 全部傳輸數據都要通過受權和加密。 最後,與 HTTP/S 協議、Git 協議及本地協議同樣,SSH 協議很高效,在傳輸前也會盡可能壓縮數據。github

      缺點: SSH 協議的缺點在於你不能經過他實現匿名訪問。 即使只要讀取數據,使用者也要有經過 SSH 訪問你的主機的權限,這使得 SSH 協議不利於開源的項目。 若是你只在公司網絡使用,SSH 協議多是你惟一要用到的協議。 若是你要同時提供匿名只讀訪問和 SSH 協議,那麼你除了爲本身推送架設 SSH 服務之外,還得架設一個可讓其餘人訪問的服務。web

  4. Git 協議
       接下來是 Git 協議。 這是包含在 Git 裏的一個特殊的守護進程;它監聽在一個特定的端口(9418),相似於 SSH 服務,可是訪問無需任何受權。 要讓版本庫支持 Git 協議,須要先建立一個 git-daemon-export-ok 文件 —— 它是 Git 協議守護進程爲這個版本庫提供服務的必要條件 —— 可是除此以外沒有任何安全措施。 要麼誰均可以克隆這個版本庫,要麼誰也不能。 這意味着,一般不能經過 Git 協議推送。 因爲沒有受權機制,一旦你開放推送操做,意味着網絡上知道這個項目 URL 的人均可以向項目推送數據。 不用說,極少會有人這麼作。
       優勢: 目前,Git 協議是 Git 使用的網絡傳輸協議裏最快的。 若是你的項目有很大的訪問量,或者你的項目很龐大而且不須要爲寫進行用戶受權,架設 Git 守護進程來提供服務是不錯的選擇。 它使用與 SSH 相同的數據傳輸機制,可是省去了加密和受權的開銷。
       缺點: Git 協議缺點是缺少受權機制。 把 Git 協議做爲訪問項目版本庫的惟一手段是不可取的。 通常的作法裏,會同時提供 SSH 或者 HTTPS 協議的訪問服務,只讓少數幾個開發者有推送(寫)權限,其餘人經過 git:// 訪問只有讀權限。 Git 協議也許也是最難架設的。 它要求有本身的守護進程,這就要配置 xinetd 或者其餘的程序,這些工做並不簡單。 它還要求防火牆開放 9418 端口,可是企業防火牆通常不會開放這個非標準端口。 而大型的企業防火牆一般會封鎖這個端口。
       這裏使用的是ssh協議,採用的是的gitcore搭建的,若是想搭建一個高端一點的(相似github,有web界面的)能夠點擊參考,裏面由關於gitweb和gitlab的介紹。

    shell

環境

服務端: ubuntu 14.04 、 gitcore 1.9.1
客戶端: ubuntu 16.04 、 git 2.7.4ubuntu

搭建過程

服務端

  1. 先建立一個帳戶用於操做git倉庫
    shell sudo adduser git #用戶名隨意叫,普通用戶便可
  2. 安裝git core
    shell sudo apt-get update && sudo apt-get upgrade && sudo apt-get install git-core
  3. 建立測試git倉庫
    shell su git #切換到git用戶,這樣接下來的建立的倉庫保證都是具備讀寫權限的 cd ~ && mkdir -p ~/github/test.git cd ~/github/test.git && git init --shared --bare #--bare 建立一個空倉庫 --shared 用於配置倉庫的訪問權限 ,咱們這裏採用默認配置,同屬於git group的人能夠訪問。
    此時會顯示:vim

    Initialized empty Git repository in /home/git/github/test.git

客戶端

  1. 生成用於ssh登陸的證書:安全

    ssh-keygen -t rsa #產生證書過程當中會有兩步提示,第一步讓你選擇文件保存位置,這一步直接回車;第二步讓你輸入私鑰保護密碼,建議設置密碼爲了安全。

    這時在home目錄下會產生一個.ssh的隱藏文件夾,裏面會產生一個 id_rsa 和 id_rsa.pub的公私鑰對.bash

  2. 上傳證書到服務器

    cat ~/.ssh/id_rsa.pub | ssh git@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" #server是你服務器的域名或者ip地址
  3. 登陸服務器(optional)
    shell  ssh git@server #若是在建立私鑰的時候輸入了保護密碼,此時會向你索取保護密碼

  4. 測試上傳代碼
    若是本地沒有已經存在的代碼:
    shell git clone git@server:~/git/github/test.git cd test touch README.md git add README.md git commit -a #提交代碼的時候會要求你寫入日誌,若是是採用的nano編輯器,寫入結束後按ctrl + x 保存退出 git push -u origin master
    若是你本地已經有寫好的代碼了則執行如下步驟:
    shell cd existing_dir git init git remote add origin git@server:~/git/github/test.git git add . git commit -a git push -u origin master
    注意: 當倉庫爲空時push操做沒法成功,會報出error: src refspec master does not match any 錯誤。

添加用戶

第一種

  1. 建立一個新的公私密鑰對,而後將公鑰添加到/home/git/.ssh/authorized_keys文件的末尾
    shell cat ~/.ssh/new.pub | ssh git@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" #server是你服務器的域名或者ip地址

  2. 而後將公私密鑰對分發給新用戶,放在新用戶本地的~/.ssh 文件夾下面便可。

  注: 已驗證

第二種

  1. 在服務端建立一個git group的用戶,而後爲其生成公私密鑰分發給新用戶用於ssh通訊

   注:待驗證

git shell 安全 (Optional)

   上面建立的git是一個普通用戶,可是仍然能夠登陸到服務器中,且對git倉庫具有操做權限,存在潛在風險,爲此咱們要限制它的能力。這能夠藉助一個名爲 git-shell 的受限 shell 工具,你能夠方便地將用戶 git 的活動限制在與 Git 相關的範圍內。該工具隨 Git 軟件包一同提供。

   若是將 git-shell 設置爲用戶 git 的登陸 shell(login shell),那麼用戶 git 便不能得到此服務器的普通 shell 訪問權限。 若要使用 git-shell,須要用它替換掉 bash 或 csh,使其成爲系統用戶的登陸 shell。 爲進行上述操做,首先你必須確保 git-shell 已存在於 /etc/shells 文件中:

cat /etc/shells   # see if `git-shell` is already in there.  If not...
    which git-shell   # make sure git-shell is installed on your system.
    sudo vim /etc/shells  # and add the path to git-shell from last command

   如今你可使用 chsh 命令修改任一系統用戶的 shell:

sudo chsh git  # and enter the path to git-shell, usually: /usr/bin/git-shell

   這樣,用戶 git 就只能利用 SSH 鏈接對 Git 倉庫進行推送和拉取操做,而不能登陸機器並取得普通 shell。 若是試圖登陸,你會發現嘗試被拒絕,像這樣:

ssh git@gitserver
    fatal: Interactive git shell is not enabled.
    hint: ~/git-shell-commands should exist and have read and execute access.
    Connection to gitserver closed.

   如今,網絡相關的 Git 命令依然可以正常工做,可是開發者用戶已經沒法獲得一個普通 shell 了。 正如輸出信息所提示的,你也能夠在 git 用戶的家目錄下創建一個目錄,來對 git-shell 命令進行必定程度的自定義。 好比,你能夠限制掉某些本應被服務器接受的 Git 命令,或者對剛纔的 SSH 拒絕登陸信息進行自定義,這樣,當有開發者用戶以相似方式嘗試登陸時,便會看到你的信息。 要了解更多有關自定義 shell 的信息,請運行 git help shell。

Git守護進程(Optional)

   接下來咱們將經過 「Git」 協議創建一個基於守護進程的倉庫。 對於快速且無需受權的 Git 數據訪問,這是一個理想之選。 請注意,由於其不包含受權服務,任何經過該協議管理的內容將在其網絡上公開。

   若是運行在防火牆以外的服務器上,它應該只對那些公開的只讀項目服務。 若是運行在防火牆以內的服務器上,它可用於支撐大量參與人員或自動系統(用於持續集成或編譯的主機)只讀訪問的項目,這樣能夠省去逐一配置 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/ \
        /opt/git/
    respawn

   出於安全考慮,強烈建議使用一個對倉庫擁有隻讀權限的用戶身份來運行該守護進程 - 你能夠建立一個新用戶 git-ro 而且以該用戶身份來運行守護進程。 爲簡便起見,咱們將像 git-shell 同樣,一樣使用 git 用戶來運行它。

   當你重啓機器時,你的 Git 守護進程將會自動啓動,而且若是進程被意外結束它會自動從新運行。 爲了在不重啓的狀況下直接運行,你能夠運行如下命令:

initctl start local-git-daemon

   在其餘系統中,你可使用 sysvinit 系統中的 xinetd 腳本,或者另外的方式來實現 - 只要你可以將其命令守護進程化並實現監控。

   接下來,你須要告訴 Git 哪些倉庫容許基於服務器的無受權訪問。 你能夠在每一個倉庫下建立一個名爲 git-daemon-export-ok 的文件來實現。

cd /path/to/project.git
    touch git-daemon-export-ok

   該文件將容許 Git 提供無需受權的項目訪問服務。

參考網址:

相關文章
相關標籤/搜索