criticablog

ソフトウェアエンジニアがニッチな情報を書きます。

bitnami redmine と同じホストで git 連携する

目的

Bitnami 版 Redmine と同じホストの /git というパスで git リポジトリにHTTPアクセスできるようにする。 もちろん Redmine のプロジェクトのメンバー管理と連動して git リポジトリへのアクセス制限を掛ける。

git-http-backend を(mod_cgi.so が Apache に無かったので)fcgiwrap を使って FastCGI として実行することにした。

Bitnami 公式ドキュメントの手順 https://wiki.bitnami.com/Applications/BitNami_Redmine#How_to_configure_Redmine_for_advanced_integration_with_Git と比較すると、git.YOUR_DOMAIN_NAME とか別VirtualHost を切らなくていいし、htdocs 下に別の Passenger アプリ grack を置く必要もない(Apache の設定は詳しくないので別なやり方あれば教えてください……)。

なおリポジトリをこの Redmine 上で作成するために SCM Creator プラグイン を入れているが、たぶん無くても動作するのでここでは説明しない。

材料と道具

使用したバージョン

設定

fcgiwrap

apache (/opt/bitnami/apache2/bin/httpd.bin) プロセスが fcgiwrap の作るソケットに読み書きできるようにユーザ/グループを設定する。

/etc/default/fcgiwrap

FCGI_USER=daemon
FCGI_GROUP=bitnami
FCGI_SOCKET_OWNER=daemon
FCGI_SOCKET_GROUP=daemon

httpd の設定

vcs.conf とか別ファイルに書いて /opt/bitnami/apache2/conf/httpd.conf から Include する。

<IfModule !perl_module>
LoadModule perl_module modules/mod_perl.so
</IfModule>
<IfModule !env_module>
LoadModule env_module modules/mod_env.so
</IfModule>
PerlLoadModule Apache::Authn::Redmine

# Subversionの設定
<Location /svn>
    DAV svn
    SVNParentPath /opt/repositories/svn
    SVNListParentPath on
    # 適当な内容の設定を置いてある
    AuthzSVNAccessFile /usr/local/etc/svnauthz

    AuthType Basic
    AuthName "Subversion"
    # http://www.redmine.org/boards/2/topics/35428
    AuthUserFile /dev/null
    Require valid-user

    # Redmine プロジェクトのメンバー管理と連動したアクセス制御。
    PerlAccessHandler Apache::Authn::Redmine::access_handler
    PerlAuthenHandler Apache::Authn::Redmine::authen_handler
    # /opt/bitnami/apps/redmine/htdocs/config/database.yml と同じ値にする。
    RedmineDSN "DBI:mysql:database=bitnami_redmine;host=localhost;mysql_socket=/opt/bitnami/mysql/tmp/mysql.sock"
    RedmineDbUser "bitnami"
    RedmineDbPass "****"
</Location>

# Gitの設定
# bitnami の apache には mod_cgi.so が付属しないので CGI コマンドを直接実行できない。
<IfModule !proxy_module>
LoadModule proxy_module modules/mod_proxy.so
</IfModule>
<IfModule !proxy_fcgi_module>
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
</IfModule>

LogLevel trace2
# Alias を使い SCRIPT_FILENAME が git-http-backend を指すようにする。$1 は GIT_PROJECT_ROOT 下のディレクトリ名
AliasMatch "/git/(.+)" "/opt/bitnami/git/libexec/git-core/git-http-backend/$1"
<Location /git>
    # SCRIPT_FILENAME 変数が proxy:fcgi://〜 で始まるというバグが Apache 2.4.20 の mod_proxy_fcgi にある。
    # [Bug 59618 – SCRIPT_FILENAME is prefixed with bogus "proxy:fcgi"](https://bz.apache.org/bugzilla/show_bug.cgi?id=59618)
    # そのため fcgiwrap が実行すべきコマンドが分からず
    # Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?
    # というエラーを返す。 https://github.com/gnosek/fcgiwrap/blob/master/fcgiwrap.c
    # 一方 proxy:balancer: は除去するようになっているので balancer を経由するよう書けばよい:
    SetHandler "proxy:balancer://fcgi59618workaround"
    # バグ修正されたバージョンの Apache を使う場合こうなるはず:
    #SetHandler "proxy:unix:/run/fcgiwrap.socket|fcgi://."

    SetEnv GIT_HTTP_EXPORT_ALL ""
    SetEnv GIT_PROJECT_ROOT "/opt/repositories/git"

    AuthType Basic
    AuthName "Git"
    # http://www.redmine.org/boards/2/topics/35428
    AuthUserFile /dev/null
    Require valid-user

    # Redmine プロジェクトのメンバー管理と連動したアクセス制御。
    PerlAccessHandler Apache::Authn::Redmine::access_handler
    PerlAuthenHandler Apache::Authn::Redmine::authen_handler
    # /opt/bitnami/apps/redmine/htdocs/config/database.yml と同じ値にする。
    RedmineDSN "DBI:mysql:database=bitnami_redmine;host=localhost;mysql_socket=/opt/bitnami/mysql/tmp/mysql.sock"
    RedmineDbUser "bitnami"
    RedmineDbPass "****"
    RedmineGitSmartHttp yes
</Location>

# bug 59618 の回避策用の balancer を定義する。ここで決めた名前に proxy: をプレフィクスして上の SetHandler で参照している。
<Proxy "balancer://fcgi59618workaround">
    # fcgiwrap は FCGI プロトコルをしゃべり、SCRIPT_FILENAME で指定された CGIコマンド を実行する。
    # Unix domain socket を使う記法は https://httpd.apache.org/docs/2.4/en/mod/mod_proxy_fcgi.html のとおり。
    # socat でデバッグするときはソケットの path を変更する。
    BalancerMember "unix:/run/fcgiwrap.socket|fcgi://."
</Proxy> 

モジュールの配置

mkdir -p /opt/bitnami/perl/lib/site_perl/5.16.3/Apache/Authn
ln -sv /opt/bitnami/apps/redmine/htdocs/extra/svn/Redmine.pm /opt/bitnami/perl/lib/site_perl/5.16.3/Apache/Authn/Redmine.pm

おわりに

以上の設定で /opt/repositories/git/aaa を git clone http://(サーバ名)/git/aaa などと読み書きできるはず。

/opt/bitnami/apache2/conf/httpd.conf は大部分 bitnami の配布しているままだが、再現性の観点から載せとく。

/opt/bitnami/apache2/conf/httpd.conf

Apache で mod_proxy_fcgi と fcgiwrap を組み合わせる例もウェブ上には少ないので参考になると思う。

おまけ

FastCGIunix domain socket 通信内容を見たい場合 socat を apt-get でインストールして

sudo socat -t100 -v unix-listen:/home/bitnami/fcgiwrap.socket,mode=777,reuseaddr,fork unix-connect:/run/fcgiwrap.socket > ~/fcgiwrap.log 2>&1 &

と起動しておいて上の vcs.confunix:/run/fcgiwrap.socket と書いてるとこを unix:/home/bitnami/fcgiwrap.socket と置き換えればよい。 ちなみに設定を書き換えたら sudo /opt/bitnami/ctlscript.sh restart apache で読みなおす必要がある。