svnserve (専用サーバ)

The svnserve program is a lightweight server, capable of speaking to clients over TCP/IP using a custom, stateful protocol. Clients contact an svnserve server by using URLs that begin with the svn:// or svn+ssh:// scheme. This section will explain the different ways of running svnserve, how clients authenticate themselves to the server, and how to configure appropriate access control to your repositories.

サーバの起動

svnserve プログラムを動作させるのに、以下のように、いくつか異なる方法があります。

  • リクエストを受け付ける、スタンドアロンデーモンとして svnserve 実行します。

  • Have the Unix inetd daemon temporarily spawn svnserve whenever a request comes in on a certain port.

  • Have SSH invoke a temporary svnserve over an encrypted tunnel.

  • svnserve を Windows サービスとして実行します。

デーモンとしての svnserve

The easiest option is to run svnserve as a standalone 「daemon」 process. Use the -d option for this:

$ svnserve -d
$               # svnserve is now running, listening on port 3690

デーモンモードでsvnserveを実行するときには --listen-port=--listen-host=オプションで待ち受けポートとホスト 名を「指定」することができます。

Once we successfully start svnserve as above, it makes every repository on your system available to the network. A client needs to specify an absolute path in the repository URL. For example, if a repository is located at /usr/local/repositories/project1, then a client would reach it via svn://host.example.com/usr/local/repositories/project1. To increase security, you can pass the -r option to svnserve, which restricts it to exporting only repositories below that path. For example:

$ svnserve -d -r /usr/local/repositories
…

-rオプションの利用は リモートファイルシステム空間のルートとしてプログラムが扱う場所 を効果的に変更することができます。この場合クライアントはそのルート までの部分を除いたパスを指定することになり、もっと短い(そしてより情報制限された) URL を利用できます:

$ svn checkout svn://host.example.com/project1
…

inetd 経由の svnserve

If you want inetd to launch the process, then you need to pass the -i (--inetd) option. In the example, we've shown the output from running svnserve -i at the command line, but note that isn't how you actually start the daemon; see the paragraphs following the example for how to configure inetd to start svnserve.

$ svnserve -i
( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline ) ) )

--inetd オプション付きで起動すると svnserve はSubversion クライアントとの間 で、専用のプロトコルを使い、stdinstdoutチャンネル経由で通信しようとします。 これはinetdを経由して 実行されるプログラムの標準的な振る舞い方です。IANAはポート3690 をSubversion プロトコルのために予約しているため Unix 系のシステム上 なら/etc/servicesファイルに(もしまだ追加されていない のなら)以下の行を追加することができます:

svn           3690/tcp   # Subversion
svn           3690/udp   # Subversion

そしてもし伝統的な Unix 系の inetd デーモンを使っている場合 /etc/inetd.conf に以下のような行を追加できます。

svn stream tcp nowait svnowner /usr/bin/svnserve svnserve -i

Make sure 「svnowner」 is a user which has appropriate permissions to access your repositories. Now, when a client connection comes into your server on port 3690, inetd will spawn an svnserve process to service it. Of course, you may also want to add -r to the configuration line as well, to restrict which repositories are exported.

トンネル経由の svnserve

A third way to invoke svnserve is in 「tunnel mode」, with the -t option. This mode assumes that a remote-service program such as RSH or SSH has successfully authenticated a user and is now invoking a private svnserve process as that user. (Note that you, the user, will rarely, if ever, have reason to invoke svnserve with the -t at the command line; instead, the SSH daemon does so for you.) The svnserve program behaves normally (communicating via stdin and stdout), and assumes that the traffic is being automatically redirected over some sort of tunnel back to the client. When svnserve is invoked by a tunnel agent like this, be sure that the authenticated user has full read and write access to the repository database files. It's essentially the same as a local user accessing the repository via file:// URLs.

This option is described in much more detail in SSH のトンネリング項.

