Apache HTTP Serverの仮想ホストのHTTP/HTTPS共通設定

「Apache HTTP Serverの名前ベース仮想ホスト」で仮想ホスト (VirtualHost) の仕組みについて簡単に整理した。今回はその設定について整理した。
概要
httpdの名前ベース仮想ホストはIPアドレスごとに設定する。そのため,HTTPとHTTPSの両方に対応した仮想ホストの設定を用意する必要がある。
ただ,ServerName
やDocumentRoot
など重複する内容が多く,同じ内容を何回も書くのはDRY原則に反し,保守性が悪くなる。
そこで,できるだけ重複がなくなるように仮想ホストの設定を考えて用意したので紹介する。
方法
まずは,同じ問題についての議論があったので記しておく。
「apache 2.2 – Serve http (port 80) and https (port 443) on same VirtualHost – Server Fault」では,共通部分を外部ファイルに分離して,Include
で読み込むという方法が提案されていた。
この方法はhttpd標準機能だけでできるところがいい。ただ,今回はホストごとに設定を1ファイルにまとめたいと考えており,この方法だとファイルが追加で1個必要になるのがネックに感じた。
「apache2 – Avoiding redundancy with http and https virtual hosts using Webmin + Apache – Server Fault」では,以下2点が工夫されていた。
- 80ポートへのHTTPアクセスを443ポートのHTTPSにリダイレクト
mod_macro
を使ってホストごとの設定をマクロで記述
重複部分がなくなり,スマートなやり方だった。ただし,mod_macro
は通常のhttpdのインストールでは有効にならず,mod_macro
の用意が手間に感じた。
2番目の方法をベースに,mod_macro
ではなくDefine
指令によるマクロを使うことで標準機能でできる限り共通化を実現する。
設定
HTTPとHTTPSの共通設定例を以下に示す。GitHubでも公開している。
httpd-other.conf
Define OTHER_DOMAIN other.com
Define OTHER_DOCUMENT_ROOT /usr/local/var/www/${OTHER_DOMAIN}
<Directory ${OTHER_DOCUMENT_ROOT}>
Options Indexes FollowSymLinks
## For .htaccess
# AllowOverride AuthConfig FileInfo Indexes Limit
AllowOverride None
Require all granted
</Directory>
<VirtualHost *:80>
ServerAdmin webmaster@${OTHER_DOMAIN}
ServerName ${OTHER_DOMAIN}
DocumentRoot ${OTHER_DOCUMENT_ROOT}
## Always HTTPS
<If "%{HTTPS} == 'on'">
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</If>
<ElseIf "%{REQUEST_URI} !~ m#^/\.well-known#">
RewriteEngine On
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI}?%{QUERY_STRING} [L,R=301]
</ElseIf>
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@${OTHER_DOMAIN}
ServerName ${OTHER_DOMAIN}
DocumentRoot ${OTHER_DOCUMENT_ROOT}
ErrorLog "logs/${OTHER_DOMAIN}-error_log"
CustomLog "logs/${OTHER_DOMAIN}-access_log" common
SSLEngine on
SSLCertificateFile "/usr/local/etc/letsencrypt/live/${OTHER_DOMAIN}/fullchain.pem"
SSLCertificateKeyFile "/usr/local/etc/letsencrypt/live/${OTHER_DOMAIN}/privkey.pem"
</VirtualHost>
以下の方針で設定を用意した。
Define
により共通のドメインとDOCUMENT_ROOT
をマクロ化DOCUMENT_ROOT
へのアクセス権限を設定- HTTP (80ポート) には最低限の設定とリダイレクト設定のみ指定
- HTTPS (443ポート) にログの設定も指定
冒頭のDefine
指令でドメイン名とドキュメントルートをマクロ化することで,この重複を回避した。
ただし,Define
で定義するマクロはhttpd.conf
全体で共通のため,他の仮想ホストの設定と被らないように,変数名の最初にホスト名 (例: OTHER_
) を付与している。実際にこの設定を流用する場合も,OTHER_
を自分のホスト名に置換し,ファイル名のother
もホスト名に変えておく。
リダイレクトの設定は.htaccess
に任せてもいいだろう。
後はこの設定をメインのhttpd.conf
から以下のようにInclude
で読み込めばいい。
Include conf/httpd-other.conf
これまで書き溜めた「Apache HTTP Serverでの常時SSL/HTTPS化の設定」や「Apache HTTP Serverの名前ベース仮想ホスト」などの総まとめとなっている。
結論
httpdでの仮想ホストの共通設定例を記した。
常時HTTPSの設定に続いて,実運用上で最低限必要となる仮想ホストの設定を整理できた。仮想ホストの理解から設定の共通化まで時間がかかったがこれというものを整理できてよかった。
今後はこの設定をベースに自分のWebサービスの設定を行っていきたい。