2026年7月2日
2026年7月2日
Apacheでバーチャルホストを設定する方法(名前ベース・HTTPS・WordPress対応)
Apacheのバーチャルホストを使うと、1台のサーバーで複数のドメインのサイトを動かせます。設定の中心は <VirtualHost> ブロックの ServerName と DocumentRoot で、ドメインごとに設定ファイルを1つ作り、文法を確認してから再読み込みするのが基本の流れです。この記事では、名前ベースのバーチャルホストの書き方をUbuntuとRHEL系(AlmaLinux・Rocky Linuxなど)それぞれの手順で示し、DNSを切り替える前の確認方法、HTTPS化、WordPressを置くときの注意点、表示がおかしいときの調べ方まで説明します。
名前ベースのバーチャルホストの仕組み
ブラウザはリクエストの中に、アクセスしたいドメイン名を Host ヘッダーとして送ります。Apacheはこの値を各バーチャルホストの ServerName と ServerAlias に照らし合わせ、一致した設定のディレクトリからファイルを返します。これが名前ベースのバーチャルホストで、IPアドレスが1つでも複数のサイトを運用できます。HTTPSでも、ブラウザが接続の最初にドメイン名を伝える仕組み(SNI)があるため、同じように振り分けられます。
覚えておきたいのは、**どの ServerName にも一致しないリクエストは、そのIPアドレスとポートで最初に読み込まれたバーチャルホストが受け持つ**という動きです。IPアドレスで直接アクセスされた場合や、DNSの設定ミスで想定外のドメインが向いている場合に、別のサイトが表示される原因になります。対策は後で説明します。
なお、Apache 2.2までの解説に出てくる NameVirtualHost ディレクティブは、2.4では不要になっています。主要なディストリビューションが提供しているのは2.4系です(2026年10月現在)。
準備: 公開ディレクトリを作る
ここでは example.com というドメインを例にします。実際の作業では自分のドメインに置き換えてください。
sudo mkdir -p /var/www/example.com/public
echo 'example.com OK' | sudo tee /var/www/example.com/public/index.html
WordPressを置く場合、ファイルの所有者はApacheの実行ユーザー(Ubuntuは www-data、RHEL系は apache)に合わせるのが一般的ですが、すべてを書き込み可能にする必要はありません。更新やアップロードで書き込みが必要なのは主に wp-content 以下です。
Ubuntuでの設定手順
Ubuntuでは /etc/apache2/sites-available/ にサイトごとの設定ファイルを作り、a2ensite で有効にします。
# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
<Directory /var/www/example.com/public>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
sudo a2ensite example.com.conf
sudo a2enmod rewrite # WordPressのパーマリンクに必要
sudo apache2ctl configtest # Syntax OK を確認
sudo systemctl reload apache2
各項目の意味は次のとおりです。
ServerName: このサイトの正式なドメイン名。1つだけ書きます。ServerAlias: 同じサイトとして扱う別名。www付きや、*.example.comのようなワイルドカードも書けます。DocumentRoot: 公開するディレクトリ。<Directory>内のRequire all granted: このディレクトリへのアクセスを許可します。Apache 2.4では明示しないと403になる場合があります。AllowOverride All:.htaccessの設定を有効にします。WordPressのパーマリンクは.htaccessの書き換えルールで動くため、Noneのままだとトップページ以外が404になります。許可範囲を絞りたい場合は、WordPressの書き換えに必要なFileInfoなどを指定する方法もありますが、プラグインが.htaccessに書き込む内容によっては足りなくなることがあります。ErrorLog/CustomLog: サイトごとにログを分けておくと、トラブル時の調査が楽になります。${APACHE_LOG_DIR}はUbuntuで/var/log/apache2を指す変数です。
RHEL系(AlmaLinux・Rocky Linuxなど)での設定手順
RHEL系には a2ensite のような仕組みはなく、/etc/httpd/conf.d/ に .conf で終わるファイルを置くと読み込まれます。
# /etc/httpd/conf.d/example.com.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
<Directory /var/www/example.com/public>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/log/httpd/example.com-error.log
CustomLog /var/log/httpd/example.com-access.log combined
</VirtualHost>
sudo apachectl configtest
sudo systemctl reload httpd
RHEL系ではSELinuxが有効なので、/var/www の外(たとえば /srv/www)を公開ディレクトリにした場合は、ラベルを付けないと403になります。
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www/example.com(/.*)?"
sudo restorecon -Rv /srv/www/example.com
/var/www 以下であれば、新しく作ったディレクトリにも通常は適切なラベルが自動で付きます。WordPressのアップロード先など書き込みが必要な場所には、httpd_sys_rw_content_t を付けます。
DNSを切り替える前に動作を確かめる
新しいサーバーにサイトを移すときなどは、DNSを変更する前に表示を確認しておくと安心です。サーバーのIPアドレスに対して、Host ヘッダーを指定してリクエストを送ります。
curl -I -H "Host: example.com" http://203.0.113.10/
ブラウザで見たい場合は、手元のパソコンのhostsファイルに 203.0.113.10 example.com のように書くと、そのパソコンからだけ新しいサーバーにつながります。確認が終わったら、hostsファイルの記述を消すのを忘れないでください。
Apacheがどのバーチャルホストをどう認識しているかは、次のコマンドで一覧できます。
sudo apachectl -S
ポートごとに default server(一致しないリクエストを受け持つサイト)と、各 ServerName が定義されたファイルと行番号が表示されます。意図したサイトが表示されないときは、まずここを確認します。
一致しないリクエストの受け皿を用意する
前述のとおり、どの名前にも一致しないアクセスは最初のバーチャルホストに届きます。IPアドレス直打ちのアクセスで本番サイトが表示されるのを避けたい場合は、受け皿専用のバーチャルホストを最初に読み込まれるように置きます。Ubuntuなら 000-default.conf がファイル名の順で最初に読まれるので、ここを受け皿として整えるのが簡単です。RHEL系では conf.d 内でもファイル名の順に読み込まれるため、00-default.conf のような名前にします。
<VirtualHost *:80>
ServerName default.invalid
DocumentRoot /var/www/empty
<Location />
Require all denied
</Location>
</VirtualHost>
/var/www/empty は空のディレクトリとして作っておきます。この設定では、一致しないリクエストに403を返します。443番でも同じく最初に読み込まれたバーチャルホストが受け持つので、HTTPS化した後は apachectl -S で443番の default server も確認してください。
HTTPS化とHTTPからのリダイレクト
Let's Encryptの証明書を使う場合は、Certbotのapacheプラグインを使うと、既存の *:80 のバーチャルホストを元に443番用の設定を作り、証明書の指定まで行ってくれます。
sudo certbot --apache -d example.com -d www.example.com
Ubuntuでは example.com-le-ssl.conf のような名前で443番用のファイルが追加されるのが一般的な動きです。生成されるファイル名や、HTTPからのリダイレクトを自動で追加するかどうかはCertbotのバージョンや選択によって変わるので、実行後に apachectl -S で確認してください。
手動で設定する場合の443番の例です。証明書は中間証明書を含む fullchain.pem を指定します。
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
<Directory /var/www/example.com/public>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Ubuntuでは事前に sudo a2enmod ssl、RHEL系では sudo dnf install mod_ssl が必要です。HTTPS化が済んだら、80番のバーチャルホストは ServerName と ServerAlias を残したまま、DocumentRoot や <Directory> の代わりに Redirect permanent / https://example.com/ を書いてHTTPSへ転送します。WordPressの場合は、管理画面の「設定」→「一般」にあるWordPressアドレスとサイトアドレスも https:// に変更します。作業前にはデータベースのバックアップを取っておきます。
表示がおかしいときの確認順
- 別のサイトや初期ページが表示される:
apachectl -Sで、そのドメインがどのファイルに定義されているか確認します。Ubuntuでa2ensiteを忘れている、ServerNameの綴りが違う、DNSが別のサーバーを向いている、のいずれかが多い原因です。 - 403 Forbidden: エラーログに
AH01630: client denied by server configurationがあればRequire all grantedの不足、Permission deniedがあればディレクトリの権限(親ディレクトリも含めて実行ユーザーが辿れるか)、RHEL系ならSELinuxのラベルを疑います。 - トップページ以外が404:
AllowOverrideがNoneのまま、またはmod_rewriteが無効です。 - 起動時に「Could not reliably determine the server's fully qualified domain name」と出る: 全体設定に
ServerNameが無いことを示す警告で、動作には通常影響しません。気になる場合は全体設定にServerNameを1行追加します。
まとめ
- 名前ベースのバーチャルホストは、
HostヘッダーとServerName/ServerAliasの一致でサイトを振り分けます。 - Ubuntuは
sites-availableに置いてa2ensite、RHEL系はconf.dに.confを置きます。どちらもconfigtestの後にreloadします。 - WordPressでは
AllowOverride All(または必要な範囲)とmod_rewriteがパーマリンクに必要です。 - 一致しないリクエストは最初のバーチャルホストが受け持つため、受け皿のバーチャルホストを用意しておくと誤表示を防げます。
apachectl -Sとサイト別のエラーログが、原因を調べるときの出発点になります。