Windows サービスとしての svnserve

If your Windows system is a descendant of Windows NT (2000, 2003, XP, Vista), then you can run svnserve as a standard Windows service. This is typically a much nicer experience than running it as a standalone daemon with the --daemon (-d) option. Using daemon-mode requires launching a console, typing a command, and then leaving the console window running indefinitely. A Windows service, however, runs in the background, can start at boot time automatically, and can be started and stopped using the same consistent administration interface as other Windows services.

You'll need to define the new service using the command-line tool SC.EXE. Much like the inetd configuration line, you must specify an exact invocation of svnserve for Windows to run at start-up time:

C:\> sc create svn
        binpath= "C:\svn\bin\svnserve.exe --service -r C:\repos"
        displayname= "Subversion Server"
        depend= Tcpip
        start= auto

This defines a new Windows service named 「svn」, and which executes a particular svnserve.exe command when started (in this case, rooted at C:\repos.) There are a number of caveats in the prior example, however.

First, notice that the svnserve.exe program must always be invoked with the --service option. Any other options to svnserve must then be specified on the same line, but you cannot add conflicting options such as --daemon (-d), --tunnel, or --inetd (-i). Options such as -r or --listen-port are fine, though. Second, be careful about spaces when invoking the SC.EXE command: the key= value patterns must have no spaces between key= and exactly one space before the value. Lastly, be careful about spaces in your command-line to be invoked. If a directory name contains spaces (or other characters that need escaping), place the entire inner value of binpath in double-quotes, by escaping them:

C:\> sc create svn
        binpath= "\"C:\program files\svn\bin\svnserve.exe\" --service -r C:\repos"
        displayname= "Subversion Server"
        depend= Tcpip
        start= auto

Also note that the word binpath is misleading—its value is a command line, not the path to an executable. That's why you need to surround it with quote marks if it contains embedded spaces.

Once the service is defined, it can stopped, started, or queried using standard GUI tools (the Services administrative control panel), or at the command line as well:

C:\> net stop svn
C:\> net start svn

The service can also be uninstalled (i.e. undefined) by deleting its definition: sc delete svn. Just be sure to stop the service first! The SC.EXE program has many other subcommands and options; run sc /? to learn more about it.

組み込みの認証と認可

クライアントがsvnserveプロセスに接続する とき、以下のことが起こります:

  • クライアントは特定のリポジトリを選択します。

  • サーバはリポジトリの conf/svnserve.conf ファイルを処理しその中に定義されている認証と認可の方式に強制的に 従います。

  • そのときの状況と認可の方式により、以下のどれかになります。

    • クライアントは要求を匿名で行うことができ、どのような認証確認も 要求されないか、

    • クライアントは常に認証許可を求められるか、

    • もし"トンネルモード"で実行されている場合であれば、クライアント は既に外部的に認証されたことを宣言するか、です。

At the time of writing, the server only knows how to send a CRAM-MD5 [41] authentication challenge. In essence, the server sends a small amount of data to the client. The client uses the MD5 hash algorithm to create a fingerprint of the data and password combined, then sends the fingerprint as a response. The server performs the same computation with the stored password to verify that the result is identical. At no point does the actual password travel over the network.

もちろんクライアントはトンネルエージェント、たとえば SSHのようなものを経由して外部的に 認証することもできます。この場合サーバは単に実行している ユーザを確認し、それを認証されたユーザ名であるとして 利用します。より詳しくは SSH のトンネリング項を見てください。

