ApacheからNginxに移行する方法:VirtualHostsをServer Blocksに変換する
このチュートリアルでは、ApacheからNginxへの移行方法について説明します。ApacheとNginxは、おそらくLinux上で最も使用されているWebサーバーです。前者は二つの中で最も古いもので、1995年に開発が始まり、ワールドワイドウェブの拡大において非常に重要な役割を果たしました。現在でも最も人気のあるWebサーバーです。一方、Nginxの最初のバージョンは2004年にリリースされました。Nginxは単なるWebサーバーではなく、リバースプロキシやロードバランサーとしても機能します。
ApacheとNginxはどちらも無料でオープンソースです。その最も重要な機能の一つは、複数のウェブサイトやリソースを提供できることです。Apacheは「VirtualHosts」という仕組みを使用し、Nginxは「Server Blocks」を使用します。このチュートリアルでは、最も一般的なApacheのVirtualHost設定をNginxに移行する方法を見ていきます。
このチュートリアルでは、あなたが学ぶことができることは:
- DebianおよびRed Hat系ディストリビューションにNginxをインストールする方法
- ApacheからNginxへの移行方法
- ApacheのVirtualHost設定をNginxのサーバーブロックに翻訳する方法
使用されるソフトウェア要件と規約
Nginxのインストール
Nginxは、一般的に使用されるすべてのLinuxディストリビューションのデフォルトリポジトリにあります。それでは、DebianおよびRed Hatベースのディストリビューションで、各パッケージマネージャを使用してインストールする方法を見ていきましょう。
Debianおよびその多くの派生版では、aptitudeとaptのパッケージマネージャのどちらかを選択することができます。ここでは後者を使用します。Nginxをインストールするには、次のように実行します:
sudo apt-get update && sudo apt-get install nginxRed Hatのディストリビューションファミリー、つまりRHEL(Red Hat Enterprise Linux)やFedoraを含む、では、dnfを使用してソフトウェアをインストールできます。専用のパッケージをインストールするために実行すべきコマンドは次の通りです:
sudo dnf install nginxシステムにソフトウェアがインストールされたので、次のコマンドを使用してnginxサービスを開始し、起動時に自動的に起動するように設定できます:
sudo systemctl enable --now nginxサーバーはデフォルトでポート 80 でリスニングしていますので、到達可能であることを確認するために、お気に入りのウェブブラウザで localhost に移動することができます。以下は Fedora の Nginx ウェルカムページです:
ApacheからNginxへの移行 - ApacheのバーチャルホストとNginxのサーバーブロック
このチュートリアルのイントロダクションで述べたように、ApacheとNginxの両方は複数のウェブサイトを提供する能力があります。Apacheでは、提供されるさまざまなサイトはVirtualHostを使用して構成されます。一方、NginxではServer Blocksが使用されます。最も基本的なApacheのVirtualHostディレクティブを見て、それらをnginxが受け入れる指示にどのように翻訳できるかを見てみましょう。以下のVirtualHostには非常に少ないディレクティブが含まれています。
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
</VirtualHost>
上記の数少ない指示に従って、名前ベースのVirtualHostを設定しました。上記の設定は、.conf拡張子のファイルに配置する必要があります。Debian系のディストリビューションでは、そのファイルは/etc/apache2/sites-availableディレクトリに存在する必要があります。「有効化」するためには、/etc/apache2/sites-enabledディレクトリにそのためのシンボリックリンクを作成する必要があり、a2ensiteコマンドを使用します:
sudo a2ensite site1.lan.confRHELベースのディストリビューションを使用している場合、ファイルは/etc/httpd/cond.dの下に配置する必要があります。どちらの場合でも、設定が有効になるためにはWebサーバーを再起動する必要があります。
サンプルで使用した指令を見てみましょう。まず、*:80の表記を使用することで、VirtualHostがポート80で全IPのすべてのリクエストに応答するようにしました。複数のVirtualHostが定義されているときにApacheがどのように動作するかを思い出すことは良いことです。ApacheがリクエストのIP-ポートの組み合わせに一致する複数のVirtualHost設定を見つけた場合、Apacheは一致するVirtualHostがより特定的であるか、言い換えれば、リクエストがServerName指令の値と一致するかどうかを確認します。一致するVirtualHostがそれほど特定的でない場合、最初にリストされたものがリクエストに応答するために使用されます。
設定の本文では、次のディレクティブを使用しました:
- ServerName
- DocumentRoot
ServerName を使って、基本的に サーバーが自分を識別するために使用するホスト名とポートを設定します。この場合、site1.lan です。これは、ユーザーが私たちの VirtualHost によって提供されるものにアクセスするために、例えばウェブブラウザに入力する必要があるものです。
DocumentRoot ディレクティブは、サイトのドキュメントツリーをホストするルートディレクトリを示すために使用されます。この場合、以前に作成したディレクトリは /var/www/site1.lan です。
上記のVirtualHost構成をNginxサーバーブロックにどのように翻訳できるでしょうか?私たちが書けることは次のとおりです:
server {
listen *:80;
server_name site1.lan;
root /var/www/site1.lan;
}
一見すると、2つの構成の類似点がすでに見えてきます。ご覧のように、サーバーブロックの構成は、Server { }スタンザの中で定義されています。ここで使用したディレクティブは次の通りです:
- 聞く
- サーバー名
- ルート
listen ディレクティブは、サーバーブロックが応答し、リクエストに応じる アドレス と IP を設定するために使用されます。この場合、私たちは *:80 のみを設定しており、つまりサーバーブロックはポート 80 で全てのIP(* はすべてをキャッチする)へのリクエストに応答するために使用されます。
ApacheのVirtualHostと同様に、server_nameディレクティブを使用してサーバー名を定義しました:これにより、特定のリクエストを処理するために使用されるサーバーブロックが確立されます。
rootディレクティブは、ApacheのDocumentRootに相当し、サーバーブロックによって提供されるリクエストのルートディレクトリを設定します。
Nginxサーバーブロックの設定をファイルシステム内のどこに配置するべきでしょうか?それは、使用しているディストリビューションによって異なります。Debianやその派生ディストリビューションでは、設定ファイルを/etc/nginx/sites-availableディレクトリ内に作成し、その後/etc/nginx/sites-enabled内にシンボリックリンクを作成する必要があります。設定がsite1.lan.confファイルに保存されていると仮定すると、次のコマンドを実行します:
sudo ln -s /etc/nginx/sites-available/site1.lan.conf /etc/nginx/sites-enabled/FedoraやRed Hatファミリーの他のディストリビューションでは、代わりに/etc/nginx/conf.dディレクトリ内にファイルを作成するだけです。いずれの場合も、設定が有効になるためにはNginxサーバーを再起動する必要があります。
ウェブサイトの特定のセクションに設定を適用する
Apacheを使用する際、サイトの特定のディレクトリとその中に含まれるすべてのファイルおよびディレクトリに一連の指示を適用するために、<Directory>ディレクティブを使用します。以下は使用例です:
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
<Directory /var/www/site1.lan/>
# Directives here
</Directory>
</VirtualHost>
Nginxサーバーブロックに対応するディレクティブはlocationです:
server {
listen *:80;
server_name site1.lan;
root /var/www/site1.lan;
location / {
# Directives here
}
}
上記の場合、ルートディレクトリ自体の設定を行ったので、指示はサイト内のすべてのファイルに適用されます。ApacheのDirectoryディレクティブとNginxのlocationディレクティブは、設定を微調整するために繰り返すことができます。
どのファイルをインデックスとして使用するかを指定する
ApacheのVirtualHostを設定する際、特定のディレクトリでインデックスとして使用するリソースを設定するためにDirectoryIndexディレクティブを使用できます。例えば、index.htmlとindex.phpの両方のファイルを使用するには、次のように書きます:
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
<Directory /var/www/site1.lan/>
DirectoryIndex index.html index.php
</Directory>
</VirtualHost>
複数のURLが指定される場合、この場合のように、サーバーは最初に見つけたものを使用します。Nginxを使用し、サーバーブロックを設定する際にディレクトリ内のインデックスとして使用すべきファイルのリストを提供するためには、代わりにindexディレクティブを使用したいです。
server {
listen *:80;
server_name site1.lan;
root /var/www/site1.lan;
location / {
index index.html index.php
}
}
Apacheを使用する際に起こるように、ファイルは指定された順序でチェックされるので、最初に見つかったものが使用されます。
ディレクトリリスト出力を有効にする
サイトディレクトリに移動し、設定されたインデックスファイルが存在しない場合、特定の状況下では、ウェブサーバーに、そのディレクトリに存在するファイルのリストを生成して表示させることを許可する必要があります(デフォルトの動作はアクセスを拒否することです)。この機能を実現するためには、特定のディレクティブを使用する必要があります:Options。このディレクティブは、特定のディレクトリで利用可能なサーバー機能を制御します。私たちは、+記号を使ってIndexesを有効にするためにそれを使用します。
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
<Directory /var/www/site1.lan/>
Options +Indexes
</Directory>
</VirtualHost>
Nginxで同じ動作を取得するのも非常に簡単です。私たちがすべきことは、autoindexディレクティブを使用し、それをonに設定することだけです。
server {
listen 80;
server_name site1.lan;
root /var/www/site1.lan;
location / {
autoindex on;
}
}
リソースへのアクセスを制限する
Apacheを使用している場合、VirtualHostによって提供されるリソースへのアクセスを制限するには、Directoryスタンザ内にRequireディレクティブを使用できます。特定のサブネット(例えば、192.168.0.0/24)からのアクセスのみを許可するには、次のように書きます:
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
<Directory /var/www/site1.lan/>
Require 192.168.0.0/24
</Directory>
</VirtualHost>
そのサブネットからのアクセスを拒否するために、代わりに次のように書きます:
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
<Directory /var/www/site1.lan/>
<RequireAll>
Require all granted
Require not 192.168.0.0/24
</RequireAll>
</Directory>
</VirtualHost>
この最後の例には少し説明が必要です。なぜ<RequireAll>ディレクティブを使用したのでしょうか?まず、VirtualHostのアクセスを設定する際に、3つの「グループ化」ディレクティブを使用できることを言わなければなりません。
- RequireAll
- RequireAny
- RequireNone
これらの指令は複数のアクセスルールをグループ化するために使用され、次のように機能します:
| 指令 | 成功するために |
|---|---|
| RequireAll | 失敗してはいけない指示があり、少なくとも一つは成功しなければなりません(指示は中立的な場合もあります) |
| RequireAny | 少なくとも1つの指令は成功しなければなりません |
| RequireNone | いかなる指示も成功してはならない |
もしこれらの指示が一連のRequire命令をグループ化するために使用され、ここではIPからのアクセスを<強調>否定するために一つだけを使用した場合(この場合はサブネット全体)、なぜRequireAllを使用したのか?それは、requireディレクティブが否定された場合(notを使用した場合)、失敗するか中立的な結果を返すことしかできないからです。したがって、要求は単独の否定されたrequireによって承認されることはありません。私たちがしなければならなかったのは、否定されたRequireをRequireAllディレクティブの内部に置くことです。この場合、成功するためには、その内部の任意のディレクティブが失敗してはならないため、失敗します。そのため、Require all grantedをその内部に入れたのです:成功するチャンスを与えるためです。これを行わないと、サーバーの再起動時に次のエラーが発生します:
AH01624: directive contains only negative authorization directivesNginxサーバーブロックの同等の設定は、allowおよびdenyディレクティブを通じて得られます。上記の例で使用したサブネットからのみアクセスを許可するには、次のように記述します:
server {
listen *:80;
server_name site1.lan;
root /var/www/site1.lan;
location / {
deny all;
allow 192.168.0.0/24;
}
}
アクセスを 拒否 するために、192.168.0.0/24 サブネットからのリクエストを、代わりに:
server {
listen *:80;
server_name site1.lan;
root /var/www/site1.lan;
location / {
deny 192.168.0.0/24;
}
}
上記は基本的なアクセス制御の例に過ぎませんが、Nginxを使用した場合にVirtualHostのロジックをどのように変換するかのアイデアを与えることができれば幸いです。
専用のエラーおよびアクセスログファイルを指定する
ApacheのVirtualHostを設定する際、特定のリソースのエラーログを専用のファイルに書き込むようにすることができます。このような機能を実現するために使用するディレクティブはErrorLogで、引数としてログファイルのパスを受け取ります:
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
ErrorLog "/var/log/httpd/site1.lan-error.log"
</VirtualHost>
サーバーによって受信されたリクエストがどこに記録されるかは、CustomLogディレクティブによって管理されます。このディレクティブは2つの必須引数を受け取ります:最初は
ログが書き込まれるファイルのパスで、2つ目は何がファイルに書き込まれるかを指定します。これはフォーマット文字列を使用して定義します。例を見てみましょう:
<VirtualHost *:80>
ServerName site1.lan
DocumentRoot /var/www/site1.lan
ErrorLog "/var/log/httpd/site1.lan-error.log"
CustomLog "/var/log/httpd/site1.lan-access.log" "%t %h %>s"
</VirtualHost>
ここでは、アクセスが /var/log/httpd/site1.lan-access.log ファイルに記録されるように CustomLog ディレクティブを使用しました。フォーマット文字列は次のように定義されています:
| 表記 | 意味 |
|---|---|
| %t | リクエストが受信された時間 |
| %h | リクエストのIPアドレス |
| %>s | リクエストの最終状況 |
私たちのアクセスログファイルの行は、この場合、次のようになります:
[01/Oct/2021:23:49:56 +0200] 127.0.0.1 200これはもちろん、ログの説明で使用できるシンボルの小さなサブセットに過ぎません。完全なリストについては、公式ドキュメントを参照してください。
特定のサーバーブロックのためにエラーをログするためにNginxが使用するファイルを設定するには、error_logディレクティブを使用することができます。
server {
listen *:80;
server_name site1.lan;
root /var/www/site1.lan;
error_log "/var/log/nginx/site1.lan-error.log";
}
アクセスをログに記録するファイルを設定するために、代わりに access_log ディレクティブを使用します。デフォルトでは、メッセージはデフォルトの combined 形式で保存されますが、これは log_format ディレクティブを介して変更できます。すでにデフォルト形式が設定されているため、access_log ディレクティブを使用して、ファイルパスのみを渡すことができます。例えば:
server {
listen *:80;
server_name site1.lan;
root /var/www/site1.lan;
error_log "/var/log/nginx/site1.lan-error.log";
access_log "/var/log/nginx/site1.lan-access.log";
}
デフォルトのログ形式を使用すると、アクセスログの行は次のようになります:
127.0.0.1 - - [01/Oct/2021:23:58:32 +0200] "GET / HTTP/1.1" 200 12 "-" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:92.0) Gecko/20100101 Firefox/92.0"結論
このチュートリアルでは、ApacheからNginxに移行する方法を、最も一般的なVirtualHostの設定をNginxのServer Blockに変換する方法を見てきました。ルートとサーバー名の定義方法、リソースへのアクセス制限の方法、リソース特有のエラーログとアクセスログの使用方法、特定のディレクトリのためのインデックスとして使用すべきファイルの設定方法、そしてそのようなファイルが存在しない場合にディレクトリリストの生成を許可する方法を見ました。
私たちはまた、特定のIP:ポートリクエストに応答するためにVirtualHost/サーバーブロックを構成する方法を見ました。上記に挙げたものは基本的な構成だけですが、これが出発点になることを願っています。より深い知識を得るために、ApacheとNginxのドキュメントを両方とも読んでください!

