Apache VirtualHostの効率的な管理方法
ってどうするのが良いのでしょうか。今回の条件は下記として...
とりあえず最近は、開発環境向けにこんな感じで設定している。
設定が変わるたびにいろいろな箇所を修正するのが大変なので、可能な限り共通部分は別ファイルに切りだしてIncludeするように。
conf/ httpd.conf conf.d/ vhost/ example.com.conf _example.com.conf _ssl.conf
- サーバ全体に対する設定はhttpd.confとconf.d/*.confに記述。
- httpd.confの末尾で、VirtualHostの設定ファイルをInclude。
- conf.d/vhost 以下に example.com.conf のようなドメイン別ファイルを用意。
- 80番,443番で共通の設定は _example.com.confのようにドメイン内の共通ファイルを作成し、ドメイン別ファイルからIncludeする。
- SSLでの共通設定はドメインを超えて _ssl.conf に記述し、各ドメイン別ファイルからIncludeする。
いろいろ端折ってるけどファイルの中身はこんな感じ。
conf/httpd.conf
# ...上部でサーバ全体向けの設定 NameVirtualHost *:80 NameVirtualHost *:443 Include conf.d/vhost/example.com
conf.d/vhost/example.com.conf
<VirtualHost *:80> Include conf.d/vhost/_example.com.conf </VirtualHost> <VirtualHost *:443> Include conf.d/vhost/_example.com.conf Include conf.d/vhost/_ssl.conf </VirtualHost>
conf.d/vhost/_example.com.conf
ServerName example.com ServerAlias www.example.com DirectoryIndex index.php DocumentRoot "/path/to/example.com/www" <Directory "/path/to/example.com/www"> AllowOverride All Allow from All </Directory> CustomLog logs/example.com/access_log combined ErrorLog logs/example.com/error_log
conf.d/vhost/_ssl.conf
SSLEngine on SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key SetEnvIf User-Agent ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0
で、サービスのVirtualHostを追加するごとに、example.com.conf, _example.com.confが増えていく感じ。
mod_rewriteでリダイレクトあれこれ
ドメインの正規化
wwwあり・なしをどちらか片方に寄せたい場合。
今回はwww.example.comなど、example.com以外でアクセスされたらexample.comにリダイレクトする設定。
<VirtualHost *:80> # (1) ServerName example.com ServerAlias www.example.com RewriteEngine On # (2) RewriteCond %{HTTP_HOST} !^example\.com # (3) RewriteRule .* http://example.com$0 [QSA,NE,R=301,L] </VirtualHost>
(1)で、どちらのホスト名でもVirtualHostが動くようにする。
(2)は正規表現の末尾に$を付けないようにする。Hostリクエストヘッダは
Host = "Host" ":" host [ ":" port ] ; Section 3.2.2
http://www.studyinghttp.net/header#Host
と定義されているように、host名の後に「:ポート番号」が付与される形式がある。
例えば http://www.example.com:80/ にアクセスした場合に
Host: www.example.com:80
と送ってくるクライアントに対応できないので、前方一致で比較する。
(3)で
にアクセスした場合
にリダイレクトする。
リダイレクト時の各オプションは、
QSA
QueryString append。QSAを付与しないとQueryStringを上書いてします。詳しくは後述。
R=301
Moved Permanently
L
ここでルールの適用を終了する。
QSAはこの場合不要だけど、定義変更時に忘れがちなので付けておく。
HTTPSを強制
HTTPでアクセスされたらHTTPSにリダイレクトする。
RewriteEngine On # (1) RewriteCond %{HTTPS} !=on RewriteRule .* https://example.com$0 [QSA,NE,R=301,L]
DoCoMo機種の場合、強制的にguid=ONを付与
強制するのはどうなの?って感じですが。
RewriteEngine On # (1) RewriteCond %{HTTP_USER_AGENT} ^DoCoMo [NC] # (2) RewriteCond %{QUERY_STRING} !^(.*&)?guid=ON(&.*)?$ [NC] # (3) RewriteCond %{HTTPS} !=on # (4) RewriteRule .* http://example.com$0?guid=ON [QSA,NE,R=302,L]
(1) UserAgentがDoCoMoから始まるもの かつ
(2) QueryStringにguid=ONが含まれていない場合 かつ
(3) HTTPS接続で無い場合
(4) guid=ONを付与してリダイレクトする
ただし、アクセスする度にguid=ON付きURLにリダイレクトしたり、POSTのリクエストがリダイレクトされても困るので、
別途、アプリケーション側で内部リンクに自動的にguid=ONを付与するような仕組みを設けること。
(4)でR=302な理由は、DoCoMo端末のみのリダイレクト(!= Moved Permanently)であるのと、
301リダイレクトだと「サイトが移動しました(301)」のメッセージがでるので302を返すように。
(4)で「QSA」がついていないと、
にアクセスした場合に、Query Stringが書き換えられ
になってしまう。「QSA」が付与されていると
となる。