Home > Virtual Hosting | English

Virtual Hosting

Contact

実験: Apacheバーチャルホストの動的設定

最近、KobuComのWeb・メールサーバをよりお手頃なVPS(virtual private server)に移し、Let's Encryptの無料SSL証明書を追加しました。 その過程で、Apacheウェブサーバの「大量の仮想ホストの動的設定」(dynamically configured mass virtual hosting)を試したので、その体験を紹介します。

設定したドメイン数はたかだか三つですが、それでも同じ設定を何度も繰り返すのは気持ちが悪いので、この方法は精神的によいです。

三つの方式

VirtualHostを繰り返さなくてよい方法を調べていたら次の問答が見つかりました。

Sharing configuration between several VHosts
https://stackoverflow.com/questions/18714293/sharing-configuration-between-several-vhosts

Apacheが三つの方式を提唱しているとの回答がありました。

モジュール 説明 難易度 柔軟性
mod_vhost_alias 可変パスの指定 簡単 制限あり
mod_macro マクロ展開 比較的簡単 それほど制限はない
mod_rewrite URL書き換え 難易度高し 無制限

そこで最初の二つを試してみて、最終的にHTTP Port 80ではmod_vhost_aliasを、HTTPS port 443ではmod_macroでサイトの設定を行いました。

実験で使った簡単な設定例を順にお見せします。 ローカルLANのRaspberry PiのRaspbian (Debian 10)のApache2 v2.4.38でテストしました。 Apacheの基本設定、仮想ホストの設定(名前利用/IP利用の違いなど)の知識を前提にしています。 Apacheの関連リンクはページの最後にまとめてあります。

静的な設定

以下の例では次のふたつのドメインを使用します。 ここではIPで分ける方法ではなく(IP-based)名前で分ける方法(name-based)を使います。

従来の静的な設定は次のとおりです。

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/html
    ScriptAlias "/cgi-bin/" "/var/www/example.com/cgi-bin/"
    # other settings
</VirtualHost>

<VirtualHost *:80>
    ServerName example.org
    ServerAlias www.example.org
    DocumentRoot /var/www/example.org/html
    ScriptAlias "/cgi-bin/" "/var/www/example.org/cgi-bin/"
    # other settings
</VirtualHost>

このように対象ドメインの数だけVirtualHostの設定が必要です。

mod_vhost_alias

はじめにvhost_aliasモジュールを使う方法を試します。 このモジュールはDebian 10でもCentOS 8でも元から入ってました。 Debianの場合はa2enmodで有効にしてください。

mod_vhost_aliasを用いたVirtualHostの記述例です。

<VirtualHost *:80>
  UseCanonicalName Off
  VirtualDocumentRoot "/var/www/%-2.0.%-1.0/html"
  VirtualScriptAlias "/var/www/%-2.0.%-1.0/cgi-bin/"
  # other common settings can be added here
</VirtualHost>

UseCanonicalNameは要求元ドメイン名の決定方法を指定します。 "Off"はHostヘッダから、"DNS"はDNS逆検索を意味します。 Offは名前を使う仮想ホスティングで、DNSはIPアドレスを使うホスティングで使います。 VirtualDocumentRootとVirtualScriptAliasはそれぞれ静的または動的なコンテンツの置き場所を指定します。 IPベースの場合はかわりにVirtualDocumentRootIPとVirtualScriptAliasIPを使います。

要求受信時にホスト名から動的に決定される部分は「%-2.0.%-1.0」です。 これはドメイン名のドット(.)で区切られた最後の二つの部分を表します。 要求が「www.example.com」または「example.com」の場合、可変部分は「example.com」になります。 つまり「www」があってもなくても同じディレクトリを指すようにします。

パターンの表現

mod_vhost_aliasのパスの構成要素を表す文法については少し説明が必要と思います。 アパッチの文書にはふたつの表といくつかの例が記されています。 表を引用します。

可変のパターンは次のものを含みます。

%% insert a %
%p insert the port number of the virtual host
%N.M insert (part of) the name

NとMはいずれも次の値を取ります。

0 the whole name
1 the first part
2 the second part
-1 the last part
-2 the penultimate part
2+ the second and all subsequent parts
-2+ the penultimate and all preceding parts
1+ and -1+ the same as 0

「penultimate」は最後からひとつ前という意味です。

「www.example.com」を使っていくつかパターンを列挙します。

パターン 説明
%0 www.example.com ドメイン名全体
%1 www ドットで区切られた最初の要素
%-1 com 最後の要素
%1.0 www 最初の要素の文字列全体
%-1.0 com 最後の要素の文字列全体
%-2.0 example 最後よりひとつ前の要素の文字列全体
%1.1 w 最初の要素の最初の文字
%-1.-1 m 最後の要素の最後の文字

これで'%-2.0.%-1.0'の意味がおわかりかと思います。 '%-2.0'とドットに'%-1.0'が続いたもので、この例の場合は「example.com」です。

テスト

