レンタルサーバ等で gitosis を使う

gitosis の使い方の記事はいろいろある*1ようですが、gitosis 用のユーザを作らず一般ユーザ権限のみで運用する方法について書いた記事が無いようなので、その場合の方法、注意点等を軽く書いておきます。

gitosis は ~/.ssh/authorized_keys を管理用リポジトリの post-update hook を使って自動的に書き換えることでユーザ管理を実現しています。したがって、gitosis を使うには OpenSSH 形式の ~/.ssh/authorized_keys が使える事が大前提です。また、公開鍵認証以外でのログイン手段が無い場合、authorized_keys が壊れた場合に対処ができなくなるので危険です*2。諦めましょう。

インストール

Git と Python あたりのインストールは済んでいるものとします。

リポジトリから gitosis を取ってきてインストールします:

$ git clone git://eagain.net/gitosis.git
$ cd gitosis
$ python setup.py install --user

インストール先は ~/.local/ になるので、~/.local/bin に PATH を通しておいてください。

gitosis 初期設定

gitosis 管理用の鍵ペアを用意し gitosis を初期化します:

$ gitosis-init < id_rsa.pub

gitosis の仕組み上、authorized_keys へ通常のログイン用に登録された鍵を併用するとちょっと面倒かもしれません。
管理用のリポジトリ ~/repositories/gitosis-admin.git の post-update hook に実行権限を付けておきます:

chmod 755 ~/repositories/gitosis-admin.git/hooks/post-update

後は gitosis-admin.git を clone してきて設定をするのですが……、
えーと、力尽きたので、後の作業は http://progit.org/book/ja/ch4-7.html を見てください。

gitosis の仕組み

gitosis の設定後の authorized_keys の中身は

### autogenerated by gitosis, DO NOT EDIT
command="gitosis-serve user1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3(略) user1
command="gitosis-serve user2",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3(略) user2

のようになっています。command オプションが指定されているため、この鍵で認証された場合はユーザがクライアント側で指定したコマンドを無視し、その代わりに command オプションで指定された gitosis-serve user1 が実行されます。
クライアントが指定したコマンドは環境変数 SSH_ORIGINAL_COMMAND に格納されているので、gitosis-serve はその環境変数を解釈してアクセス制御をしています*3

ありがちな問題?

鍵を流用した場合

gitosis 管理用に鍵ペアを用意せず、通常のログインに使う鍵を流用した場合

$ git clone hoge@example.org:gitosis-admin.git
Initialized empty Git repository in /home/fuga/gitosis-admin/.git/
fatal: 'gitosis-admin.git' does not appear to be a git repository
fatal: The remote end hung up unexpectedly

のようなエラーに見舞われることがあります。これは、gitosis 経由でリポジトリにアクセスしていないため発生します*4
この場合は、単に、

git clone hoge@example.org:repositories/gitosis-admin.git

のように、直接リポジトリにアクセスしてしまえば良いでしょう。

PATHが通せない場合

大抵 ~/.bashrc か ~/.ssh/environment あたりに書いておけば良いと思いますが、
PATH が通せない場合は gitosis をフルパスで指定する必要があるので、スクリプトを手で弄る必要があります。

gitosis/ssh.py 中に

def generateAuthorizedKeys(keys):
    TEMPLATE=('command="gitosis-serve %(user)s",no-port-forwarding,'
              +'no-X11-forwarding,no-agent-forwarding,no-pty %(key)s')
    yield COMMENT
    for (user, key) in keys:
        yield TEMPLATE % dict(user=user, key=key)

という部分があるので、gitosis-serve をフルパスに修正します。例えば /home/hoge/.local/bin/gitosis-serve の場合、

def generateAuthorizedKeys(keys):
    TEMPLATE=('command="/home/hoge/.local/bin/gitosis-serve %(user)s",no-port-forwarding,'
              +'no-X11-forwarding,no-agent-forwarding,no-pty %(key)s')
    yield COMMENT
    for (user, key) in keys:
        yield TEMPLATE % dict(user=user, key=key)

とします。もう一箇所は、gitosis/templates/admin/hooks/post-update 中の gitosis-run-hook を、やはりフルパスに修正します。

前:

#!/bin/sh
set -e
gitosis-run-hook post-update
git-update-server-info

後:

#!/bin/sh
set -e
/home/hoge/.local/bin/gitosis-run-hook post-update
git-update-server-info

*1:http://progit.org/book/ja/ch4-7.html

*2:gitosis 用ユーザを作る理由の一つでしょう

*3:git がリポジトリへアクセスする方法については http://progit.org/book/ja/ch9-6.html を参照してください

*4:同じ鍵に対して、gitosis 経由でアクセスするものと、通常のログイン用の両方の設定があるので