Nginxの設定ファイルの構造と設定コンテキストを理解する
以下の文章を日本語で自然に言い換えてください。1つの選択肢で構いません。
イントロダクション
Nginxは高性能なウェブサーバーであり、インターネット上で最大のサイトの負荷を処理する役割を担っています。特に多くの同時接続の処理に優れており、静的なコンテンツの転送や提供にも優れています。本ガイドでは、Nginxの設定ファイルの構造とファイルの設計について説明します。
Nginxの設定コンテキストを理解する
このガイドでは、メインのNginx設定ファイルの構造について説明します。このファイルは、Nginxのインストール方法によって場所が異なります。多くのLinuxディストリビューションでは、ファイルは /etc/nginx/nginx.conf にあります。もし存在しない場合は、/usr/local/nginx/conf/nginx.conf や /usr/local/etc/nginx/nginx.conf にある可能性もあります。
メインの設定ファイルを眺める際に最初に気づくべきことの一つは、木構造に似た形式で整理されていることです。これは、波括弧({と})で示されるセットによってマークされます。Nginxのドキュメントでは、これらの波括弧によって定義される領域を「コンテキスト」と呼びます。なぜなら、それらは、設定の詳細が関心の範囲に応じて分離されているからです。これらの分割により、組織的な構造が提供され、一部の条件付きロジックも適用する設定を決定する役割を果たします。
複数のコンテキストが階層的に配置されることがあるため、Nginxでは設定を継承することができます。一般的な原則として、ディレクティブが複数の入れ子スコープで有効である場合、より広範なコンテキストでの宣言は、子コンテキストにデフォルト値として渡されます。子コンテキストはこれらの値を上書きすることができます。なお、配列型ディレクティブのオーバーライドは、前の値を置き換えることになりますので、それに注意する必要があります。
指示は、それらが設計されたコンテキストでのみ使用することができます。Nginxは、誤ったコンテキストで宣言された指示を含む設定ファイルを読み込む際にエラーを発生させます。Nginxのドキュメントには、各指示が有効なコンテキストの情報が記載されており、それは便利な参考資料となります。
以下では、Nginxを使用する際に最も一般的な状況について話し合います。
コアの文脈
最初に議論するコンテキストのグループは、階層的なツリーを作成し、個々の設定ブロックを分離するためにNginxが使用するコアコンテキストです。これらのコンテキストは、Nginx設定の主要な構造を構成するものです。
主要な文脈
最も一般的な文脈は「メイン」または「グローバル」文脈です。これは、通常の文脈ブロック内に含まれない唯一の文脈です。
/etc/nginx/nginx.confは、以下のように日本語で言い換えられます:
「/etc/nginx/nginx.conf」
# The main context is here, outside any other contexts
. . .
context {
. . .
}
これらのブロックの完全に外部に存在する任意のディレクティブは、「main」コンテキストに属しています。Nginxの設定がモジュール式に設定されている場合、つまり複数のファイルに設定オプションがある場合、一部のファイルには括弧のないコンテキスト外に存在するように見える指示が含まれていますが、設定が一緒にロードされるとコンテキスト内に含まれます。
メインコンテキストは、Nginxの設定において最も広範な環境を表します。このコンテキストは、アプリケーション全体に影響を与える詳細な設定を行うために使用されます。このセクションのディレクティブは、下位のコンテキストにも影響を及ぼしますが、その中には下位レベルで上書きできないものも多くあります。
メインコンテキストに設定される一般的な詳細は、ワーカープロセスの実行に使用されるシステムユーザーとグループ、ワーカーの数、およびメインのNginxプロセスのIDを保存するためのファイルです。アプリケーション全体のデフォルトのエラーファイルは、このレベルで設定できます(これはより具体的なコンテキストでオーバーライドすることもあります)。
イベントの背景
「イベント」コンテキストは「メイン」コンテキストに含まれています。これは、Nginxが接続を一般的なレベルでどのように処理するかに影響を与えるグローバルオプションを設定するために使用されます。Nginxの設定内には、イベントコンテキストが1つだけ定義できます。
この文脈は、他のかっこで括られた文脈の外側の設定ファイルでは、次のように表示されます。
# main context
events {
# events context
. . .
}
Nginxはイベントベースの接続処理モデルを使用しており、このコンテキスト内で定義されたディレクティブが、ワーカープロセスが接続を処理する方法を決定します。主にここで見つかるディレクティブは、接続処理のテクニックを選択するか、またはこれらの方法の実装方法を変更するために使用されます。
通常、接続処理の方法はプラットフォームが最も効率的な選択肢に基づいて自動的に選択されます。Linuxシステムでは、通常、epollメソッドが最良の選択です。
他の設定可能な項目には、各ワーカーが処理できる接続の数、ワーカーが一度に一つの接続のみを処理するか、保留中の接続をすべて処理するかの通知を受けた後に処理するか、またはワーカーが順番にイベントに応答するかどうかが含まれます。
HTTPコンテキスト
Nginxを設定する際、Webサーバーまたはリバースプロキシとしての使用では、HTTPコンテキストを定義することがおそらく最も一般的です。HTTPコンテキストは、大部分の設定を保持します。このコンテキストには、HTTPまたはHTTPS接続の処理方法を定義するために必要なすべてのディレクティブや他のコンテキストが含まれます。
httpコンテキストはイベントコンテキストの兄弟であるため、ネストではなく両方を横に並べるべきです。両者はどちらもメインコンテキストの子です。
「nginxの設定ファイルである/etc/nginx/nginx.conf」
# main context
events {
# events context
. . .
}
http {
# http context
. . .
}
低いコンテキストでは、リクエストの処理方法についてより具体的に指示がされますが、このレベルの指令は、定義された仮想サーバー全体に対してデフォルトを制御します。これより下の階層では、継承の方法に応じて多くの指令が設定可能です。
以下のディレクティブのいくつかは、アクセスログとエラーログ(access_logとerror_log)のデフォルトの場所を制御し、ファイル操作の非同期I/Oを設定する(aio、sendfile、directio)、エラー発生時のサーバの状態を設定する(error_page)ことができます。その他のディレクティブは圧縮(gzipとgzip_disable)を設定し、TCPのキープアライブ設定(keepalive_disable、keepalive_requests、keepalive_timeout)を微調整し、パケットとシステムコールの最適化のためにNginxが従うルールを設定する(sendfile、tcp_nodelay、tcp_nopush)ことができます。追加のディレクティブでは、アプリケーションレベルでのドキュメントルートとインデックスファイル(rootとindex)を設定し、さまざまなデータの種類を格納するために使用されるハッシュテーブルを設定します(server_names、types、variablesの*_hash_bucket_sizeと*_hash_max_size)。詳細については、Nginxのドキュメントを参照してください。
サーバーコンテキスト
「サーバー」コンテクストは「http」コンテクスト内で宣言されます。これは、入れ子のかっこで表されるコンテクストの最初の例です。また、複数の宣言を許可する最初のコンテクストでもあります。
サーバーコンテキストの一般的な形式は、次のようになる可能性があります。これらはhttpコンテキスト内に配置されることを忘れないでください。
# main context
http {
# http context
server {
# first server context
}
server {
# second server context
}
}
各インスタンスは特定の仮想サーバーを処理するため、複数のサーバーコンテキストを宣言することができます。必要なだけサーバーブロックを作成し、それぞれが特定の接続のサブセットを処理できます。
このコンテキストタイプは、Nginxがアルゴリズムを選択するために最初に使用するものです。各クライアントのリクエストは、単一のサーバーコンテキストで定義された設定に従って処理されるため、Nginxはリクエストの詳細に基づいて最も適切なサーバーコンテキストを選択する必要があります。ドメイン名の使用方法が異なる2つの一般的なオプションがあります。
- listen: The IP address / port combination that this server block is designed to respond to. If a request is made by a client that matches these values, this block will potentially be selected to handle the connection.
- server_name: This directive is the other component used to select a server block for processing. If there are multiple server blocks with listen directives of the same specificity that can handle the request, Nginx will parse the “Host” header of the request and match it against this directive.
この文脈では、ログ、ドキュメントのルート、圧縮などを含む、httpコンテキストで定義される可能性のある多くのディレクティブを上書きすることができます。httpコンテキストから引き継がれるディレクティブに加えて、リクエストに応答するために設定されたファイルを構成することもできます(try_files)、リダイレクトやリライトを発行することもできます(returnやrewrite)、および任意の変数を設定することもできます(set)。
場所の文脈
あなたが定期的に取り組む次の文脈は、場所の文脈です。場所の文脈は、サーバーの文脈と多くの関係品質を共有しています。例えば、複数の場所の文脈が定義され、それぞれの場所は特定のクライアントリクエストを処理するために使用され、各場所は場所の定義をクライアントリクエストと一致させる選択アルゴリズムを通じて選択されます。
サーバーブロックの選択を決定する指示は、サーバーコンテキスト内で定義されますが、リクエストを処理する場所の能力を決定するコンポーネントは、場所の定義(場所ブロックを開く行)に配置されています。
一般的な構文は次のようになります。
/etc/nginx/nginx.conf→ 「/etc/nginx/nginx.conf」
location match_modifier location_match {
. . .
}
場所ブロックは、サーバーのコンテキスト内に存在し、サーバーブロックとは異なり、お互いにネストすることができます。これは、特定のトラフィックの一部をキャッチするためのより一般的な場所コンテキストを作成し、その後、追加のコンテキストでより具体的な基準に基づいてさらに処理するために役立ちます。
「/etc/nginx/nginx.conf」
# main context
server {
# server context
location /match/criteria {
# first location context
}
location /other/criteria {
# second location context
location nested_match {
# first nested location
}
location other_nested {
# second nested location
}
}
}
IPアドレス/ポートの組み合わせと「Host」ヘッダー内のホスト名に基づいて、サーバーコンテキストが選択されます。一方、リクエストURIを見て、ロケーションブロックはさらにリクエストの処理をサーバーブロック内で分割します。リクエストURIとは、ドメイン名やIPアドレス/ポートの組み合わせの後に続くリクエストの部分です。
例えば、クライアントがポート80でhttp://www.example.com/blogを要求した場合、http、www.example.com、およびポート80の要素はそれぞれサーバーブロックを選択するために使用されます。サーバーブロックが選択された後、リクエストURIである/blog部分は定義された場所と照合され、リクエストに応答するためにさらにどのようなコンテキストが使用されるべきかが判断されます。
場所の文脈で見られる多くの指示は、親のレベルでも利用可能です。このレベルでの新しい指示により、ドキュメントルートの外の場所にアクセスできます(alias)、場所を内部のみでアクセス可能とします(internal)、他のサーバーや場所にプロキシします(http、fastcgi、scgi、uwsgiプロキシを使用)。
他の文脈
上記の例は、Nginxで遭遇する必要がある基本的な文脈を表していますが、他の文脈も存在します。以下の文脈は、特定の状況でのみ使用されるか、ほとんどの人が使用しない機能に使用されます。
- split_clients: This context is configured to split the clients that the server receives into categories by labeling them with variables based on a percentage. These can then be used to do A/B testing by providing different content to different hosts.
- perl / perl_set: These contexts configure Perl handlers for the location they appear in. This will only be used for processing with Perl.
- map: This context is used to set the value of a variable depending on the value of another variable. It provides a mapping of one variable’s values to determine what the second variable should be set to.
- geo: Like the above context, this context is used to specify a mapping. However, this mapping is specifically used to categorize client IP addresses. It sets the value of a variable depending on the connecting IP address.
- types: This context is again used for mapping. This context is used to map MIME types to the file extensions that should be associated with them. This is usually provided with Nginx through a file that is sourced into the main nginx.conf config file.
- charset_map: This is another example of a mapping context. This context is used to map a conversion table from one character set to another. In the context header, both sets are listed and in the body, the mapping takes place.
流れの上流の文脈
上流コンテキストは、「上流」と呼ばれるサーバーのプールを定義および設定するために使用されます。このコンテキストでは、Nginxはリクエストをプロキシすることができます。このコンテキストは、さまざまなタイプのプロキシを設定する場合に使用されることが多いでしょう。
アップストリームのコンテキストは、特定のサーバーコンテキストの外で、httpコンテキスト内に配置する必要があります。以下のような形式です。
# main context
http {
# http context
upstream upstream_name {
# upstream context
server proxy_server1;
server proxy_server2;
. . .
}
server {
# server context
}
}
アップストリームのコンテキストは、定義されたサーバープールにリクエストを送信するために、サーバーまたはロケーションブロック内で名前によって参照することができます。その後、アップストリームはアルゴリズム(デフォルトではラウンドロビン)を使用して、どの特定のサーバーにリクエストを渡すかを決定します。このコンテキストにより、Nginxはリクエストのプロキシ時に負荷分散を行う能力が得られます。
もし文脈がある場合
「もし」の文脈は指示の条件付き処理を提供するために確立されることがあります。従来のプログラミングにおけるif文のように、Nginxのifディレクティブは、与えられたテストが「真」を返す場合にのみ含まれる命令を実行します。
Nginxのif文はリライトモジュールによって提供され、これがこの文脈の主な使用法です。Nginxはリクエストの条件を他の多くの専用ディレクティブでテストするため、ほとんどの条件における実行にはif文は使用すべきではありません。これは非常に重要な注意事項であるため、Nginxコミュニティでは「if is evil」というページを作成しました。
問題は、Nginxの処理順序がしばしば予期せぬ結果を招くことです。この文脈で信頼できる安全な指令は、return指令とrewrite指令(この文脈のために作られたもの)だけです。if文脈を使用する際には、同じ文脈内のtry_files指令は無効になることにも注意してください。
ほとんどの場合、書き換えが必要かどうかを判断するために if 文が使用されます。これらは主に位置ブロック内に存在するため、一般的な形式は以下のようになります。
# main context
http {
# http context
server {
# server context
location location_match {
# location context
if (test_condition) {
# if context
}
}
}
}
Limit_except(限定除外)コンテキスト
limit_exceptコンテキストは、場所のコンテキスト内で特定のHTTPメソッドの使用を制限するために使用されます。たとえば、特定のクライアントのみがPOSTコンテンツにアクセスできるようにするが、誰でもコンテンツを読む能力を持っている必要がある場合、limit_exceptブロックを使用してこの要件を定義することができます。
上記の例は、おおよそこれと同じように見えるでしょう。
. . .
# server or location context
location /restricted-write {
# location context
limit_except GET HEAD {
# limit_except context
allow 192.168.1.1/24;
deny all;
}
}
この場合、コンテキストヘッダーにリストされていないHTTPメソッドが出現した場合、そのコンテキスト内の指令(アクセス制限を意図しています)が適用されます。上記の例の結果として、どのクライアントもGETおよびHEADの動詞を使用できますが、192.168.1.1/24サブネットからのクライアントのみが他の方法を使用できます。
文脈に基づく一般的なルールに従う必要があります。
Nginxの設定を探索する際によく遭遇する一般的な文脈を把握した今、Nginxのコンテキストを扱う際のベストプラクティスについて話し合いましょう。
最高の文脈で指示を適用してください。
多くの指令は複数の文脈で有効です。例えば、http、server、locationの文脈に配置できる指令はかなりあります。これにより、これらの指令を設定する際に柔軟性が生まれます。
一般的なルールとして、適用される最も広いコンテキストで指示を宣言し、必要に応じて下位のコンテキストでオーバーライドすることが、通常は最善です。これは、Nginxが実装する継承モデルのおかげで可能です。この戦略を使用する理由は多々あります。
まず第一に、高いレベルで宣言することによって、同じコンテキスト間での不要な繰り返しを避けることができます。例えば、以下の例では、各場所が同じドキュメントルートを宣言しています。
/etc/nginx/nginx.conf「/etc/nginx/nginx.conf」
http {
server {
location / {
root /var/www/html;
. . .
}
location /another {
root /var/www/html;
. . .
}
}
}
次のように、ルートをサーバーブロックに移動するか、さらにhttpブロックに移動することもできます。
http {
root /var/www/html;
server {
location / {
. . .
}
location /another {
. . .
}
}
}
ほとんどの場合、サーバーレベルが最も適切ですが、上位レベルでの宣言には利点があります。これにより、ディレクティブをより少ない箇所で設定するだけでなく、デフォルト値をすべての子要素に継承することができ、低レベルでディレクティブを忘れることによるエラーを防ぐことができます。これは長い設定において重大な問題となります。上位レベルでの宣言は、良好なデフォルトを提供します。
処理には、if文の代わりに複数の兄弟コンテキストを使用してください。
クライアントの要求に含まれる情報によって処理を異なるようにしたい場合、多くのユーザーは条件分岐のために「if」文を使おうとします。先程少し触れたように、これにはいくつかの問題があります。
最初の事柄は、「もし」の指示がしばしば管理者の期待とは異なる結果を返すことです。入力が同じであれば処理結果は常に同じになるが、Nginxが環境を解釈する方法は、徹底的なテストなしでは想定と異なることがあります。
これに対する第二の理由は、これらの目的の多くに使用される最適化された特定の指示文が既に存在するためです。Nginxは既に、サーバーブロックやロケーションブロックの選択アルゴリズムに関する十分に文書化された選択方法を使用しています。可能であれば、異なる設定をそれぞれ独自のブロックに移動させ、このアルゴリズムに選択プロセスの論理を処理させる方が最善です。
例えば、ユーザーが提供したリクエストを自分の希望する形式に変換するための書き直しに頼る代わりに、リクエストに対応するために2つのブロックを設定することを試してみるべきです。1つは望むメソッドを表し、もう1つは混乱したリクエストを捕捉し、正しいブロックにリダイレクト(および必要に応じて書き直し)するものです。
結果は通常、より可読性が高く、さらにパフォーマンスが向上するという利点もあります。正しいリクエストは追加の処理を必要とせず、多くの場合、誤ったリクエストもリダイレクトするだけで正しく通過することができます。これによりオーバーヘッドが低く実行されます。
結論
この時点では、Nginxの最も一般的なコンテキストと、それを定義するブロックを作成するディレクティブについて、十分な理解を持つべきです。
常にNginxのドキュメンテーションをチェックし、ディレクティブを配置できるコンテキストや最適な場所を評価する情報を確認してください。設定を作成する際に注意を払うことは、メンテナビリティを向上させるだけでなく、性能もしばしば向上させます。
次に、Nginxでパスワード認証の設定方法を学ぶことができます。