テストで用いたディレクトリ構成は次のとおりです。

$pwd
/var/www

$ ls
example.com/  example.org/

$ ls -R example.com
example.com:
cgi-bin/  html/

example.com/cgi-bin:
test.cgi*

example.com/html:
index.html

ファイルの中身を見ます。

$cat example.com/html/index.html
example.com

$cat example.com/cgi-bin/test.cgi
#!/bin/bash
echo 'Content-Type: text/plain'
echo ''
echo test.cgi of example.com running

example.orgも「com」が「org」になる以外は同じです。

HTMLファイルのテストをします。

$ curl http://example.com/
example.com
$ curl http://example.org/
example.org

次はCGIスクリプトです。

$ curl http://example.com/cgi-bin/test.cgi
test.cgi of example.com running
$ curl http://example.org/cgi-bin/test.cgi
test.cgi of example.org running

「www」を付けた場合も試します。

$ curl http://www.example.com/
example.com
$ curl http://www.example.com/cgi-bin/test.cgi
test.cgi of example.com running

vhost_aliasモジュールによる動的仮想ホスト設定は簡便ですが、可変にできるのがDocumentRootとScriptAliasだけです。 他の設定についてもドメイン固有にする必要がある場合はmod_vhost_aliasは使えません。 mod_macroモジュールはもっと柔軟です。

mod_macro

続いて試したのがmacroモジュールです。 このモジュールはDebian 10でもCentOS 8でも元から入ってました。 Debianの場合はa2enmodで有効にしてください。

mod_macroを用いたVirtualHostの記述例です。

<Macro VHost $domain>
<VirtualHost *:80>
    ServerName $domain
    ServerAlias www.$domain
    DocumentRoot "/var/www/$domain/html"
    ScriptAlias "/cgi-bin/" "/var/www/$domain/cgi-bin/"
    # other per-domain settings can be added here
</VirtualHost>
</Macro>

Use VHost example.com
Use VHost example.org

UndefMacro VHost

Macro VHostで始まり/Macroで終わる部分がマクロ定義です。 引数の$domainで可変のドメイン名を表します。 Use VHostで指定の$domainの値を持つ設定となるようマクロが展開されます。 この場合はexample.comとexample.org用に二個のVirtualHostブロックが作成されます。 UndefMacroはそれ以降ではマクロを参照しないむねの指定です。

テストしてみます。

$ curl www.example.com
example.com
$ curl www.example.org
example.org
$ curl example.com
example.com
$ curl example.org
example.org
$ curl example.com/cgi-bin/test.cgi
test.cgi of example.com running
$ curl example.org/cgi-bin/test.cgi
test.cgi of example.org running

最初のmod_vhost_aliasは本当の意味で動的な動作をします。 あらかじめ指定しなくても、配下のDNSで公開されているものなら、どんなドメイン名でも対象となります。 いっぽうmod_macroの場合はApache起動時にUseで指定されたドメインについて静的な設定が作られます。 それ以外のドメイン名は対象となりません。

mod_rewrite

最後の方式はrewriteモジュールでURLを任意に書き換える方法です。 Apacheのページにいくつか例が紹介されています。 うちひとつを引用します。 site.example.comを/home/site/wwwに差し向ける例です。

# SITE.example.com -> /home/SITE/www
RewriteEngine on
RewriteMap    lowercase int:tolower
RewriteCond   %{HTTP_HOST} !^www\.
RewriteCond   ${lowercase:%{HTTP_HOST}}   ^([^.]+)\.example\.com$
RewriteRule   ^(.*)    /home/%1/www$1

ただこのページには次のように書かれています。

mod_rewrite is usually not the best way to configure virtual hosts. You should first consider the alternatives before resorting to mod_rewrite.

「ほかの方法でダメな場合にのみmod_rewriteを使うように」と勧めています。 同感です。 mod_rewriteを使いこなすのはたいへんでデバッグに手間がかかります。 他人(あるいは半年前に自分)が書いたスクリプトを読みこなすのも困難です。 私は極力使わないようにしています。

仮想ホスト設定においては、まずmod_vhost_aliasで済ませられるかどうか判断し、ダメならmod_macroを使う、という対応がよいように思います。

References

Dynamically Configured Mass Virtual Hosting
https://httpd.apache.org/docs/trunk/vhosts/mass.html

Apache Module mod_vhost_alias
http://httpd.apache.org/docs/2.4/mod/mod_vhost_alias.html

Apache Module mod_macro
http://httpd.apache.org/docs/2.4/mod/mod_macro.html

Dynamic mass virtual hosts with mod_rewrite
https://httpd.apache.org/docs/trunk/rewrite/vhosts.html

An In-Depth Discussion of Virtual Host Matching
https://httpd.apache.org/docs/2.4/vhosts/details.html

お知らせ

ネットインフラ・サイト構築のご用命があれば承ります。 できるだけリモートで進めたいと思います。 ご相談ください。

Written 2020-May-03