Apache HTTP サーバ バージョン 2.4
この文書は、バーチャルホストの設定の際に よくある質問に答えるものです。想定している対象は 名前ベース や IP ベース のバーチャルホストを使って 一つのサーバで複数のウェブサイトを運用している状況です。
Virtual_host
と
mod_proxy を併用する_default_
のバーチャルホストを
使うServerPath
ディレクティブを
使うサーバは IP アドレスを一つ割り当てられていて、DNS でマシンに
複数の名前 (CNAME) が指定されています。このマシンで
www.example.com
と www.example.org
のためのウェブサーバを実行させたいとします。
Apache サーバの設定でバーチャルホストの設定をしただけで、
知らない間にそのホスト名に対応する DNS のエントリが
作成されたりはしません。そのサーバの IP アドレスに解決される
ように DNS に名前を登録しなければなりません。
そうでないと誰もあなたのウェブサイトを見ることはできません。
ローカルでのテストのために hosts
ファイルに
エントリを追加することもできますが、この場合はその
hosts エントリのあるマシンからしか動作しません。
# Ensure that Apache listens on port 80
Listen 80
# Listen for virtual host requests on all IP addresses
NameVirtualHost *:80
<VirtualHost *:80>
DocumentRoot /www/example1
ServerName www.example.com
# Other directives here
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /www/example2
ServerName www.example.org
# Other directives here
</VirtualHost>
アスタリスクはすべてのアドレスにマッチしますので、主サーバは
リクエストを扱いません。www.example.com
は
最初にあるため、優先順位は一番高くなり、default もしくは
primary のサーバと考えることができます。つまり、リクエストが
どの ServerName
ディレクティブにもマッチしない場合、
一番最初の VirtualHost
により扱われます。
*
をシステムの実際の IP アドレスに置き換える
こともできます。その場合は VirtualHost
の引数は
NameVirtualHost
の引数と同じにしなければなりません
:
NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40>
# etc ...
しかし、IP アドレスが予測不可能なシステム
――例えばプロバイダから動的に IP アドレスを取得して何らかの
ダイナミック DNS を使っている場合など――においては、*
指定はさらに便利です。*
はすべての IP アドレスに
マッチしますので、この設定にしておけば IP アドレスが変更されても
設定変更せずに動作します。
名前ベースのバーチャルホスティングではほぼすべての状況で、 上記の設定で希望の設定になっていることでしょう。 実際この設定が動作しないのは、IP アドレスやポートの違いによって 違うコンテンツを送るときだけです。
ここで説明されている方法は IP アドレスが 何個あっても同様にできます。
サーバには二つ IP アドレスがついています。一つ目
(172.20.30.40
) では主サーバ
server.domain.com
を扱い、もう一方
(172.20.30.50
) では二つかそれ以上の数の
バーチャルホストを扱います。
Listen 80
# This is the "main" server running on 172.20.30.40
ServerName server.domain.com
DocumentRoot /www/mainserver
# This is the other address
NameVirtualHost 172.20.30.50
<VirtualHost 172.20.30.50>
DocumentRoot /www/example1
ServerName www.example.com
# Other directives here ...
</VirtualHost>
<VirtualHost 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example.org
# Other directives here ...
</VirtualHost>
172.20.30.50
以外のアドレスへのリクエストは主サーバ
が扱います。172.20.30.50
への、未知のホスト名または
Host:
ヘッダなしのリクエストは www.example.com
が扱います。
サーバマシンは IP アドレスを二つ (192.168.1.1
と 172.20.30.40
) 持っています。このマシンは内部
(イントラネット) と 外部 (インターネット) のネットワークの間に
あります。server.example.com
はネットワークの外からは
外部アドレス (172.20.30.40
) として解決されますが、
ネットワークの中からは内部アドレス (192.168.1.1
)
として解決されます。
VirtualHost
一つだけでサーバが内部のリクエストと
外部のリクエストの両方に同じコンテンツで応答するようにできます。
NameVirtualHost 192.168.1.1
NameVirtualHost 172.20.30.40
<VirtualHost 192.168.1.1 172.20.30.40>
DocumentRoot /www/server1
ServerName server.example.com
ServerAlias server
</VirtualHost>
これでどちらのネットワークからのリクエストも同じ VirtualHost
で扱われるようになります。
内部ネットワークでは完全なホスト名の
server.example.com
の代わりに、単に server
を使うことができます。
上の例では、IP アドレスのリストを、すべてのアドレスに
同じコンテンツで応答する *
に置き換えられます。
同じ IP に複数のドメインがあり、さらに複数のポートを使って リクエストを扱いたいときがあります。"NameVirtualHost" タグの中で ポートを定義することで、これを動作させられます。 NameVirtualHost name:port 無しや Listen ディレクティブで <VirtualHost name:port> を使おうとしても、その設定は動作しません。
Listen 80
Listen 8080
NameVirtualHost 172.20.30.40:80
NameVirtualHost 172.20.30.40:8080
<VirtualHost 172.20.30.40:80>
ServerName www.example.com
DocumentRoot /www/domain-80
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
ServerName www.example.com
DocumentRoot /www/domain-8080
</VirtualHost>
<VirtualHost 172.20.30.40:80>
ServerName www.example.org
DocumentRoot /www/otherdomain-80
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
ServerName www.example.org
DocumentRoot /www/otherdomain-8080
</VirtualHost>
サーバは www.example.com
と www.example.org
にそれぞれ解決される、二つの IP アドレス (172.20.30.40
と
172.20.30.50
) があります。
Listen 80
<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example.org
</VirtualHost>
<VirtualHost>
ディレクティブのどれでも
指定されていないアドレス (例えば localhost
) は、
主サーバがあればそこに行きます。
サーバマシンはそれぞれ www.example.com
と
www.example.org
にそれぞれ解決される、IP アドレスを二つ
(172.20.30.40
と 172.20.30.50
) 持っています。
どちらもポート 80 と 8080 でホストを走らせます。
Listen 172.20.30.40:80
Listen 172.20.30.40:8080
Listen 172.20.30.50:80
Listen 172.20.30.50:8080
<VirtualHost 172.20.30.40:80>
DocumentRoot /www/example1-80
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
DocumentRoot /www/example1-8080
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.50:80>
DocumentRoot /www/example2-80
ServerName www.example.org
</VirtualHost>
<VirtualHost 172.20.30.50:8080>
DocumentRoot /www/example2-8080
ServerName www.example.org
</VirtualHost>
いくつかのマシンでは名前ベースの、その他では IP ベースのバーチャル ホストをします。
Listen 80
NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example.com
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/example2
ServerName www.example.org
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/example3
ServerName www.example3.net
</VirtualHost>
# IP-based
<VirtualHost 172.20.30.50>
DocumentRoot /www/example4
ServerName www.example4.edu
</VirtualHost>
<VirtualHost 172.20.30.60>
DocumentRoot /www/example5
ServerName www.example5.gov
</VirtualHost>
Virtual_host
と
mod_proxy を併用する次の例は、フロント側のバーチャルホストで他のマシンへプロクシします。
例では 192.168.111.2
のマシンではバーチャルホスト名は
同じ名前で設定されています。複数のホスト名を一台のマシンにプロクシする
場合は、ProxyPreserveHost On
ディレクティブを使って、希望のホスト名を渡せるようになります。
<VirtualHost *:*>
ProxyPreserveHost On
ProxyPass / https://192.168.111.2/
ProxyPassReverse / https://192.168.111.2/
ServerName hostname.example.com
</VirtualHost>
_default_
のバーチャルホストを
使う_default_
バーチャルホスト未指定の IP アドレスとポート、つまり他のバーチャルホストに 使われていないアドレスとポートの組み合わせ、へのすべてのリクエストを 受け取ります。
<VirtualHost _default_:*>
DocumentRoot /www/default
</VirtualHost>
このようにワイルドカードのポートでデフォルトのバーチャルホストを 指定すると、主サーバにリクエストが行くのを防げます。
デフォルトのバーチャルホストは名前ベースのバーチャルホストに
使われているアドレスとポートの組に送られたリクエストを扱うことは
ありません。リクエストが不明な Host:
ヘッダやその
ヘッダがなかったりする場合は基本名前ベースバーチャルホスト (その
アドレスとポートで設定ファイル中で最初のバーチャルホスト) により
扱われます。
どんなリクエストでも AliasMatch
や RewriteRule
を使って
単一の情報ページ (やスクリプト) に書き換えることができます。
_default_
バーチャルホスト一つめの設定とほぼ同じですが、サーバは複数のポートを listen しており、
80 番ポートに対して二つめの _default_
バーチャルホストを
設定したい場合です。
<VirtualHost _default_:80>
DocumentRoot /www/default80
# ...
</VirtualHost>
<VirtualHost _default_:*>
DocumentRoot /www/default
# ...
</VirtualHost>
80 番ポートのデフォルトバーチャルホスト (ワイルドカードポートの デフォルトバーチャルホストよりも前に書かれていなければなりません) は 未指定の IP アドレスに送られたすべてのリクエストを扱います。 主サーバはリクエストを扱いません。
_default_
バーチャルホスト80 番ポートにはデフォルトのバーチャルホストが必要で、他の バーチャルホストはデフォルトが必要ない場合です。
<VirtualHost _default_:80>
DocumentRoot /www/default
...
</VirtualHost>
80 番ポートへのアドレス未指定のリクエストはデフォルトのバーチャル ホストから送られます。他の未指定のアドレスとポートへのリクエストは 主サーバから送られます。
ホスト名が名前 www.example.org
のバーチャルホスト
(名前ベースの例の 2 番目の設定) が専用の IP アドレスを
得たとします。名前ベースのバーチャルホストの古い IP アドレスを
キャッシュしているネームサーバやプロキシのために移行期間中は両方の
バーチャルホストを提供したいとします。
答は簡単です。単に新しい IP アドレス (172.20.30.50
)
を VirtualHost
ディレクティブに追加することで
できます。
Listen 80
ServerName www.example.com
DocumentRoot /www/example1
NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example.org
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/example3
ServerName www.example.net
ServerAlias *.example.net
# ...
</VirtualHost>
このバーチャルホストは新しいアドレス (IP ベースのバーチャルホストとして) と古いアドレス(名前ベースのバーチャルホストとして) の両方から アクセスできます。
ServerPath
ディレクティブを
使う名前ベースのバーチャルホストが二つあるサーバがあるとします。
正しいバーチャルホストを得るためにはクライアントは正しい
Host:
ヘッダを送らなければなりません。
古い HTTP/1.0 はそのようなヘッダを送らないので、Apache はクライアントが
どのバーチャルホストを意図したのかさっぱりわかりません
(なので、主バーチャルホストでリクエストを扱います)。
可能な限りの下位互換性を得るため、名前ベースのバーチャルホストの
URL 接頭辞へのリンクの書かれたページを返す、
主バーチャルホストが作成されます。
NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40>
# primary vhost
DocumentRoot /www/subdomain
RewriteEngine On
RewriteRule ^/.* /www/subdomain/index.html
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/subdomain/sub1
ServerName www.sub1.domain.tld
ServerPath /sub1/
RewriteEngine On
RewriteRule ^(/sub1/.*) /www/subdomain$1
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/subdomain/sub2
ServerName www.sub2.domain.tld
ServerPath /sub2/
RewriteEngine On
RewriteRule ^(/sub2/.*) /www/subdomain$1
# ...
</VirtualHost>
ServerPath
ディレクティブの設定に
より、URL https://www.sub1.domain.tld/sub1/
は
常に sub1-vhost により扱われます。URL
https://www.sub1.domain.tld/
へのリクエストは
クライアントが正しい Host:
ヘッダを送ったときにのみ
sub1-vhost から送られます。Host:
ヘッダがなければ
クライアントは主ホストの情報ページを得ます。
一つ奇妙な動作をする点があることは覚えておいてください。
https://www.sub2.domain.tld/sub1/
へのリクエストも
Host:
ヘッダがなければ sub1-vhost により扱われます。
正しい Host:
ヘッダを送ったクライアントはどちらの
URL、つまり接頭辞がある方も無い方も使えるように
RewriteRule
ディレクティブが
使われています。