プロジェクト

全般

プロフィール

CentOS 7でapache経由のgitサーバーを構築

はじめに

CentOS 7の標準Gitに含まれるCGI(git-http-backend)を使用して、Apache httpdで動作するGitサーバーを構築します。
このCGIとは別にWebDAVを使う方法もありますが、遅い、サーバー側のフックスクリプトが使えないといった制約があるので使用しません。

最小限のサーバー構築

認証なしで読み書き可能なGitサーバーを構築します。使用するポート番号はhttpdデフォルトの80で、リポジトリの場所は/var/lib/git/の下とします。

必要なパッケージ

CentOS 7標準のhttpdおよびgitを使用します。

# yum install httpd git

設定

httpdの設定

/etc/httpd/conf.d/ディレクトリにgit設定専用のgit.confを作成します。

SetEnv GIT_PROJECT_ROOT /var/lib/git
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv REMOTE_USER $REDIRECT_REMOTE_USER

ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/

<LocationMatch "^/git/">
  Require all granted
</LocationMatch>
  • 匿名アクセスの場合、REMOTE_USER環境変数定義をここに記述します
  • Apache 2.4からは、Require all grantedが必要です

ファイアウォールの設定

サービスhttp(ポート80)を許可します。

# firewall-cmd --permanent --add-service=http
success
# firewall-cmd --reload
success
#

SELinuxの設定

