Apache を使って Bazaar サーバーをたてる

このドキュメントでは、 Apache 2.0 と FastCGI, mod_python, mod_wsgi の どれかを利用して Bazaar の HTTP スマートサーバーをセットアップする方法を 説明します。

スマートサーバーに関する詳細な情報とそれを設定する他の方法に関しては、 スマートサーバーのドキュメント を参照してください。

プレーンなHTTPで /srv/example.com/www/codehttp://example.com/code/… として すでに公開しているとします。これはbzrのブランチと /srv/example.com/www/code/branch-one/srv/example.com/www/code/my-repo/branch-two のようなディレクトリを含みます。 既存のHTTP形式のアクセス権限に加えてリードオンリーのスマートサーバーのアクセス権限を これらのディレクトリに提供したい場合を考えます。

Apache 2.0を設定する

FastCGI

最初に、mod_fastcgiを設定します。たとえば次の行をhttpd.confに追加します:

LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so
FastCgiIpcDir /var/lib/apache2/fastcgi

我々の例では、http://example.com/code/srv/example.com/www/code をすでに提供しているので 既存のApacheの設定は次のようになります:

Alias /code /srv/example.com/www/code
<Directory /srv/example.com/www/code>
    Options Indexes
    # ...
</Directory>

.bzr/smartの形式で終わるURLに対するすべてのリクエストを扱うために 次のように変更する必要があります:

Alias /code /srv/example.com/www/code
<Directory /srv/example.com/www/code>
    Options Indexes FollowSymLinks
    RewriteEngine On
    RewriteBase /code
    RewriteRule ^(.*/)?\.bzr/smart$ /srv/example.com/scripts/bzr-smart.fcgi
</Directory>

# bzr-smart.fcgiはDocumentRootの元に存在しないので、実行されるように
# AliasはこれをURLの名前空間のエイリアスにする。
Alias /srv/example.com/scripts/bzr-smart.fcgi /srv/example.com/scripts/bzr-smart.fcgi
<Directory /srv/example.com/scripts>
    Options ExecCGI
    <Files bzr-smart.fcgi>
        SetHandler fastcgi-script
    </Files>
</Directory>

この設定はFastCGIを通して /code 内部の /.bzr/smart で終わるURLに対する Bazaarのスマートサーバーへのリクエストを扱うようにApacheに指示します。

詳細な情報は mod_rewritemod_fastcgi のドキュメントを参照してください。

mod_python

最初に、次のようなコードを httpd.conf に追加して mod_python を設定します:

LoadModule python_module /usr/lib/apache2/modules/mod_python.so

FastCGI と同じ方法で mod_rewrite を用いて書き換えルールを定義します:

RewriteRule ^(.*/)?\.bzr/smart$ /srv/example.com/scripts/bzr-smart.fcgi

変更は次のようになります:

RewriteRule ^(.*/)?\.bzr/smart$ /srv/example.com/scripts/bzr-smart.py

mod_fastcgi のように、スクリプトがどのように扱われるのかも定義します:

Alias /srv/example.com/scripts/bzr-smart.py /srv/example.com/scripts/bzr-smart.py
<Directory /srv/example.com/scripts>
    <Files bzr-smart.py>
        PythonPath "sys.path+['/srv/example.com/scripts']"
        AddHandler python-program .py
        PythonHandler bzr-smart::handler
    </Files>
</Directory>

この設定は mod_python を通して /code 内部の /.bzr/smart で終わるURLに対するリクエストを Bazaar のスマートサーバーに渡すように指示します。

注: bzrlib が PATH の中に存在しない場合、次の行を変更する必要があります:

PythonPath "sys.path+['/srv/example.com/scripts']"

変更後は次のようになります:

PythonPath "['/path/to/bzr']+sys.path+['/srv/example.com/scripts']"

詳細な情報は mod_python のドキュメントを参照してください。

mod_wsgi

最初に、 a2enmod wsgi などで mod_wsgi を有効にしておきます。 次に、 .bzr/smart で終わる全ての URL に対するリクエストを mod_wsgi 経由 で処理するように設定します。設定例は次のようになります。

WSGIScriptAliasMatch ^/code/.*/\.bzr/smart$ /srv/example.com/scripts/bzr.wsgi

#The three next lines allow regular GETs to work too
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/code/.*/\.bzr/smart$
RewriteRule ^/code/(.*/\.bzr/.*)$ /srv/example.com/www/code/$1 [L]

<Directory /srv/example.com/www/code>
    WSGIApplicationGroup %{GLOBAL}
</Directory>

この設定では、 Apache は /code 以下の /.bzr/smart で終わる URL に 対する全てのリクエストを WSGI 経由で Bazaar のスマートサーバーに渡し、 それ以外の全てのリクエストは Apache が直接扱うようにしています。

詳細は mod_wsgi のドキュメントを参照してください。

Bazaarを設定する

FastCGI

/srv/example.com/scripts/bzr-smart.fcgi でスマートサーバーを実行するためにApacheを設定しました。 これはスマートサーバーを設定するために書く必要のある単なるシンプルなスクリプトで サーバーをFastCGIのゲートウェイに結びつけます。次のようになります:

import fcgi
from bzrlib.transport.http import wsgi

smart_server_app = wsgi.make_app(
    root='/srv/example.com/www/code',
    prefix='/code/',
    path_var='REQUEST_URI',
    readonly=True,
    load_plugins=True,
    enable_logging=True)

fcgi.WSGIServer(smart_server_app).run()

 fcgi のモジュールはhttp://svn.saddi.com/py-lib/trunk/fcgi.pyで見つかります。 これは flup の一部です。

mod_python

/srv/example.com/scripts/bzr-smart.py でスマートサーバーを実行するためにApacheを設定しました。 これはスマートサーバーを設定するために書く必要のあるシンプルなスクリプトでサーバーをmod_pythonの ゲートウェイに結びつけます。次のようになります:

import modpywsgi
from bzrlib.transport.http import wsgi

smart_server_app = wsgi.make_app(
    root='/srv/example.com/www/code',
    prefix='/code/',
    path_var='REQUEST_URI',
    readonly=True,
    load_plugins=True,
    enable_logging=True)

def handler(request):
    """Handle a single request."""
    wsgi_server = modpywsgi.WSGIServer(smart_server_app)
    return wsgi_server.run(request)

modpywsgi モジュールは http://ice.usq.edu.au/svn/ice/trunk/apps/ice-server/modpywsgi.py で見つかります。 これは pocoo の一部でした。 modpywsgi.py を bzr-smart.py と同じディレクトリ (すなわち/srv/example.com/scripts/)に設置していることを確認してください。

mod_wsgi

We’ve configured Apache to run the smart server at /srv/example.com/scripts/bzr.wsgi. This is just a simple script we need to write to configure a smart server, and glue it to the WSGI gateway. Here’s what it looks like:

from bzrlib.transport.http import wsgi

def application(environ, start_response):
    app = wsgi.make_app(
        root="/srv/example.com/www/code/",
        prefix="/code",
        readonly=True,
        enable_logging=False)
    return app(environ, start_response)

クライアント

これで bzr+http:// 形式のURLやただの http:// のURLを利用できます:

bzr log bzr+http://example.com/code/my-branch

プレーンなHTTP形式のアクセスも持続します:

bzr log http://example.com/code/my-branch

高度な設定

BazaarのHTTPスマートサーバーはWSGIアプリケーションなので、 WSGI標準に準拠するサードパーティのWSGIのミドルウェアもしくはサーバーで利用できます。 唯一の要件は以下のとおりです:

  • SmartWSGIApp をコンストラクトするためには、それが提供する root transport を指定する必要があります。
  • それぞれのリクエストの environ dict は ‘bzrlib.relpath’ 変数の設定を持たなければなりません。

この例で使われている make_app ヘルパーは それに渡される root パスに基づいたトランスポートを伴う SmartWSGIApp をコンストラクトし、引数 prefix と`path_var` に基づくそれぞれのリクエストに対する  bzrlib.relpath を算出します。 上記の例において、これは (Apacheによって設定される)’REQUEST_URI’ を取り、接頭辞の ‘/code/’ と接尾辞の ‘/.bzr/smart’ をはぎ取り、それを ‘bzrlib.relpath’ として設定するので、 ‘/code/foo/bar/.bzr/smart’ に対するリクエストは ‘foo/bzr’ の ‘bzrlib.relpath’ になります。

SmartWSGIApp を直接コンストラクトすることで、ローカルではないトランスポートに対して スマートサーバーを設定するもしくは任意任意のパスの変換を行うことは可能です。 詳細な情報に関しては bzrlib.transport.http.wsgi のdocstringsと WSGI標準 を参照してください。

HTTP スマートサーバー経由で push する

HTTP スマートサーバーを通してデータをプッシュすることは可能です。 これを行うための最も簡単な方法は、 wsgi.make_app() コールに readonly=False を 提供するだけです。ただし、スマートプロトコルは認証機能が含まれないので注意してください。 書き込みのサポートを有効にする場合、 実際にシステム上のデータを書き込みできる人を制限するために、 .bzr/smart URLへの権限を制限するとよいでしょう。例えば Apache で次のような設定を します。

<Location /code>
    AuthType Basic
    AuthName "example"
    AuthUserFile /srv/example.com/conf/auth.passwd
    <LimitExcept GET>
        Require valid-user
    </LimitExcept>
</Location>

現時点では、同じURLに対して読み込み限定の人と読み込みと書き込みの人を 分けることはできません。 (認証を行う)HTTPレイヤーにおいて、すべては単なるPOSTリクエストだからです。 しかしながら、HTTPSアクセスの場合に認証が必要な書き込みサーバーを使い、 プレーンなHTTPは読み込み限定のアクセスを許可することはできます。

HTTPS サイトに対してアクセスしたときに bzr が次のようなエラーを表示する 場合:

bzr: ERROR: Connection error: curl connection error (server certificate verification failed.
CAfile:/etc/ssl/certs/ca-certificates.crt CRLfile: none)

You can workaround it by using https+urllib rather than http in your URL, or by uninstalling pycurl. See bug 82086 for more details.

URL に https の代わりに https+urllib を使うことで問題を回避 できます。 詳細については bug 82086 を参照してください。