第6回 仮想ディレクトリとマッピングの設定

実ディレクトリ構成とWebサイトの構造は必ずしも同一ではない。これを矛盾なく整合させる仕組みが「仮想ディレクトリ」と「マッピング」である。Webサイトを構築するには、この2つを理解しておく必要がある。

2001/6/23

仮想ディレクトリを設定する理由

 仮想ディレクトリとは、URLで指定されるディレクトリを指す。例えば、http://www.atmarkit.co.jp/images/と指定された場合、/images/はwww.atmarkit.co.jpの仮想ディレクトリである。

 仮想ディレクトリは、当然のことながらサーバ上の実ディレクトリ構造と同一ではない。つまり、www.atmarkit.co.jpでアクセスされるサーバに/imagesというディレクトリは存在しない。もっと分かりやすくいえば、Windowsではディレクトリをこのように表記することはない。実際のディレクトリはc:\www\imagesかもしれないし、UNIXやLinuxであれば/home/www/imagesかもしれないのである。そこで、Webサーバは実際のディレクトリと仮想ディレクトリの「マッピング」と呼ばれる作業を行う。

 ただし、マッピングはすべての仮想ディレクトリに対して必要なものではない。前回、ドキュメントルートの設定を紹介した。ドキュメントルート(DocumentRootディレクティブ)は、仮想ルートディレクトリを設定する。もし、www.atmarkit.co.jpのドキュメントルートが/home/www/だとすれば、http://www.atmarkit.co.jp/index2.htmlというリクエストは/home/www/index2.htmlに対するアクセスとなるわけだ。

 このとき、/home/www/に/images/というサブディレクトリがあったとしよう。この場合、特にマッピングしなくてもこのディレクトリにはhttp://www.atmarkit.co.jp/images/でアクセスできる。つまり、マッピング済みディレクトリのサブディレクトリはあらためてマッピングを行う必要がない、ということだ。

図1 実ディレクトリと仮想ディレクトリの対応

 もちろん、その名前を変えてアクセスさせたい場合は、あらためてマッピングを行う必要がある。例えば、/images/でもアクセスできるところを/pictures/としたければマッピングが必要になる。ただし、/images/を/pictures/にマッピングしても、元の仮想ディレクトリ(/images/)も有効だから注意していただきたい。

 また、マッピングと関係のないディレクトリは、当然マッピングを行わなくてはならない(図1)。

仮想ディレクトリとマッピング

仮想ディレクトリの設定方法

 マッピングは、httpd.confのAliasディレクティブを利用する。このディレクティブの使い方は、実に簡単である。

Alias 仮想ディレクトリ 実ディレクトリ

のように記述するだけだ。例えば、/home/www/imagesディレクトリを/images/にマッピングしたければ、

Alias /images/ "/home/www/images/"

と記述する。記述する位置はどこでも構わないのだが、ほかのマッピングと同じ位置に書いた方が分かりやすい。

 Apache導入時に作成されるデフォルトのhttpd.confを見ると分かるが、Aliasディレクティブは<IfModule mod_alias.c></IfModule>の間に記述されている。これは、Aliasディレクティブがmod_aliasと呼ばれるモジュールの機能を使っているためである。

 mod_aliasモジュールは、Apacheのインストール時に自動的にインストールされるモジュールの1つだ。従って、そのモジュールが存在するかどうかをチェックする必要はないのだが、デフォルトの状態ではチェックするようになっている。それが<IfModule>ディレクティブの役割であり、モジュールが存在する場合はその中のディレクティブを読み込むようになっている。従って、Aliasディレクティブを新たに追加するのなら、<IfModule mod_alias.c>〜</IfModule>の間に記述することを勧める。

スクリプトディレクトリのマッピング

 新しく仮想ディレクトリをマッピングする場合とマッピング済みの仮想ディレクトリに別名でアクセスしたい場合。仮想ディレクトリを作成する理由を2種類説明したのだが、実はもう1つ理由が存在する。それが、スクリプトディレクトリをマッピングする場合である。

 スクリプトディレクトリとは、一般にCGIプログラムと呼ばれるプログラムのファイルを配置するディレクトリを意味する。CGIプログラムは、URLでアクセスを受けるとWebサーバによって実行される。プログラムを配置するディレクトリはほかのファイル(HTMLや画像)とは別のディレクトリにしなくてはならない。なぜなら、Webサーバにはプログラムファイルとほかのファイルの区別がつかないからである。

 Webサーバは、プログラムとして実行すべきかどうかをディレクトリの単位で判断する。「プログラムを置くディレクトリである」と宣言されていれば、そのディレクトリ内のファイルはすべてプログラムであると判断するのだ。そして、それらのファイルにアクセスがあればプログラムとして実行する(図2)。