gitは、リポジトリに対して読み書き(unlinkを含む)のアクセスをします。また、hookスクリプトについては実行権限が必要です。
そこで、リポジトリ全体(/var/lib/git/以下)のファイルコンテクストをhttpd_var_lib_t とし、hookスクリプトを置く場所(/var/lib/git/*/hooks/以下)のファイルコンテクストをhttpd_sys_script_exec_t とします。

# semanage fcontext -a -t httpd_var_lib_t '/var/lib/git(/.*)?'
# semanage fcontext -a -t httpd_sys_script_exec_t '/var/lib/git/[^/]+/hooks(/.*)?'
# restorecon -v -R /var/lib/git
    :(ファイルコンテクストの変更が発生したディレクトリ・ファイルが表示)

リポジトリの作成

/var/lib/gitディレクトリを作成し、その下にフラットにgitリポジトリを並べます(制約)。

# mkdir /var/lib/git
# cd /var/lib/git
# git init --bare --shared first.git
# cd first.git
# git update-server-info
# mv hooks/post-update.sample hooks/post-update
# chown -R apache.apache /var/lib/git

httpdの起動と自動起動設定

httpdサービスを起動します。

# systemctl start httpd

OS再起動時にhttpdを自動起動する設定をします。

# systemctl enable httpd

Apache httpdの認証を使ったサーバー構築

T.B.D.(もしかしたら将来書くかも)

Redmine 認証(LDAP未使用)サーバー構築

Redmineのユーザーで認証するGitサーバーを構築します。Redmineのプロジェクトへの読み書き可否がgitリポジトリの読み書き可否に対応します。
例えば、Redmineのプロジェクトを参照できるが編集できないユーザーは、gitリポジトリも参照できるが変更できません(cloneはできるがpushはできない)。

必要なパッケージ

Redmineのユーザー認証をhttpdから行うためのモジュールがRedmine側に用意されています。

  • <Redmineインストールディレクトリ>/extra/svn/Redmine.pm

これは、Apache httpd のmod_perlを使った仕組みです。今後Redmineのバージョンアップで更新したときに都度コピーするのは忘れがちなので、シンボリックリンクを作成しておきます。

# mkdir -p /etc/httpd/Apache/Authn
# ln -s /var/lib/redmine/extra/svn/Redmine.pm /etc/httpd/Apache/Authn/Redmine.pm

mod_perlはCentOS 7標準リポジトリには存在しないので、EPELからインストールします。EPELリポジトリ設定をしていなければ、以下を実行してEPELリポジトリ設定をします。

# yum install epel-release

次に、mod_perlと、他に必要となるperl-Digest-SHAをインストールします。perl-Digest-SHAはCentOS標準パッケージです。

# yum install mod_perl perl-Digest-SHA

  • 他にも必要なパッケージが発生するかも

設定

httpdの設定

先ほど認証無しの設定で作成したgit.confをベースに必要な設定を追記します。redmine認証用になるのでファイル名もgit.confからgit-redmine.confに変えておきます。

# cd /etc/httpd/conf.d/
# mv git.conf git-redmine.conf

/etc/httpd/conf.d/git-redmine.conf にRedmine認証設定を追記します。

+ PerlLoadModule Apache::Authn::Redmine

  SetEnv GIT_PROJECT_ROOT /var/lib/git
  SetEnv GIT_HTTP_EXPORT_ALL
  SetEnv REMOTE_USER $REDIRECT_REMOTE_USER

  ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/

  <LocationMatch "^/git/">
+   PerlAuthenHandler Apache::Authn::Redmine::authen_handler
+   AuthType Basic
+   AuthName "Git Redmine" 
+
+   # for Redmine Authentication
+   RedmineDSN "DBI:mysql:database=db_redmine;host=localhost" 
+   RedmineDbUser "redmine" 
+   RedmineDbPass "password" 
+   RedmineGitSmartHttp yes
+
-   Require all granted
+   Require valid-user
</LocationMatch>

  • Redmine認証用のmod_perlモジュール Redmine.pm をインポートします
  • アクセス可否判定のハンドラー(ユーザーが参照できる、または匿名で参照できるか判定)と 認証可否のハンドラーを定義します
  • Basic認証の仕組みでブラウザとやり取りします
  • Redmineの認証は、Redmineのデータベースに直接SQLクエリして判定しているようです
  • Redmineのデータベースに接続するための情報を記述します。データベース種類、データベース名、ホスト名、ユーザー/パスワードを設定します。ここはRedmine側の設定に合わせて記述します

設定ファイルにはセンシティブな情報を記述しているので、パーミッションをrootのみに限定します。

# chmod 0400 /etc/httpd/conf.d/git-redmine.conf

Gitリポジトリの名称

Redmine認証を使用する場合、Gitリポジトリのディレクトリ名は、必ずRedmineのプロジェクト識別子と同名か、プロジェクト識別子にピリオドを付けてそれ以降に任意の文字列を続けた名前であることが前提となります。

<Redmineプロジェクト識別子>.<任意の文字列>

Redmine.pmの問題

CentOS 6のApache 2.2では、PerlAccessHandler Apache::Authn::Redmine::access_handler を/etc/httpd/conf.d/git-redmine.confに記述していました。これは、匿名アクセスでも読み/書き可能なRedmineプロジェクトのリポジトリであれば、認証を求めずにgitでアクセスできるものです。しかし、Apache 2.4ではうまく動かないので上述の設定では除去しています。そのため、匿名で参照できるRedmineプロジェクトのリポジトリであっても必ず認証が必要になります(ユーザー名/パスワードを入力する必要がある)。

この問題はRedmine本家のissueにも上がっています。
https://www.redmine.org/issues/16948

ワークアラウンドな(当人いわくdirty)回避がstackoverflowにちらっと記載されていたので、Redmine.pmを少し修正してみました。
http://stackoverflow.com/questions/22638972/debug-apache-2-4-perlauthenhandler

--- Redmine.pm.1        2015-07-26 16:10:58.000000000 +0900
+++ Redmine.pm  2015-11-22 19:48:49.089000000 +0900
@@ -332,10 +332,12 @@

   my $project_id = get_project_identifier($r);

-  $r->set_handlers(PerlAuthenHandler => [\&OK])
-      if is_public_project($project_id, $r) && anonymous_allowed_to_browse_repository($project_id, $r);
+  if (is_public_project($project_id, $r) && anonymous_allowed_to_browse_repository($project_id, $r)) {
+      $r->set_handlers(PerlAuthenHandler => [\&OK]);
+      $r->user("");
+  }

   return OK
 }

 sub authen_handler {

Redmine.pmをこの修正版に差し替えると、/etc/httpd/conf.d/git-redmine.conf に次を追記できます。



	

Redmine 認証(LDAP使用)サーバー構築

先のRedmineのユーザーで認証するGitサーバーは、Redmineの内部ユーザーの認証は可能ですが、LDAP等で外部の認証を利用しているユーザーの認証ができません。
そこで、LDAPユーザーについては認証できるよう追加設定をします。

必要なパッケージ

perl-Authen-Simple-LDAP パッケージが必要ですが、CentOS 7にもEPELにもありません。CPANからモジュールを取得するのが一般的なようですが、今回うまく取得できなかったので、RPMパッケージ化しておきます。RPMとしておくとCentOSではとりわけ便利です。

RPMの作成方法と作成したRPMファイルは、WikiページCentOS_6/7でPerl-Authen-Simple-LDAPのRPMパッケージを作る を参照してください。

# yum localinstall perl-Authen-Simple-LDAP-0.3-1.el7.centos.noarch.rpm

設定

git-redmine.conf

 PerlLoadModule Apache::Authn::Redmine
+ PerlLoadModule Authen::Simple::LDAP

 SetEnv GIT_PROJECT_ROOT /var/lib/git

SELinuxの設定

httpdプロセスの中でLDAP接続をするので、SELinuxの設定でhttpd_tドメイン(プロセスのコンテキスト)にLDAP接続を許可する設定をします。

# sudo setsebool -P httpd_can_connect_ldap 1

Redmine 認証(LDAPS使用)サーバー構築

LDAPへの接続をSSLにします。

T.B.D.

Redmine.pm 表示 - apache 2.4向けアドホック修正版 (16.8 KB) 高橋 徹, 2015/11/23 15:28

クリップボードから画像を追加 (サイズの上限: 1 GB)