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

Apache HTTP Serverの名前ベース仮想ホスト」で仮想ホスト (VirtualHost) の仕組みについて簡単に整理した。今回はその設定について整理した。

概要

httpdの名前ベース仮想ホストはIPアドレスごとに設定する。そのため,HTTPとHTTPSの両方に対応した仮想ホストの設定を用意する必要がある。

ただ,ServerNameDocumentRootなど重複する内容が多く,同じ内容を何回も書くのは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点が工夫されていた。

  1. 80ポートへのHTTPアクセスを443ポートのHTTPSにリダイレクト
  2. 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>

以下の方針で設定を用意した。

仮想ホストの共通設定の方針
  1. Defineにより共通のドメインとDOCUMENT_ROOTをマクロ化
  2. DOCUMENT_ROOTへのアクセス権限を設定
  3. HTTP (80ポート) には最低限の設定とリダイレクト設定のみ指定
  4. 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サービスの設定を行っていきたい。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です