LinuxでGitサーバを構築する

Debian GNU/Linux 8 (jessie) 上にGitサーバ(httpアクセス用)を構築します。 debian-8.0.0-amd64-DVD-1.iso に基づいて執筆しています。ディストリビューションが違う場合、または同じDebainでもバージョンが違う場合、下記手順通りではうまくいかない場合がありますので、他サイトでの情報と照らし合わせながら、参考程度にしてください。

isoファイルをDVD-Rに焼いたら、インストールします(なお、下記の解説では、VMware vSphere Hypervisor 上で行っています)。Debianの基本的なインストールには慣れている方を想定していますので、インストール手順は適当に省略します。

ホスト名は、とりあえず mygit とします。

私の環境では、一台のマシンにたくさんの機能を詰め込むことはせず、サービス毎にマシンを分けています。VMware上の仮想マシンなので、その方がメンテナンスしやすいという理由もあります。この仮想マシンにはapacheとgit以外のサービスはインストールしないので、ストレージ容量は、システム要件最小の2GBとし、ディスク全体を単一パーティションで運用することにします。リポジトリは、最終的には外部NASに置く想定です。

web server、SSH server、standard system utilities をインストールします。デスクトップ環境は入れません。

通常は、Debianパッケージリポジトリとして、ネットワークミラーを使用すると思いますので、CD/DVDを検索対象から外します。

/etc/apt/sources.list を開いて、「deb cdrom:~」という行をコメントアウトします。

エディタを終了したら、 apt-get update を実行しておきます。

次に、 apt-get install git を実行して、Gitをインストールします。先の software selection の画面で web server を選択し忘れた場合には、 apt-get install apache2 も実行します。

hostname -I を実行して、IPアドレスを確認します。

別のマシンからウェブブラウザでアクセスしてみます。とりあえず、apacheが動作していることだけ確認しておきます。

/usr/lib/git-core/git-http-backend が存在することを確認しておきます。

git-http-backendのマニュアルに軽く目を通しておきます。

a2enmod cgi を実行して、apacheのCGIモジュールを有効にします。

apache2をリスタートしてくださいと言われますが、まだ後で構いません。

/etc/apache2/sites-enabled/000-default.conf を編集します。

<VirtualHost>定義の中に git-http-backend の定義と認証の定義を記述します。

(前略)

    SetEnv GIT_PROJECT_ROOT /var/lib/git
    SetEnv GIT_HTTP_EXPORT_ALL
    ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

    <LocationMatch "^/git/">
        AuthType Basic
        AuthName "Git"
        AuthUserFile /etc/apache2/git.htaccess
        Require valid-user
    </LocationMatch>
</VirtualHost>

認証ファイルを作成します。

htpasswd -c {ファイルの場所} {ユーザID}

apacheを再起動します。

service apache2 restart

ここで、外部ブラウザから、アクセスしてみます。(最後の / を忘れずに入力します)

http://192.168.0.230/git/

認証ダイアログが出て、正しい認証情報を入力すると、真っ白なページが表示されたら(たぶん)正常に動作しています。もしここで、404 Not Foundが出た場合、CGIモジュールが正しく動作していない可能性があります。 a2enmod cgi を忘れていないか確認します。ScriptAlias定義のタイプミスがないかも確認します。

次に、最初のリポジトリを作成します。

root@mygit:~# cd /var/lib/git/
root@mygit:/var/lib/git# mkdir test.git
root@mygit:/var/lib/git# cd test.git/
root@mygit:/var/lib/git/test.git# git init --bare --shared
Initialized empty shared Git repository in /var/lib/git/test.git/
root@mygit:/var/lib/git/test.git# git update-server-info

チェックアウトしてみます。

ファイルを追加してコミットします。

プッシュしてみます。

root@mygit:~/test# git push
warning: push.default is unset; its implicit value has changed in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the traditional behavior, use:

(中略)

Username for 'http://localhost': soramimi
Password for 'http://soramimi@localhost':
Counting objects: 3, done.
Writing objects: 100% (3/3), 217 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: error: insufficient permission for adding an object to repository database objects
remote: fatal: failed to write object
error: unpack failed: unpack-objects abnormal exit
To http://localhost/git/test.git
 ! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'http://localhost/git/test.git'
root@mygit:~/test#

failedだそうです。エラーになりました。権限が無いとかいって怒られました。よく見ると remote: error と書いてありますので、クローンしたローカル側ではなくて、リモート側リポジトリの問題です。確認してみます。

root@mygit:/var/lib/git# ls -la
total 12
drwxr-xr-x  3 root root 4096 Nov 27 11:02 .
drwxr-xr-x 33 root root 4096 Nov 27 10:20 ..
drwxrwsr-x  7 root root 4096 Nov 28 19:39 test.git 

最初に作ったリポジトリの所有者がrootになったままでした。apache(で動いているCGI)から読み書きできないといけません。リポジトリとその配下のファイルの所有者を変更します。Debianの場合は www-data.www-data です。

root@mygit:/var/lib/git# chown www-data.www-data -R test.git

では、改めて、クローンした作業ディレクトリに戻ってpushしてみましょう。

root@mygit:/var/lib/git# cd
root@mygit:~# cd test
root@mygit:~/test#
root@mygit:~/test# git push
warning: push.default is unset; its implicit value has changed in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the traditional behavior, use:

(中略)

Username for 'http://localhost': soramimi
Password for 'http://soramimi@localhost':
Counting objects: 3, done.
Writing objects: 100% (3/3), 217 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To http://localhost/git/test.git
 * [new branch]      master -> master
root@mygit:~/test#
pushが成功しました。リポジトリの所有者の変更は、うっかり忘れやすいです。 git update-server-info も忘れやすいので、これらは続けて実行するように注意します。