GeekFactory

int128.hatenablog.com

SSHとHTTPSでアクセスできるGitサーバの設計と構築

(追記) この記事は公開から時間が経っており、内容が古くなっています。

本稿では、すでにプライベートなWebサーバを運用している人向けにGitサーバの構築方法を説明します。ひと手間をかけるだけでGitサーバを構成できます。Webサーバがない人はGitHubでプライベートリポジトリを作った方が早くて安くて旨いかもしれません。

要件

以下の要件を考えてみます。

具体的には、

git clone git@git.example.com:/something.git

とか、

git clone https://myname@git.example.com/something.git

とかしたいです。

Gitクライアントの設定は省略します。GitHubHTTPSアクセスで接続試験しておきましょう。

設計

世の中で広く使われている標準的な構成を採用します。

  • gitolite
  • gitweb
  • git-http-backend (gitに含まれる)
  • Apache httpd server
    • mod_ssl
    • Virtual Host
    • CGI
    • suexec
セキュリティ設計

リポジトリには機密情報が含まれる可能性があるため、リポジトリにアクセスできる手段を可能な限り絞り込みます。具体的には、以下のように設計します。

  • SSH経由のアクセス
    • SSHで公開鍵認証を行い、Gitoliteでアクセス制御を行います。
    • Gitoliteは公開鍵を適切に管理する役割も担います。
    • 認証からリポジトリ操作までgitユーザでプロセスを実行します。
  • HTTPS経由のアクセス
    • Apache httpdで認証およびアクセス制御を行い、さらにGitoliteでアクセス制御を行います。
    • 認証に用いるクレデンシャルは適切に管理されている前提とします。
      • 私の環境ではLDAPで統合認証しています。
      • htpasswdによるパスワード認証でも構いません。
    • Apache httpdからsuexecを経由してgitユーザでプロセスを実行します。
Gitolite

Gitoliteは、Gitリポジトリを管理するためのツールです。リポジトリからSSH設定までまるっと管理してくれます。詳しい仕組みは ユカイ、ツーカイ、カイハツ環境!(26):Git管理の神ツール「Gitolite」なら、ここまでできる! (1/2) - @IT が参考になります。本稿では以下の設計とします。

  • gitユーザ(gitグループ)でリポジトリを管理します。
    • suexecを使うため、gitユーザのUIDはシステムユーザではない範囲(一般に500以上)にします。
    • ホームディレクトリは /home/git とします。
    • gitoliteパッケージのインストールで作成されるユーザは今回使いません。名前が長いし、システムユーザだし。
  • /home/git/repositories にリポジトリ群を配置します。
  • gitユーザのみGitリポジトリを参照できるようにします。
GitWeb

GitWebは、Webベースのリポジトリビューアです。GitHubに比べたらお世辞にも高機能とは言えませんが、CGIファイルを置くだけで使えるので簡単です。詳しくは Git - GitWeb が参考になります。本稿では以下の設計とします。

  • suexecを利用してgitユーザでスクリプトを実行します。
  • suexecを利用するため、スクリプトやリソースは /var/www/git に配置します。
git-http-backend

git-http-backendは、HTTP経由のリポジトリアクセスを実現するためのバックエンドです。詳細な仕組みは Smart HTTP Transport が参考になります。本稿では以下の設計とします。

  • suexecを利用してgitユーザでバックエンドを実行します。
  • suexecを利用するため、バックエンドを呼び出すラッパースクリプトを /var/www/git に配置します。
Apache httpd

以下の設計とします。

  • 他のWebサイトとGitサーバを分離したいので、新しくバーチャルホストを作成します。ここでは https://git.example.com とします。
  • パスワードを保護するため、SSLを使います。
    • ワイルドカード証明書(例:*.example.com)にしておくと、SSLでもバーチャルホストを増やせるので便利です。
    • 自己署名CAの場合は、WebブラウザにCA証明書をインポートしておきしましょう。
  • suexecを有効化します。

構築

Gitolite

詳しい方法は ユカイ、ツーカイ、カイハツ環境!(26):Git管理の神ツール「Gitolite」なら、ここまでできる! (1/2) - @IT を参照してください。

結果的に、以下のディレクトリ構造があればOKです。

  • /home/git (git:git 700)
Apache httpd

下記のようにhttpd.confを設定します。これはApache httpd 2.4の例です。2.2では手直しが必要です。あと、バーチャルホスト以外の設定は省略しています。

# Basic SSL setup
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
SSLPassPhraseDialog builtin
SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300
SSLCertificateFile    /etc/pki/https-wildcard.crt  # 環境に応じて変更してください
SSLCertificateKeyFile /etc/pki/https-wildcard.key
SSLCACertificateFile  /etc/pki/https-ca.crt
Listen 443

<VirtualHost *:443>
  SSLEngine on
  ServerName git.example.com
  SuexecUserGroup git git
  DocumentRoot /var/www/git
  <Location />
    AuthMerging And
    Authname "git"
    Include "/etc/httpd/conf.d/auth-ldap"  # 認証方式に応じて変更してください
    Require user someone
  </Location>
  <Directory /var/www/git>
    Require all granted
    Options ExecCGI
    AddHandler cgi-script .cgi
    DirectoryIndex gitweb.cgi
  </Directory>
  ScriptAliasMatch ^/.*\.git/.*$ /var/www/git/git-http-backend-wrapper.cgi$0
</VirtualHost>

ポイントは、

  • 認証を有効にします。
  • / にアクセスすると GitWeb が実行されるようにします。
  • .git/ が含まれるパスにアクセスするとバックエンドラッパーが実行されるようにします。
git-http-backend

下記の内容で /var/www/git/git-http-backend-wrapper.cgi を配置します。chmod +xしておきます。

#!/bin/sh
export GIT_PROJECT_ROOT=/home/git/repositories
export GIT_HTTP_EXPORT_ALL=1
export GIT_HTTP_BACKEND=/usr/libexec/git-core/git-http-backend
export GITOLITE_HTTP_HOME=/home/git
exec gl-auth-command

ポイントは、

GitWeb

設定ファイル(/etc/gitweb.conf)にリポジトリパスを指定します。

テスト

まず https://git.example.com/ にアクセスしてみましょう。GitWebのリポジトリ一覧が表示されるはずです。

今度はHTTPS経由でgit cloneしてみましょう。

git clone https://myname@git.example.com/something.git

別のリポジトリを使って、HTTPS経由のgit pushも試してみましょう。

git remote add private https://myname@git.example.com/hoge.git
git push private master

うまくいきましたか?アクセスに失敗した場合はApache httpdのエラーログやsuexecログを参照します。特にsuexecの実行条件はかなり複雑なので、一つずつ問題を解決していきましょう。