図2 ScriptAliasによるCGIの実行指定

 プログラムを配置するディレクトリと一般のディレクトリを区別する設定は、ScriptAliasディレクティブで行う。ディレクティブの名称が異なるだけで、書式などはAliasディレクティブと同じだ。Apacheは、Aliasディレクティブで宣言された仮想ディレクトリか、ScriptAliasで宣言された仮想ディレクトリかで読み取りと実行の区別をつける。

 サイトマップを作成する際は、プログラムを配置するディレクトリか否かを明確にしておかなくてはならない。できれば、プログラムの種類(PHP、Perl、JSPなど)に応じてディレクトリを分け、できるだけ分かりやすくしておく方がいいだろう。サイトマップが完成したら、それに合わせてAliasディレクティブとScriptAliasディレクティブの設定を行えばいい。

 ただし、ScriptAliasディレクティブはCGIプログラムにだけ利用することを忘れないでほしい。JSPやPHPもプログラムに違いはないのだが、通常はApache本体が実行するものではない。あくまでも、拡張モジュールなどを必要としないCGIプログラムにだけ使う、と理解しておいていただきたい。

ユーザーディレクトリとCGI

 マッピングの話はこれくらいにして、「ユーザーディレクトリ」に目を向けよう。この機能は、もう1つの仮想ディレクトリともいえる機能だ。Apacheに限らず、ほとんどのWebサーバがこの機能を備えるが、残念ながらWindowsでは使えない。なぜなら、この機能はUNIXのホームディレクトリを活用した機能だからだ。

ユーザーディレクトリの設定

 UNIXやLinuxでは、ユーザー作成時にそのユーザーのホームディレクトリを設定する。例えば、ichishiというユーザーを作るときに、/home/ichishiをホームディレクトリとする、といった具合だ。ユーザーは、システムにログインすると必ずホームディレクトリに導かれる。通常は、1ユーザーに対して1つのホームディレクトリが作成される。そこには個人的なファイルや各ユーザーの設定ファイルなどが配置される。

 この機能を生かし、ユーザーごとにWebページを管理できるようにしよう、というのが「ユーザーディレクトリ」機能である。http://〜/~ichishi/というようなURLを見かけたことがあるだろう。これがまさにユーザーディレクトリである。

 http://〜/~ichishi/というURLは、ユーザーichishiのユーザーディレクトリにアクセスする、という意味を持つ。従って、別のユーザーのユーザーディレクトリにアクセスしたければ、http://〜/~ユーザー名/とすればよい。これは、多くの商用プロバイダがユーザーのWebページを公開するのに利用している機能だ。

 問題は、これらのユーザーディレクトリについて、Webサーバがどのような振る舞いをするかである。ユーザーには、それぞれにホームディレクトリがあるのだから、そこにアクセスすれば話は早い。しかし、ユーザーも自分のホームディレクトリ直下にWebページのためのファイルを置きたいとは思わないだろう。それに、そんなことをしたらホームディレクトリ以下のファイルにアクセスされ放題になってしまう。

図3 ホームディレクトリとユーザーディレクトリ

 そこで、Webページ用のファイルを置く特別なディレクトリを設定する。例えば「public_html」といった具合だ。ただし、このディレクトリ名は全ユーザー共通にしなければならない。

 すべてのユーザーで共通のディレクトリ名を使うことで、Webサーバ側の設定は非常に簡単なものになる。上記の例であれば、ユーザーディレクトリへは、そのユーザーのホームディレクトリ直下を参照して「public_html」以下のファイルにアクセスする、という具合に共通化できるからだ(図3)。

 Apacheでは、この機能をmod_userdirというモジュールでサポートする。このモジュールも、通常はデフォルトでインストールされる。設定するディレクティブも簡単で、UserDirディレクティブに、全ユーザーで共通のディレクトリ名を記述するだけである。例えば、