As you've already guessed, a repository's svnserve.conf file is the central mechanism for controlling authentication and authorization policies. The file has the same format as other configuration files (see 実行時設定領域項): section names are marked by square brackets ([ and ]), comments begin with hashes (#), and each section contains specific variables that can be set (variable = value). Let's walk through these files and learn how to use them.

ユーザファイルと認証範囲の作成

For now, the [general] section of the svnserve.conf has all the variables you need. Begin by changing the values of those variables: choose a name for a file which will contain your usernames and passwords, and choose an authentication realm:

[general]
password-db = userfile
realm = example realm

realm は自分で定義できる名前です。 それはクライアントに接続先の「認証用の名前空間」の種別を伝えます; Subversion クライアントは認証プロンプトでそれを表示し、ディスク上の キャッシュされた証明のキーとして(サーバのホスト名、ポートと共に) 利用します。(クライアント証明のキャッシュ項参照。) password-db変数はユーザ名称とパスワードのリスト を含む個別のファイルを指す変数で、やはり同じ形式が利用されます。 たとえば:

[users]
harry = foopassword
sally = barpassword

password-db の値はユーザファイルの相対または 絶対パスです。多くの管理者にとって、svnserve.conf に従ったリポジトリの conf/領域にファイルを 正しく保つのは容易なことです。一方、同じユーザファイルを共有するような 二つ以上のリポジトリがほしいこともあります; そのような場合は ファイルは多分もっと公開された場所に移動すべきでしょう。ユーザファイルを共有 するリポジトリは同じ認証範囲を持つよう設定されていなくてはならず、それは ユーザ全逸ウ器コ本質的にただ一つの認証範囲を定義するためです。 ファイルがある場所であればどこでもファイルの読み書きパーミッション を正しく設定してください。もし svnserveを どのユーザが実行しているかわかるのであれば、必要に応じて ユーザファイルに対する読み出しアクセス制限をかけてください。

アクセス制御の設定

There are two more variables to set in the svnserve.conf file: they determine what unauthenticated (anonymous) and authenticated users are allowed to do. The variables anon-access and auth-access can be set to the values none, read, or write. Setting the value to none prohibits both reading and writing; read allows read-only access to the repository, and write allows complete read/write access to the repository. For example:

[general]
password-db = userfile
realm = example realm

# anonymous users can only read the repository
anon-access = read

# authenticated users can both read and write
auth-access = write

この例としての設定は、実際にはこれらの変数のデフォルト値なので定義 しなくても問題ありません。もしさらに保守的に設定したいのなら、 匿名のアクセスを完全に遮断することもできます:

[general]
password-db = userfile
realm = example realm

# anonymous users aren't allowed
anon-access = none

# authenticated users can both read and write
auth-access = write

The server process not only understands these 「blanket」 access controls to the repository, but also finer-grained access restrictions placed on specific files and directories within the repository. To make use of this feature, you need to define a file containing more detailed rules, and then set the authz-db variable to point to it:

[general]
password-db = userfile
realm = example realm

# Specific access rules for specific locations
authz-db = authzfile

The syntax of the authzfile file is discussed in detail in パスベース認証項. Note that the authz-db variable isn't mutually exclusive with the anon-access and auth-access variables; if all the variables are defined at once, then all of the rules must be satisfied before access is allowed.

SSH のトンネリング

svnserveの組み込み認証は非常に使いやすいものですが、 それは本当のシステム上のアカウントを作る必要がないからです。一方 管理者によっては既に確立された SSH 認証の仕組みを運用しているかも 知れません。そのような場合、プロジェクトユーザのすべてはシステムアカウント を持っており、サーバマシンに対して 「SSH による」 アクセスが可能なはず です。

It's easy to use SSH in conjunction with svnserve. The client simply uses the svn+ssh:// URL scheme to connect:

$ whoami
harry

$ svn list svn+ssh://host.example.com/repos/project
harry@host.example.com's password:  *****

foo
bar
baz
…

In this example, the Subversion client is invoking a local ssh process, connecting to host.example.com, authenticating as the user harry, then spawning a private svnserve process on the remote machine running as the user harry. The svnserve command is being invoked in tunnel mode (-t) and its network protocol is being 「tunneled」 over the encrypted connection by ssh, the tunnel-agent. svnserve is aware that it's running as the user harry, and if the client performs a commit, the authenticated username will be used as the author of the new revision.

ここで重要なのは Subversion クライアントはsvnserve デーモンに接続するわけではないということです。 このアクセス方法はデーモンは不要で、存在しているかどうかを知る必要も ありません。実際には sshが一時的に起動する svnserve プロセスにだけ依存していて、ネットワーク接続が閉じるとそのプロセスも終了します。

svn+ssh://の URL を使ってリポジトリにアクセスする 場合、認証を要求するのはsshプログラムであり svnクライアントプログラムではないことを思い出して ください。これは自動的なパスワードのキャッシュが起きないことを 意味します(クライアント証明のキャッシュ項を見てください)。 Subversion クライアントはリポジトリに複数の接続を張ることもよくあります がユーザはパスワードキャッシュの仕組みによって通常そのことに気づくことは ありません。しかし svn+ssh:// URL を使う場合には ユーザは接続ごとに sshが繰り返しパスワードをうながす ことに悩ませられるかも知れません。解決策は Unix 風のシステムなら ssh-agent、Windows なら pageant のような独立した SSH パスワードキャッシュツールを利用することです。

When running over a tunnel, authorization is primarily controlled by operating system permissions to the repository's database files; it's very much the same as if Harry were accessing the repository directly via a file:// URL. If multiple system users are going to be accessing the repository directly, you may want to place them into a common group, and you'll need to be careful about umasks. (Be sure to read 複数リポジトリアクセス方法のサポート項.) But even in the case of tunneling, the svnserve.conf file can still be used to block access, by simply setting auth-access = read or auth-access = none. [42]

You'd think that the story of SSH tunneling would end here, but it doesn't. Subversion allows you to create custom tunnel behaviors in your run-time config file (see 実行時設定領域項). For example, suppose you want to use RSH instead of SSH[43]. In the [tunnels] section of your config file, simply define it like this:

[tunnels]
rsh = rsh

And now, you can use this new tunnel definition by using a URL scheme that matches the name of your new variable: svn+rsh://host/path. When using the new URL scheme, the Subversion client will actually be running the command rsh host svnserve -t behind the scenes. If you include a username in the URL (for example, svn+rsh://username@host/path) the client will also include that in its command (rsh username@host svnserve -t). But you can define new tunneling schemes to be much more clever than that:

[tunnels]
joessh = $JOESSH /opt/alternate/ssh -p 29934

この例はいろいろなことの参考になります。まずそれはどのようにして Subversion クライアントが非常に特殊なトンネリングのためのプログラムを 特定のオプション付きで起動するかを示しています(この場合それは /opt/alternate/sshにあります)。 この場合svn+joessh:// URLにアクセスすると 引数として-p 29934の付いた特定のSSHプログラム が起動されるでしょう— もし標準ではないポートにトンネルプログラム を接続したいと考えているならこれは便利です。

次にそれはどのように してトンネルプログラムの名前を上書きする環境変数を定義してやれば 良いかを示しています。 SVN_SSH環境変数を設定するのはデフォルトの SSH トンネル エージェントを上書きする便利な方法です。 しかしもし異なるサーバ上でいくつもの異なる上書きが必要で、それぞれが 異なるポートや異なるオプションを SSH に渡しているような場合には、この例で 示すような仕組みを利用することができます。 もしJOESSH環境変数を設定 してあれば、その値はトンネル変数全体を上書きします— $JOESSH/opt/alternate/ssh -p 29934のかわりに実行 されるでしょう。

SSH 設定の技法

クライアントが sshを起動する方法を制御できるだけ ではなく、サーバマシン上の sshdの動作の仕方も 制御することができます。この節では sshd によって起動される svnserveコマンドを正しく制御する 方法を示して、複数のユーザが単一システムアカウントをどのように共有すれば 良いかについて説明します。

初期設定

まずsvnserveを起動するのに使うアカウントの ホームディレクトリを用意します。そのアカウントに SSH の公開鍵/秘密鍵 がインストールされていて、ユーザがその公開鍵でログインできることを 確認してください。パスワード認証は動作しなくなりますが、それは以下の SSH の技法を使うと、すべての処理に SSH authorized_keysファイル を使うためです。

まだ存在していなければauthorized_keysファイルを 作ってください(Unix では普通 ‾/.ssh/authorized_keys になります)。このファイルの各行には接続を許す相手先の公開鍵の記述があります。 各行は普通以下のような形をしています:

ssh-dsa AAAABtce9euch… user@example.com

The first field describes the type of key, the second field is the base64-encoded key itself, and the third field is a comment. However, it's a lesser known fact that the entire line can be preceded by a command field:

command="program" ssh-dsa AAAABtce9euch… user@example.com

commandフィールドが設定されると 通常の svnserve -t のかわりに SSH デーモンがその名前のプログラムを実行します。このプログラムが Subversion クライアントの接続先になります。これがサーバ上でのいろいろな技法を 可能にする鍵です。以下の例では、ファイル中で次のように行を省略して説明します:

command="program" TYPE KEY COMMENT

起動コマンドの制御

実行されるサーバ側コマンドを指定することができるので、特定の svnserveバイナリを指定したり、追加の引数を 指定して実行することが簡単にできます:

command="/path/to/svnserve -t -r /virtual/root" TYPE KEY COMMENT

この例では /path/to/svnservesvnserve に対するカスタマイズされたラッパースクリプ トで、umask を設定するようなものかも知れません(複数リポジトリアクセス方法のサポート項を見てください)。それはまた svnserve用の仮想ルートディレクトリをどのように設定 するかも示しています。これはデーモンプロセスとして svnserveする場合によく起こることです。たとえばシス テムの特定の部分にアクセス制限する場合や、単に svn+ssh:// URL の絶対パス名を入力する手間を省くため であったりします。

複数のユーザが単一アカウントを共有するようにもできます。それにはまずユー ザごとに独立したシステムアカウントを作るかわりに、メンバーごとに公開鍵 /秘密鍵のペアを生成します。つぎに一行に公開鍵をひとつづつ authorized_users ファイルにおきます。そして --tunnel-user オプションを使うとうまくいきます。

command="svnserve -t --tunnel-user=harry" TYPE1 KEY1 harry@example.com
  command="svnserve -t --tunnel-user=sally" TYPE2 KEY2 sally@example.com

この例では Harry も Sally も公開鍵認証方式によって同じアカウントで接続する ように設定しています。どちらもそれぞれにカスタマイズされたコマンドが実行されます; --tunnel-userオプションは svnserve -t が名前つき引数が認証されたユーザであることを認めるように指示しています。 --tunnel-user がなければ、すべてのコミットはひとつの共有された システムアカウントから発行したように見えるようになります。

最後の注意です: 共有アカウントにある公開鍵を経由してユーザにアクセス権を 与えても、他の形の SSH アクセスを禁止したことにはなりません。これは authorized_keyscommandの 形の設定をした場合でもそうです。たとえば、ユーザは依然として SSH 経由で シェルを使ったアクセスができますし、あなたのサーバ経由で X11 や、より 一般的なポートフォワードを実行することもできます。ユーザにできるかぎり わずかな権限しか与えないようにするには commandの すぐ後にそれぞれの制限オプションを指定する必要があります:

command="svnserve -t --tunnel-user=harry",no-port-forwarding,¥
           no-agent-forwarding,no-X11-forwarding,no-pty ¥
           TYPE1 KEY1 harry@example.com


[41] See RFC 2195.

[42] Note that using any sort of svnserve-enforced access control at all is a bit pointless; the user already has direct access to the repository database.

[43] We don't actually recommend this, since RSH is notably less secure than SSH.