UserDir public_html

とすればpublic_htmlがユーザーディレクトリとなる。

 あとは、Webページを公開したいユーザーが、自分のホームディレクトリにpublic_htmlディレクトリを作成し、そこにWebページ用のファイルを配置するだけである(補足)。もちろん、サブディレクトリを作成すれば、そこにアクセスすることだってできる。できないのは、ユーザーディレクトリに設定されたディレクトリ以外でWebページを公開することだけである。ユーザーディレクトリは、いってみれば各ユーザー用の仮想ルートディレクトリだから、すべてのファイルはユーザーディレクトリ以下に配置しなくてはならない。 この機能は非常に便利だ。例えば、部門イントラネットサーバに部員のユーザーを作れば、部員各自のWebページを公開できる。UNIXやLinuxの知識がなくても、GUIで作られたFTPクライアントを使ってファイルをアップロードするくらいは難しくない。

補足
  単にユーザーディレクトリを設定しただけでは、アクセス権がない(You don't have permission...)とエラーになることがある。

 これは、ユーザーのホームディレクトリやそれ以下のディレクトリなどに適切なアクセス権限がないために起きる。Apacheは、「nobody」と呼ばれる最も権限の弱いユーザーとして、URLでリクエストされたファイルにアクセスする。ファイルやディレクトリがこのnobodyでも読み込めるように設定されていなければ、上記のようなエラーになってしまうのだ。

  例えば、/home/ichishi/public_html/index.htmlにアクセスできないのであれば、/home/に移動してichishiディレクトリのパーミッションを調べる。これが700や750であれば、755もしくは744に設定する。もちろん、パーミッションを緩めればそれだけセキュリティが脆弱になることは否めない。

ユーザーディレクトリでのCGI実行

 ユーザーディレクトリを設定して各自のWebページを公開できるようにすると、1つの問題が浮かび上がってくる。それは、各自が自由にCGIプログラムを実行できないのか、ということだ。インターネット上には興味深い多くのCGIプログラムが公開されている。それはアクセス数のカウンタであったり、メッセージをティッカーのように流すものであったり、実にさまざまだ。これを各自が実行したい、といった場合どうすればいいのだろうか。

 これを実現する設定はもちろん可能なのだが、ネガティブな要素もつきまとう。それは、セキュリティに対する問題にほかならない。

 各自がCGIプログラムを実行できるようにすると、セキュリティ面で問題のあるプログラムも容易に実行できることになってしまう。ユーザーにそういった意識がなくとも、システムの重要なファイルを盗み見られる可能性があるのだ。従って、外部に公開するサーバでCGIプログラムを自由に実行させるのはお勧めできない。どうしても許さざるを得ないのであれば、責任を持って監査するなり商用プロバイダが行っているような制限をつけるべきだ。

 それを前提にすれば、設定そのものは大して難しくない。以下に示すような一文を、仮想ディレクトリの設定位置(<IfModule mod_alias.c>〜<IfModule>の間)に記述するだけだからだ。

ScriptAliasMatch /~(..*)/cgi-bin/(.*) /home/$1/public_html/cgi-bin/$2

 この文は、/~ichishi/cgi-bin/test.plへのアクセスであれば、/home/ichishi/public_html/cgi-bin/test.plを参照するように設定している。正規表現を用いているので分かりづらいかもしれない。いずれにしても、ホームディレクトリを「/home/ユーザー名」、ユーザーディレクトリを「public_html」であると仮定している。そして、その直下にある「cgi-bin」をスクリプトディレクトリとし、cgi-binという仮想パスでアクセスできるようにしているのだ。

 このように、設定そのものは難しくないが、運用の方が難しくなる。何しろ、ファイルの権限は実行可能(755など)にしなくてはならないし、Perlを使うのであればPerlのインストールパスを伝えなくてはならない。さらには、セキュリティの確保も必要だ。それら、すべてをクリアできるのであればこうした設定も悪くはないだろう。

 もちろん、このディレクトリに対してセキュリティ設定を施すこともできる。その方法については、次回詳しくお伝えすることにしよう。