Nginx入門:高速Webサーバーの魅力に迫る


Nginx入門:高速Webサーバーの魅力に迫る

はじめに:なぜ今、Nginxなのか?Webサーバーの役割と重要性

インターネットの進化は、私たちの生活やビジネスを大きく変えました。ウェブサイトやウェブアプリケーションは、情報発信、コミュニケーション、エンターテイメント、電子商取引など、あらゆる活動の基盤となっています。そして、それらインターネット上のコンテンツを私たちのブラウザに届ける心臓部こそが「Webサーバー」です。

Webサーバーは、ユーザーからのリクエスト(「このページの情報をください」「この画像をください」など)を受け取り、それに応じた適切なレスポンス(HTMLファイル、画像ファイル、プログラムの実行結果など)を返す役割を担っています。まるで、インターネット上の「窓口」や「図書館の司書」のようなものです。

かつて、WebサーバーといえばApache HTTP Server(通称Apache)が圧倒的なシェアを誇っていました。しかし、インターネットが普及し、Webサイトへのアクセスが爆発的に増加するにつれて、Apacheのような伝統的なWebサーバーが抱える「C10K問題」(同時接続数1万件問題)などが顕在化しました。これは、多数の同時接続を効率的に処理することが難しいという課題です。

そんな中、彗星のごとく現れ、その高性能と効率性で急速にシェアを拡大しているのが「Nginx」(エンジンエックス)です。Nginxは、高負荷な環境下でも安定して多数の同時接続を処理できる能力を持ち、現代のWebサーバーに求められる様々な要件を満たしています。Facebook、Netflix、Dropbox、Airbnbなど、世界の多くの大規模サイトでNginxが採用されていることが、その信頼性と性能の証です。

この「Nginx入門」記事では、Webサーバーの基本からNginxのインストール、設定方法、そして静的ファイル配信、リバースプロキシ、ロードバランシング、SSL設定といった主要な使い方までを網羅的に解説します。約5000語というボリュームで、初心者でもNginxの魅力と実用的な使い方を理解し、一歩踏み出せるような詳細な情報を提供することを目指します。

さあ、高速WebサーバーNginxの世界へ、一緒に飛び込みましょう。

Nginxの基本:その誕生、哲学、そして特徴

Nginxとは何か?

Nginxは、ロシアのプログラマー、Igor Sysoev氏によって開発が開始され、2004年に初めて公開されたオープンソースのWebサーバーソフトウェアです。当初は、トラフィックが非常に多いロシアの大手ポータルサイトRambler.ruのために開発されました。その目的は、従来のWebサーバーでは処理しきれない高負荷なアクセスに耐えられる、高性能かつスケーラブルなWebサーバーを構築することでした。

「Nginx」という名前には、特に公式な意味はありませんが、”engine X”と読むことから、パワフルなエンジンをイメージさせます。

Nginxのアーキテクチャ:イベント駆動、非同期、ノンブロッキング

NginxがApacheなどの他のWebサーバーと一線を画す最大の理由は、その独特のアーキテクチャにあります。多くの伝統的なWebサーバーは、クライアントからの接続ごとに新しいプロセスやスレッドを生成して処理を行う「プロセス/スレッド駆動型」モデルを採用しています。これは実装が比較的容易である反面、接続数が増えるにつれてプロセス/スレッドの生成・管理コストが増大し、リソースを大量に消費するという弱点があります。これが「C10K問題」の根本原因の一つです。

一方、Nginxは「イベント駆動型」「非同期」「ノンブロッキング」というモデルを採用しています。具体的には、以下の特徴を持ちます。

  1. Master-Workerプロセスモデル: Nginxは起動すると、まず1つのマスタープロセスを起動します。このマスタープロセスは、設定の読み込みや、後述するワーカープロセスの管理などを行います。実際のクライアントからのリクエスト処理は、マスタープロセスによって生成される複数の「ワーカープロセス」が行います。ワーカープロセスの数は、通常、CPUのコア数に合わせて設定されます。
  2. イベント駆動: ワーカープロセスは、新しい接続、データの受信、データの送信、タイマーイベントなど、様々な「イベント」の発生を待機します。
  3. 非同期・ノンブロッキング: 1つのワーカープロセスは、複数のクライアント接続を同時に処理できます。これは、あるクライアントからのリクエストでデータの読み書きや他の処理(例えば、アプリケーションサーバーへのリクエスト)が発生し、その完了を待つ必要がある場合でも、その処理が完了するのを「ブロック」せずに、すぐに他のクライアントの処理に移る(ノンブロッキングI/O)ためです。処理が完了した時点で発生する「イベント」を検知して、中断した処理を再開します。
    この非同期・ノンブロッキングな処理は、OSが提供する効率的なI/O多重化機構(Linuxのepoll, FreeBSDのkqueueなど)を利用して実現されています。

このアーキテクチャにより、Nginxは少ないリソース(メモリなど)で、非常に多数の同時接続を効率的に処理することが可能です。特に静的ファイルの配信や、バックエンドのアプリケーションサーバーへのリバースプロキシとして利用する際に、その高性能を発揮します。

NginxとApacheの違い

NginxとApacheはどちらも広く使われているWebサーバーですが、その設計思想と得意な分野が異なります。

特徴 Nginx Apache HTTP Server
アーキテクチャ イベント駆動、非同期、ノンブロッキング プロセス/スレッド駆動型
得意な処理 高い同時接続数、静的ファイル配信、リバースプロキシ、ロードバランシング 動的コンテンツの処理、豊富なモジュール群
設定方法 シンプルかつ構造的、パフォーマンス重視 .htaccessによる柔軟な設定、機能豊富
モジュール コンパイル時に組み込む、または動的モジュール (限られる) 動的にロード可能、非常に豊富
リソース消費 低い 接続数に応じて増加しやすい
設定変更 設定ファイルを編集後、リロードが必要 設定ファイルを編集後、リロードまたは.htaccessの即時反映

一般的に、静的コンテンツの配信性能や同時接続数におけるスケーラビリティではNginxが優位に立つことが多いです。一方、Apacheは歴史が長く、機能が豊富で、.htaccessファイルによるディレクトリ単位での柔軟な設定変更が可能なため、共有ホスティング環境などでは依然として多く利用されています。

現代のWebアプリケーションでは、Nginxをフロントエンドに置いて静的ファイルの配信やリバースプロキシを担当させ、Apacheや他のアプリケーションサーバー(例えば、PHP-FPM, Gunicorn, uWSGIなど)をバックエンドに置いて動的コンテンツの処理を行う、という構成が一般的になっています。Nginxはリバースプロキシとしての機能が非常に優れているため、このような構成において真価を発揮します。

Nginxの主な機能

Nginxは単なるWebサーバーとしてだけでなく、以下のような多様な機能を提供します。

  • Webサーバー: HTML、CSS、JavaScript、画像などの静的ファイルを高速に配信します。
  • リバースプロキシ: クライアントからのリクエストを受け付け、それを内部ネットワークにある別のサーバー(アプリケーションサーバーなど)に転送し、そのレスポンスをクライアントに返します。バックエンドサーバーを外部に公開することなく、負荷分散、セキュリティ向上、SSLオフロードなどを実現できます。
  • ロードバランサー: 複数のバックエンドサーバーにリクエストを分散させることで、負荷を平準化し、サービスの可用性を高めます。
  • HTTPキャッシュ: リバースプロキシとして動作する際に、バックエンドからのレスポンスをキャッシュし、同じリクエストが来た場合にキャッシュから返すことで、バックエンドの負荷を軽減し、応答速度を向上させます。
  • メールプロキシ: IMAP、POP3、SMTPプロトコルのプロキシとしても機能します。
  • TLS/SSLターミネーション: 暗号化されたHTTPS接続をNginxで受け付け、バックエンドサーバーへは平文(HTTP)で転送することができます。これにより、バックエンドサーバーの負荷を軽減し、設定を簡素化できます。

これらの多機能性と高性能が、Nginxが現代のWebインフラで広く採用されている理由です。

Nginxのインストール

Nginxを使い始めるには、まずシステムにインストールする必要があります。主要なOS(Linuxディストリビューション)における一般的なインストール方法を見てみましょう。

Linux (Ubuntu/Debian)

UbuntuやDebianでは、aptパッケージマネージャーを使って簡単にNginxをインストールできます。

  1. パッケージリストの更新: 最新のパッケージ情報を取得します。
    bash
    sudo apt update
  2. Nginxのインストール: Nginxパッケージをインストールします。
    bash
    sudo apt install nginx

    これにより、Nginxの本体、設定ファイル、デフォルトのWebサイトなどがインストールされます。
  3. サービスの起動と確認: インストールが完了すると、多くの場合Nginxは自動的に起動します。起動状態を確認します。
    bash
    sudo systemctl status nginx

    active (running)と表示されていれば正常に起動しています。
  4. サービスの管理: Nginxのサービスはsystemctlコマンドで管理できます。
    • 起動: sudo systemctl start nginx
    • 停止: sudo systemctl stop nginx
    • 再起動: sudo systemctl restart nginx
    • 設定ファイルのリロード: sudo systemctl reload nginx (設定変更をサービス停止なしで適用)
  5. ファイアウォールの設定 (UFW): もしUFWファイアウォールが有効になっている場合、HTTP (80番ポート) および HTTPS (443番ポート) の通信を許可する必要があります。
    bash
    sudo ufw allow 'Nginx HTTP'
    # HTTPSも使う場合はこちらも許可
    # sudo ufw allow 'Nginx HTTPS'
    sudo ufw reload

    sudo ufw statusでルールが適用されたか確認できます。
  6. 動作確認: ウェブブラウザでサーバーのIPアドレスまたはドメイン名にアクセスします。Nginxのデフォルトの歓迎ページが表示されれば、インストールは成功です。

Linux (CentOS/RHEL/Fedora)

CentOSやRHEL、Fedoraでは、yumまたはdnfパッケージマネージャーを使ってインストールします。

  1. パッケージリストの更新: 最新のパッケージ情報を取得します。
    bash
    sudo yum update # または dnf update
  2. Nginxのインストール: Nginxパッケージをインストールします。EPEL (Extra Packages for Enterprise Linux) リポジトリが必要な場合があります。
    • まずEPELリポジトリをインストールします(CentOS/RHEL 7以下)。
      bash
      sudo yum install epel-release
    • CentOS 8以上 / Fedoraの場合はdnfを使います。
      bash
      sudo dnf install epel-release # CentOS 8 / RHEL 8
    • Nginxをインストールします。
      bash
      sudo yum install nginx # または dnf install nginx
  3. サービスの起動と有効化: Nginxサービスを起動し、システム起動時に自動的に起動するように設定します。
    bash
    sudo systemctl start nginx
    sudo systemctl enable nginx
  4. サービスの確認: 起動状態を確認します。
    bash
    sudo systemctl status nginx

    active (running)と表示されていれば正常に起動しています。
  5. サービスの管理: systemctlコマンドで管理します(上記Ubuntuと同様)。
  6. ファイアウォールの設定 (firewalld): firewalldファイアウォールが有効な場合、HTTP/HTTPSを許可します。
    bash
    sudo firewall-cmd --permanent --add-service=http
    # HTTPSも使う場合はこちらも許可
    # sudo firewall-cmd --permanent --add-service=https
    sudo firewall-cmd --reload

    sudo firewall-cmd --list-allでルールが適用されたか確認できます。
  7. 動作確認: ウェブブラウザでサーバーのIPアドレスまたはドメイン名にアクセスします。Nginxのデフォルトページが表示されれば成功です。

ソースコードからのコンパイル (上級者向け)

上記のパッケージ管理システムからのインストールが最も一般的で推奨されますが、特定のモジュールを組み込みたい場合や、最新版を使いたい場合、最適化されたビルドを行いたい場合などは、ソースコードからコンパイルしてインストールすることも可能です。この方法はより複雑で、必要なライブラリのインストールやコンパイルオプションの指定など、高度な知識が必要です。

  1. 必要なビルドツールとライブラリのインストール: gcc, make, zlib-devel, pcre-devel, openssl-develなどのパッケージが必要です。
  2. Nginxのソースコードをダウンロード: 公式サイトから最新のソースコードをダウンロードします。
  3. configureスクリプトの実行: インストールディレクトリ、有効にするモジュール、その他のオプションを指定してconfigureスクリプトを実行します。
    bash
    ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_gzip_module ...
  4. makeとmake installの実行: ソースコードをコンパイルし、指定したディレクトリにインストールします。
    bash
    make
    sudo make install
  5. サービス管理の設定: systemdなどのinitシステムからNginxを管理するための設定ファイルを別途作成する必要があります。

入門としてはパッケージ管理システムからのインストールで十分です。まずはそこから始めましょう。

Nginxの設定:設定ファイルの構造と基本ディレクティブ

Nginxの心臓部とも言えるのが、設定ファイルです。Nginxの設定は、特定の構文を持つテキストファイルによって行われます。

設定ファイルの場所

主要なLinuxディストリビューションでは、Nginxのメイン設定ファイルは通常 /etc/nginx/nginx.conf にあります。

また、より構造的に設定を管理するために、他の設定ファイルをインクルードする形で設定が分割されていることが多いです。

  • /etc/nginx/nginx.conf: メイン設定ファイル。大局的な設定や、他の設定ファイルをインクルードする記述があります。
  • /etc/nginx/conf.d/*.conf: 追加の設定ファイルを置くディレクトリ。メイン設定ファイルからinclude /etc/nginx/conf.d/*.conf;のような形で読み込まれます。ここに仮想ホスト(サーバーブロック)の設定を置くことが多いです。
  • /etc/nginx/sites-available/: 利用可能な仮想ホストの設定ファイルを置くディレクトリ(Ubuntu/Debian系でよく使われる方式)。
  • /etc/nginx/sites-enabled/: 実際に有効化されている仮想ホストへのシンボリックリンクを置くディレクトリ。/etc/nginx/nginx.confからinclude /etc/nginx/sites-enabled/*;のような形で読み込まれます。サイトを有効化するには、sites-availableにある設定ファイルからsites-enabledへシンボリックリンクを作成します(例: sudo ln -s /etc/nginx/sites-available/your_site /etc/nginx/sites-enabled/)。無効化するには、シンボリックリンクを削除します。

この記事では、conf.dディレクトリに設定ファイルを作成していく方式を基本とします。新しいサイトの設定を追加する場合、/etc/nginx/conf.d/your_site.confのようなファイルを作成するのが一般的です。

設定ファイルの構文:ディレクティブとコンテキスト

Nginxの設定ファイルは、シンプルな構文で記述されます。

  • ディレクティブ: 設定の命令です。ディレクティブ名 パラメータ; の形式で記述されます。各行はセミコロン(;)で終わる必要があります。
    例: worker_processes auto;
  • コンテキスト: 複数のディレクティブをまとめるブロックです。コンテキスト名 { ... } の形式で記述されます。コンテキストはネスト(入れ子)にすることができます。

主要なコンテキストは以下の通りです。

  • main: 設定ファイルの最上位にあるグローバルなコンテキスト。ワーカープロセス数など、全体に関わる設定を記述します。
  • events: ネットワーク接続の処理方法に関する設定。ワーカー接続数などを記述します。
  • http: HTTPサーバー全体に関わる設定。一般的なMIMEタイプ、ログ設定、HTTPモジュールの設定などを記述します。このコンテキストの中にserverコンテキストを記述します。
  • server: 仮想ホストの設定。特定のドメイン名やポート番号に対するリクエストをどのように処理するかを定義します。HTTPコンテキストの中に複数記述できます。
  • location: 特定のURLパスに対するリクエストをどのように処理するかを定義します。serverコンテキストの中に複数記述できます。
  • upstream: ロードバランシングなどで使用するバックエンドサーバー群を定義します。httpコンテキストの中に記述します。

設定ファイルの簡単な構造は以下のようになります。

“`nginx

main コンテキスト

user www-data; # Nginxを実行するユーザー (Ubuntu/Debianの場合)
worker_processes auto; # ワーカープロセスの数

events コンテキスト

events {
worker_connections 1024; # 1つのワーカープロセスが処理できる同時接続数
# その他のイベント設定…
}

http コンテキスト

http {
include /etc/nginx/mime.types; # MIMEタイプ定義ファイルをインクルード
default_type application/octet-stream; # デフォルトのMIMEタイプ

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"'; # ログフォーマット定義

access_log /var/log/nginx/access.log main; # アクセスログの出力先とフォーマット
error_log /var/log/nginx/error.log error; # エラーログの出力先とレベル

sendfile on; # sendfile()システムコールを使用するか
tcp_nopush on; # TCP_NOPUSHオプションを使用するか

keepalive_timeout 65; # Keep-Alive接続のタイムアウト時間

gzip on; # Gzip圧縮を有効にするか
# その他のgzip設定...

# server コンテキスト (仮想ホスト1)
server {
    listen 80; # リッスンするポート番号
    server_name example.com www.example.com; # サイトのドメイン名

    # location コンテキスト (ルートパス)
    location / {
        root /var/www/html; # ドキュメントルートディレクトリ
        index index.html index.htm; # デフォルトのインデックスファイル
    }

    # その他のlocationブロック...

    # エラーページの設定
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

# server コンテキスト (仮想ホスト2)
# 別のドメイン名やポートで設定...
# server { ... }

# upstream コンテキスト
# upstream backend_servers { ... }

}
“`

設定ファイルのテストとリロード

設定ファイルを変更した後は、必ず構文が正しいかテストしましょう。

bash
sudo nginx -t

test is successfulと表示されればOKです。もしエラーが出た場合は、表示された行番号などを参考に修正します。

設定を反映させるには、Nginxサービスをリロードします。

bash
sudo systemctl reload nginx

これにより、現在処理中のリクエストへの影響を最小限に抑えながら、新しい設定が適用されます。再起動(restart)は、Nginxプロセスを一度完全に停止させてから起動するため、サービスが一時的に停止します。特別な理由がない限り、設定変更の際はリロードが推奨されます。

Nginxの静的ファイル配信

Nginxは静的ファイルの配信において非常に高い性能を発揮します。HTML、CSS、JavaScript、画像、フォントなどのファイルを効率的にユーザーに届けます。

root ディレクティブと alias ディレクティブ

静的ファイルを配信するために最も重要なのは、rootまたはaliasディレクティブで、どのディレクトリからファイルを配信するかを指定することです。これらは主にserverまたはlocationコンテキストで使用されます。

  • root ディレクティブ: リクエストされたURIに、指定されたパスを「ルート」として前置します。
    “`nginx
    server {
    listen 80;
    server_name example.com;

    location / {
        root /var/www/html; # リクエストされたURIは /var/www/html の下のパスとして解釈される
        index index.html;
    }
    
    location /images/ {
        root /var/www/static; # /images/example.png へのリクエストは /var/www/static/images/example.png を探す
    }
    

    }
    ``/images/example.pngへのリクエストの場合、rootで指定された/var/www/staticとリクエストURIの/images/example.pngが結合され、/var/www/static/images/example.png`というファイルパスが生成されます。

  • alias ディレクティブ: リクエストされたURIの特定部分を、指定されたパスで「置き換え」ます。主にlocationコンテキストで使用され、rootよりも優先されます。
    “`nginx
    server {
    listen 80;
    server_name example.com;

    location /static/ {
        alias /var/www/static_files/; # /static/style.css へのリクエストは /var/www/static_files/style.css を探す
    }
    
    location /images/ {
        alias /var/www/images/; # /images/logo.png へのリクエストは /var/www/images/logo.png を探す
    }
    

    }
    ``/static/style.cssへのリクエストの場合、/static/というパスが/var/www/static_files/で置き換えられ、/var/www/static_files/style.cssというファイルパスが生成されます。
    **注意点**:
    aliasを使用する場合、locationブロックのURIの末尾がスラッシュ(/`)で終わる場合、aliasで指定するパスの末尾もスラッシュで終わらせるのが慣例的です。

どちらを使うべきかは状況によりますが、rootはLocationブロック内でさらにサブディレクトリを指定する場合にシンプルになりやすく、aliasはURI構造と物理的なファイルパス構造が大きく異なる場合や、特定のパスだけ別の場所にマッピングしたい場合に便利です。

index ディレクティブ

ディレクトリへのリクエスト(例: //docs/)が来た際に、どのファイルをデフォルトで返すかを指定します。複数のファイルを指定でき、最初に見つかったファイルが返されます。

nginx
location / {
root /var/www/html;
index index.html index.htm default.html; # この順でファイルを探す
}

静的ファイルのキャッシュ設定 (expires)

ブラウザに静的ファイルをキャッシュさせることで、ページの読み込み速度を向上させ、サーバーへのリクエスト数を減らすことができます。expiresディレクティブは、レスポンスのCache-ControlヘッダーやExpiresヘッダーを設定します。

nginx
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
root /var/www/html;
expires 30d; # 30日間キャッシュさせる
# その他の設定(gzipなど)
}

この例では、.jpg, .jpeg, .png, .gif, .ico, .css, .jsで終わるファイルに対して、30日間キャッシュするようブラウザに指示しています。時間は秒数、分数(m)、時間(h)、日数(d)、週(w)、月(M)、年(y)などで指定できます。expires off;でキャッシュを無効化、expires epoch;で過去の日時を指定して常に再検証させる、expires max;で可能な限り長くキャッシュさせる(Cache-Control: max-age=31536000)といった設定も可能です。

Gzip圧縮の設定

静的ファイル(特にHTML, CSS, JavaScript)をサーバー側で圧縮して送信することで、転送量を減らし、ページの読み込み速度を向上させることができます。Nginxではgzipモジュールを使ってこれを実現します。

“`nginx
http {
# … 他のhttp設定 …

gzip on; # Gzip圧縮を有効にする
gzip_vary on; # Vary: Accept-Encoding ヘッダーを追加
gzip_proxied any; # プロキシされたリクエストでも圧縮するか
gzip_comp_level 6; # 圧縮レベル (1-9, 6が一般的)
gzip_buffers 16 8k; # 圧縮バッファの設定
gzip_http_version 1.1; # 圧縮を有効にするHTTPプロトコルバージョン
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # 圧縮するMIMEタイプ

}
``gzip on;で基本的な圧縮が有効になります。gzip_types`で圧縮対象となるMIMEタイプを指定するのが重要です。画像やPDFなどのバイナリファイルは既に圧縮されていることが多いため、対象に含めないのが一般的です。

これらの設定を組み合わせることで、Nginxは静的ファイルを非常に効率的に配信できます。

Nginxをリバースプロキシとして使う

リバースプロキシは、クライアントからのリクエストを受け取り、それを背後にある別のサーバー(アプリケーションサーバー、APIサーバーなど)に転送し、そのサーバーからのレスポンスを受け取ってクライアントに返す役割を果たします。Nginxはこのリバースプロキシ機能に優れており、現代の多くのWebアプリケーションアーキテクチャで重要な位置を占めています。

リバースプロキシのメリット

  1. セキュリティ向上: バックエンドサーバーをインターネットから直接見えないようにし、Nginxだけを公開することで、攻撃対象を減らします。NginxでSSL終端、アクセス制限、基本的なWAF機能などを一元的に行うことができます。
  2. 負荷分散: 複数のバックエンドサーバーがある場合に、リクエストを分散させて負荷を平準化します(これはロードバランシング機能の一部です)。
  3. SSLオフロード: 暗号化/復号化の処理は計算負荷が高いため、これをNginxに担当させることで、バックエンドサーバーの負荷を軽減できます。
  4. キャッシュ: バックエンドからのレスポンスをNginxがキャッシュし、同じリクエストに対してはキャッシュから返すことで、バックエンドへのアクセスを減らし、応答速度を向上させます。
  5. 静的ファイルの配信: Nginxは静的ファイルの配信が高速なので、静的ファイルはNginx自身で配信し、動的な処理が必要なリクエストだけをバックエンドに転送するという役割分担ができます。
  6. メンテナンス性の向上: バックエンドサーバーのメンテナンスや交換が必要な場合でも、Nginxの設定を変更するだけで対応できることがあります。

proxy_pass ディレクティブ

リバースプロキシを設定するための最も基本的なディレクティブはproxy_passです。これはlocationコンテキストの中で使用され、リクエストを転送するバックエンドサーバーのアドレスを指定します。

“`nginx
server {
listen 80;
server_name example.com;

location /api/ {
    # /api/ で始まるリクエストを http://localhost:8080 に転送
    proxy_pass http://localhost:8080;
}

location /app/ {
    # /app/ で始まるリクエストを http://backend.internal/app/ に転送
    # proxy_passのURIの末尾にスラッシュがあるか無いかで挙動が変わる
    # この場合、リクエストURIの /app/ が削除されて転送される
    proxy_pass http://backend.internal/;
}

location /static/ {
    # 静的ファイルはNginxで直接配信
    alias /var/www/static/;
    expires 30d;
}

location / {
    # その他のリクエストはデフォルトのバックエンドに転送
    # proxy_passのURIの末尾にスラッシュが無い場合、リクエストURI全体が結合される
    proxy_pass http://localhost:3000;
}

}
“`

proxy_passの挙動は、指定するURLのパス部分の末尾にスラッシュがあるかないかで異なります。

  • proxy_pass http://backend.internal/; (末尾にスラッシュあり): locationでマッチしたURIのパス部分(例: /api/)が削除され、バックエンドのURL(http://backend.internal/)と残りのリクエストパス(例: users)が結合されます。結果、http://backend.internal/usersへのリクエストとなります。
  • proxy_pass http://backend.internal; (末尾にスラッシュなし): locationでマッチしたURIのパス部分が削除されずに、バックエンドのURLと結合されます。/api/usersへのリクエストはhttp://backend.internal/api/usersに転送されます。

どちらの挙動を望むかに応じて使い分けが必要です。通常は末尾にスラッシュを付ける方が、バックエンドアプリケーションが期待するパス構成になりやすいでしょう。

プロキシ関連のヘッダー

リバースプロキシを介してリクエストがバックエンドに転送される際、クライアントの元の情報(IPアドレス、ホスト名、プロトコルなど)をバックエンドに伝えるために、特定のHTTPヘッダーを付与することが一般的です。

  • X-Forwarded-For: クライアントのオリジナルのIPアドレス(と、プロキシを介した場合はその途中のIPアドレス)を伝えます。
  • X-Real-IP: クライアントのオリジナルのIPアドレスを伝えます。
  • Host: クライアントがリクエストしたオリジナルのホスト名(ドメイン名)を伝えます。
  • X-Forwarded-Proto: クライアントが使用したプロトコル(httpまたはhttps)を伝えます。

これらのヘッダーは、proxy_set_headerディレクティブを使って設定します。

“`nginx
location / {
proxy_pass http://backend;

# プロキシ関連のヘッダーを設定
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

}
``
*
$host: リクエストヘッダーのHostフィールドの値。なければserver_nameまたはIPアドレス。
*
$remote_addr: クライアントのIPアドレス。
*
$proxy_add_x_forwarded_for:$http_x_forwarded_for変数に$remote_addrを追加したもの。既存のX-Forwarded-Forヘッダーがあればそれに追記し、なければ新規に作成します。
*
$scheme`: リクエストのスキーム (http または https)。

これらのヘッダーを設定することで、バックエンドアプリケーションはリバースプロキシの後ろにいることを意識せず、クライアントの元の情報を利用できます。

WebSocketプロキシ

NginxはWebSocket接続のリバースプロキシとしても機能します。WebSocketはHTTP/1.1のUpgradeヘッダーを使って接続を確立し、確立後は持続的な双方向通信を行います。NginxでWebSocketをプロキシするには、UpgradeヘッダーとConnectionヘッダーをバックエンドに正しく転送する必要があります。

“`nginx
location /ws/ {
proxy_pass http://backend_websocket;
proxy_http_version 1.1; # HTTP/1.1を使用
proxy_set_header Upgrade $http_upgrade; # Upgradeヘッダーをバックエンドに転送
proxy_set_header Connection “upgrade”; # Connectionヘッダーを設定

# オプション: WebSocketタイムアウト設定
proxy_read_timeout 86400; # 読み取りタイムアウト
proxy_send_timeout 86400; # 送信タイムアウト

}
``proxy_http_version 1.1;は、Upgradeヘッダーを使用するために必要です。proxy_set_header Upgrade $http_upgrade;はクライアントからのUpgradeヘッダー(通常はwebsocket)をバックエンドに転送します。proxy_set_header Connection “upgrade”;はHTTP/1.1のUpgradeメカニズムにおいて、Connectionヘッダーをupgrade`に設定する必要があるためです。

プロキシキャッシュ (proxy_cache)

リバースプロキシとして動作する際に、バックエンドサーバーからのレスポンスをNginxサーバーのディスク上にキャッシュすることで、同じリクエストに対する応答速度を向上させ、バックエンドの負荷を軽減できます。

  1. キャッシュディレクトリの設定: まず、httpコンテキストでキャッシュゾーンを定義します。
    nginx
    http {
    # ...
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m max_size=1g;
    # /var/cache/nginx: キャッシュファイルの保存ディレクトリ
    # levels=1:2: キャッシュディレクトリの階層構造 (例: /var/cache/nginx/c/29/...)
    # keys_zone=my_cache:10m: キャッシュキーとメタデータを保存する共有メモリゾーン名(my_cache)とサイズ(10MB)
    # inactive=60m: 60分間アクセスがなかったキャッシュアイテムは削除
    # max_size=1g: キャッシュの最大サイズ (1GB)。これを超えると、最も古いキャッシュから削除される
    # ...
    }

    指定したディレクトリが存在しない場合は作成し、Nginx実行ユーザー(例: www-data)が書き込めるようにパーミッションを設定します。
  2. locationブロックでのキャッシュ利用: locationブロック内で、上記のキャッシュゾーンを使用するように設定します。
    nginx
    location /images/ {
    proxy_pass http://backend_images;
    proxy_cache my_cache; # 使用するキャッシュゾーン名を指定
    proxy_cache_valid 200 30d; # ステータスコード200のレスポンスを30日間キャッシュ
    proxy_cache_valid 404 1m; # ステータスコード404のレスポンスを1分間キャッシュ
    proxy_cache_key "$scheme$request_method$host$request_uri"; # キャッシュキーの定義
    }

    proxy_cacheディレクティブで、どのキャッシュゾーンを使用するか指定します。proxy_cache_validで、特定のステータスコードのレスポンスをどれだけの間キャッシュするか指定します。proxy_cache_keyは、どのリクエストに対してキャッシュを使用するかを判断するためのキーを定義します。デフォルトは$scheme$proxy_host$request_uriですが、状況に応じて変更できます。

キャッシュは、頻繁にアクセスされるが変わらない、またはあまり頻繁に変わらないコンテンツ(例えば、画像、CSS、JavaScript、特定のAPIレスポンスなど)に対して非常に有効です。

Nginxをロードバランサーとして使う

ロードバランシングは、複数のサーバー(バックエンドサーバー)にリクエストを分散させることで、個々のサーバーへの負荷を軽減し、全体のスループットと可用性を向上させる技術です。Nginxはリバースプロキシ機能の一部として、強力なロードバランシング機能を提供します。

ロードバランシングとは何か、その目的

Webサイトやアプリケーションへのアクセスが増加すると、単一のサーバーでは処理しきれなくなることがあります。サーバーを複数台用意し、それらのサーバー全体でトラフィックを処理することで、この問題を解決できます。これがロードバランシングの基本的な考え方です。

ロードバランシングの主な目的は以下の通りです。

  • 負荷分散: 複数のサーバー間で均等に、または適切なアルゴリズムに従って負荷を分散させます。
  • 可用性向上: 特定のサーバーがダウンしても、他のサーバーが処理を引き継ぐことで、サービス全体が停止することを防ぎます。
  • スケーラビリティ: 必要に応じてサーバーを追加することで、容易に処理能力をスケールアウトできます。

upstream ブロックの定義

Nginxでロードバランシングを設定するには、まずhttpコンテキスト内でupstreamブロックを定義し、バックエンドサーバー群をリストアップします。

“`nginx
http {
# …

upstream backend_servers {
    server 192.168.1.10:8000;
    server 192.168.1.11:8000;
    server unix:/tmp/backend.sock; # Unixドメインソケットも指定可能
    server backend3.internal weight=3; # 重み付け (後述)
    server backend4.internal max_fails=3 fail_timeout=30s; # ヘルスチェック (後述)
}

server {
    listen 80;
    server_name myapp.com;

    location / {
        # upstreamブロックで定義したサーバー群にリクエストを転送
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        # その他のproxy設定...
    }
}

}
``upstreamブロック名は任意ですが、ここではbackend_serversとしています。このブロック内で、serverディレクティブを使って各バックエンドサーバーのアドレス(IPアドレスまたはホスト名、ポート番号)を指定します。proxy_passディレクティブで、バックエンドサーバーとしてこのupstream`ブロックの名前を指定します。

ロードバランシングの手法 (アルゴリズム)

upstreamブロック内で、リクエストをどのサーバーに転送するかを決定するロードバランシングアルゴリズムを指定できます。指定しない場合、デフォルトは「ラウンドロビン」になります。

  • round_robin (デフォルト): リクエストをサーバーリストの上から順番に、均等に振り分けます。最もシンプルで一般的な方法です。
    nginx
    upstream backend_servers {
    # round_robin はデフォルトなので明示的に書く必要はない
    server 192.168.1.10;
    server 192.168.1.11;
    }
  • least_conn: その時点でアクティブな接続数が最も少ないサーバーにリクエストを転送します。処理に時間のかかるリクエストがある場合などに、接続数の少ないサーバーに優先的に割り振ることで、サーバー間の負荷をより均等に分散させる効果があります。
    nginx
    upstream backend_servers {
    least_conn;
    server 192.168.1.10;
    server 192.168.1.11;
    }
  • ip_hash: クライアントのIPアドレスに基づいてリクエストをハッシュし、その結果に基づいてサーバーを選択します。同じIPアドレスからのリクエストは常に同じサーバーに転送されるため、セッションの維持が必要なアプリケーション(ステートフルなアプリケーション)に適しています。クライアントがNAT環境の後ろにいる場合など、複数のクライアントが同じIPアドレスを共有している場合は、特定のサーバーに負荷が集中する可能性があります。
    nginx
    upstream backend_servers {
    ip_hash;
    server 192.168.1.10;
    server 192.168.1.11;
    }
  • hash: 指定したキー(URI、$request_uri、カスタムヘッダーなど)に基づいてリクエストをハッシュし、サーバーを選択します。ip_hashよりも柔軟なセッション維持メカニズムを提供できます。Memcachedサーバーのロードバランシングなどにも利用されます。
    nginx
    upstream backend_servers {
    hash $request_uri consistent; # consistentパラメータで、サーバー追加/削除時のキーマッピング変更を最小限に抑える
    server 192.168.1.10;
    server 192.168.1.11;
    }
  • random: リクエストをランダムにサーバーに転送します。
    nginx
    upstream backend_servers {
    random;
    server 192.168.1.10;
    server 192.168.1.11;
    }
  • sticky (Nginx Plus / 3rd Party Module): クッキーに基づいてクライアントを特定のサーバーに固定します。より洗練されたセッション維持が必要な場合に利用されます。これはオープンソース版には標準では含まれていません。

サーバーパラメータ

upstreamブロック内のserverディレクティブには、サーバーの状態や重みを指定するパラメータを付与できます。

  • weight=number: サーバーの重み。デフォルトは1。重みの大きいサーバーほど多くのリクエストを受け取るようになります。例えば、性能の違うサーバーを混在させる場合に調整します。
    nginx
    upstream backend_servers {
    server 192.168.1.10 weight=3; # 3倍のリクエストを受け取る
    server 192.168.1.11 weight=1;
    }
  • max_fails=number: 指定した回数失敗(接続確立できない、タイムアウトなど)が発生した場合、そのサーバーは一時的にダウンしていると見なされます。デフォルトは1。
  • fail_timeout=time: max_failsで指定した回数失敗した後、そのサーバーをダウンと見なす期間。この期間中は、リクエストはそのサーバーに転送されません。期間経過後、最初の1つのリクエストがテストとして転送され、成功すればサーバーは復旧と見なされます。デフォルトは10秒。
    nginx
    upstream backend_servers {
    server 192.168.1.10 max_fails=3 fail_timeout=20s;
    server 192.168.1.11;
    }
  • backup: バックアップサーバーとして指定します。他の全てのサーバーがダウンした場合にのみ、このサーバーにリクエストが転送されます。
    nginx
    upstream backend_servers {
    server 192.168.1.10;
    server 192.168.1.11;
    server 192.168.1.12 backup; # バックアップサーバー
    }
  • down: 一時的にサーバーをダウンとしてマークし、リクエストを転送しないようにします。メンテナンス時などに使用します。
    nginx
    upstream backend_servers {
    server 192.168.1.10 down; # このサーバーにはリクエストが転送されない
    server 192.168.1.11;
    }

ヘルスチェック

上記のmax_failsfail_timeoutによる基本的なヘルスチェック機能はオープンソース版でも利用できます。これは、サーバーへのリクエストが失敗した場合にそのサーバーを一時的に無効にするというものです。

より高度なヘルスチェック(例えば、定期的にサーバーに特定のURLにアクセスしてレスポンス内容をチェックするなど)は、オープンソース版のNginxには標準では含まれていません。Nginx Plus(商用版)には高度なアクティブヘルスチェック機能が搭載されています。オープンソース版で実現するには、サードパーティのモジュールをコンパイルして組み込むか、keepalivedのような別のツールと連携させる必要があります。

ロードバランシングは、現代のWebサービスにおいて非常に重要な技術であり、Nginxはその中心的な役割を担うことができます。

SSL/TLSの設定 (HTTPS化)

インターネット上の通信を暗号化し、セキュリティと信頼性を確保するために、HTTPS (HTTP over SSL/TLS) は不可欠です。NginxはSSL/TLS終端(クライアントからのHTTPS接続をNginxで復号化し、バックエンドへはHTTPで転送する)の機能も提供しており、これもNginxの重要な用途の一つです。

HTTPSとは何か、その必要性

HTTPはデータを平文でやり取りするため、通信経路上の第三者によって盗聴、改ざん、なりすましのリスクがあります。特に個人情報やクレジットカード情報などを扱うウェブサイトでは、これらのリスクを排除するためにHTTPSが必須です。

HTTPSでは、SSL/TLSプロトコルを使用して通信を暗号化します。これにより、クライアントとサーバー間のデータのやり取りが保護されます。また、SSL証明書を利用することで、アクセスしているウェブサイトが本物であるか(サーバーの認証)を確認できます。

今日では、セキュリティ意識の高まり、検索エンジン(Googleなど)によるHTTPSサイトの優遇、そしてLet’s Encryptのような無料の証明書発行サービスの登場により、ほとんど全てのウェブサイトでHTTPSを導入することが強く推奨されています。

SSL証明書の取得

HTTPSを有効にするには、サーバーにSSL証明書をインストールする必要があります。SSL証明書は、信頼できる第三者機関(認証局: Certificate Authority, CA)によって発行されます。

  • 有料証明書: 様々な種類の証明書(ドメイン認証、組織認証、EV証明書など)があり、企業のウェブサイトなどで広く利用されています。Comodo (Sectigo), DigiCert, GlobalSignなどのCAから購入できます。
  • 無料証明書: Let’s Encryptは、無料でSSL証明書を発行してくれるCAです。Automated Certificate Management Environment (ACME) プロトコルを使用して、証明書の取得と更新を自動化できるツール(Certbotなど)が提供されており、個人ブログや中小サイトなど、広く利用されています。

この記事では、Let’s EncryptとCertbotを使った証明書取得・設定連携が最も一般的になっているため、これを前提とした設定例を示します。Certbotツールは、Nginxの設定を自動的に変更してHTTPSを有効にする機能も持っています。

NginxでのSSL/TLS設定ファイル記述

SSL/TLSに関する設定は、通常、HTTPS(デフォルトポート443)でリッスンするserverブロック内で行います。

“`nginx
server {
listen 80;
server_name example.com www.example.com;

# HTTPでアクセスが来たらHTTPSにリダイレクトする設定(推奨)
return 301 https://$host$request_uri;

}

server {
listen 443 ssl; # ポート443でSSL/TLS接続を受け付ける
server_name example.com www.example.com;

# SSL証明書と秘密鍵のパスを指定
# Certbotで取得した場合の例
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # 証明書ファイル
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # 秘密鍵ファイル

# SSL/TLS関連の推奨設定
ssl_protocols TLSv1.2 TLSv1.3; # 使用を許可するTLSプロトコルバージョン
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384'; # 許可する暗号スイート
ssl_prefer_server_ciphers on; # サーバー側の暗号スイートの順番を優先
ssl_session_cache shared:SSL:10m; # SSLセッションキャッシュの設定
ssl_session_timeout 10m; # SSLセッションタイムアウト
ssl_session_tickets off; # SSLセッションチケットを無効化 (Forward Secrecyのため)

# HTTP Strict Transport Security (HSTS) ヘッダー
# 初回アクセス以降、ブラウザにHTTPSでのみアクセスするよう強制 (セキュリティ向上)
# max-age: HSTSを有効にする期間 (秒)。preloadはブラウザに事前にHSTSリストに登録させる (hsts.badssl.comで確認)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s; # CAのOCSPレスポンダーにアクセスするためのDNSリゾルバ
resolver_timeout 5s;

# その他の設定 (root, index, locationなど)
location / {
    root /var/www/html;
    index index.html;
}

# アプリケーションサーバーへのプロキシ設定など
# location /api/ {
#     proxy_pass http://backend_api;
#     # ここでSSLオフロードが行われる: NginxがHTTPSを受け付け、バックエンドへはHTTPで転送
#     proxy_set_header Host $host;
#     proxy_set_header X-Real-IP $remote_addr;
#     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#     proxy_set_header X-Forwarded-Proto $scheme; # バックエンドに元のプロトコルを伝える
# }

}
``
*
listen 443 ssl;: ポート443でSSL/TLS接続を受け付けることを指定します。
*
ssl_certificatessl_certificate_key: それぞれ証明書ファイルと秘密鍵ファイルのパスを指定します。これらのファイルはCAから取得したものです。
*
ssl_protocols: 使用を許可するTLSプロトコルのバージョンを指定します。古い脆弱なSSLv2やSSLv3、TLSv1.0, TLSv1.1は無効にし、TLSv1.2以降のみを有効にするのが現在のベストプラクティスです。
*
ssl_ciphers: 使用を許可する暗号スイートのリストを指定します。これも安全なもののみを選択し、古い脆弱なものは含めないようにします。Mozilla SSL Configuration Generatorなどのツールを利用すると、目的(Modern, Intermediate, Old)に応じた推奨設定を生成してくれます。
*
ssl_prefer_server_ciphers on;: クライアントとサーバーの両方がサポートする暗号スイートの中から、サーバーが提示するリストの順番で最初に一致するものを使用します。安全な暗号スイートをリストの上位に置くことで、より安全な暗号化方式が優先されるようになります。
*
ssl_session_cache,ssl_session_timeout,ssl_session_tickets: SSLセッションの再利用に関する設定です。セッションを再利用することで、接続確立時のハンドシェイク処理を省略でき、パフォーマンスが向上します。ssl_session_tickets off;はForward Secrecyの観点から推奨されることがあります。
*
add_header Strict-Transport-Security …: HSTS (HTTP Strict Transport Security) ヘッダーは、一度そのサイトにHTTPSでアクセスしたブラウザに対して、以降、指定された期間はHTTPでアクセスしようとしても強制的にHTTPSにリダイレクトさせるという強力なセキュリティ機能です。中間者攻撃(Man-in-the-Middle Attack)によるダウングレード攻撃を防ぎます。includeSubDomainsはサブドメインにも適用、preloadは主要ブラウザのHSTSプリロードリストに登録するためのフラグです(登録申請が必要です)。
*
ssl_stapling on;,ssl_stapling_verify on;,resolver …: OCSP Staplingは、証明書の失効情報を効率的に提供する仕組みです。NginxがCAから証明書の失効情報(OCSPレスポンス)を取得し、それをSSLハンドシェイク時にクライアントに提供します。これにより、クライアントは別途CAに問い合わせることなく証明書の有効性を確認でき、パフォーマンスとプライバシーが向上します。resolver`ディレクティブは、OCSPレスポンダーのホスト名を解決するためにNginxが使用するDNSサーバーを指定します。

SSL/TLSの設定は、セキュリティとパフォーマンスに大きく影響するため、最新のベストプラクティスに従って慎重に行う必要があります。Mozilla SSL Configuration Generatorなどのツールを活用することをお勧めします。

HTTPからHTTPSへのリダイレクト

ほとんどの場合、HTTP (ポート80) へのアクセスは全てHTTPS (ポート443) へリダイレクトすることが推奨されます。これにより、全てのトラフィックが暗号化されます。これは、HTTPでリッスンするserverブロック内で、return 301 https://$host$request_uri;のようなディレクティブを使って実現できます。

上記の例の設定ファイルでは、HTTP用のserverブロックを別に定義し、そこでポート80をリッスンしてポート443へリダイレクトするように設定しています。これは一般的な方法です。

SNI (Server Name Indication)

SNIは、1つのIPアドレスとポート番号(例: 443番ポート)で、複数のドメイン名に対して異なるSSL証明書を扱うための技術です。NginxはSNIをサポートしており、複数のHTTPSサイトを同じサーバー上でホストできます。これは、各serverブロックで異なるserver_nameと対応するssl_certificatessl_certificate_keyを指定するだけで実現できます。ほとんどのモダンブラウザはSNIをサポートしています。

その他の便利な機能と高度な設定

Nginxは上記以外にも様々な機能を提供しています。いくつか主要なものを紹介します。

アクセス制御 (Basic認証、IP制限)

  • Basic認証: ユーザー名とパスワードによる簡単なアクセス制御を実装できます。パスワードはファイルに保存します。
    1. パスワードファイルの作成: htpasswdコマンド(Apacheユーティリティに含まれることが多い)を使用して、ユーザー名と暗号化されたパスワードを含むファイルを作成します。
      bash
      sudo apt install apache2-utils # Ubuntu/Debianの場合
      sudo yum install httpd-tools # CentOS/RHELの場合
      sudo htpasswd -c /etc/nginx/.htpasswd username # 最初のユーザー、ファイル作成
      sudo htpasswd /etc/nginx/.htpasswd anotheruser # 2人目以降のユーザー、ファイル追記
    2. Nginx設定での指定: locationまたはserverブロック内でauth_basicauth_basic_user_fileディレクティブを使用します。
      nginx
      location /admin/ {
      auth_basic "Restricted Area"; # 認証ダイアログに表示されるメッセージ
      auth_basic_user_file /etc/nginx/.htpasswd; # パスワードファイルのパス
      }
  • IP制限: 特定のIPアドレスからのアクセスを許可または拒否できます。
    nginx
    location /private/ {
    allow 192.168.1.0/24; # このサブネットからのアクセスを許可
    allow 10.0.0.1; # この単一IPからのアクセスを許可
    deny all; # それ以外の全てのアクセスを拒否
    }

    許可したいIPアドレスやネットワークをallowで指定し、最後にdeny all;でそれ以外を拒否するのが一般的なパターンです。

リダイレクトと書き換え (return, rewrite)

  • return ディレクティブ: シンプルなリダイレクトや特定のステータスコードを返すのに使います。処理が効率的であるため、可能な限りrewriteよりもreturnを使うことが推奨されます。
    “`nginx
    # 特定の古いURLから新しいURLへリダイレクト
    location = /old-page.html {
    return 301 /new-page/;
    }

    サブドメインなしからwwwありへリダイレクト

    server {
    listen 80;
    listen 443 ssl;
    server_name example.com;

    # HTTPSの場合もここで処理
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    return 301 $scheme://www.example.com$request_uri;
    

    }

    メンテナンス中に503 Service Unavailableを返す

    location / {
    return 503;
    }
    * **`rewrite` ディレクティブ**: 正規表現を使ってURIを書き換えます。複数回処理が実行される可能性があり、複雑な書き換えが必要な場合に使用しますが、パフォーマンスへの影響を考慮する必要があります。nginx
    location / {
    # /download/anything.zip を /files/anything.zip に書き換える
    rewrite ^/download/(.*)$ /files/$1 last;

    # 古いブログ記事のURL形式を新しい形式に書き換える
    # 例: /blog/2023/10/article-title.html -> /articles/article-title/
    rewrite ^/blog/(\d+)/(\d+)/(.*)\.html$ /articles/$3/ permanent; # permanent は 301 リダイレクトを返す
    # last は rewrite 後のURIで再度locationマッチングを行う
    # break は rewrite を停止し、その後の処理を継続する
    # redirect は 302 リダイレクトを返す
    

    }
    ``rewriteディレクティブは強力ですが、複雑になりがちです。簡単なリダイレクトはreturn`を使うべきです。

FastCGI/uWSGI/SCGIプロキシ(アプリケーションサーバー連携)

PHP(PHP-FPM)、Python(Gunicorn/uWSGI)、Ruby(Puma/Unicorn)などの動的コンテンツを生成するアプリケーションは、通常、専用のアプリケーションサーバーやFastCGI/uWSGI/SCGIプロセスとして動作します。Nginxはこれらのプロセスへのリバースプロキシとして機能し、リクエストをアプリケーションに渡して処理させ、その結果を受け取ってクライアントに返します。

  • PHP-FPMとの連携 (FastCGI): PHPアプリケーションをNginxで動かす場合、PHP-FPM(FastCGI Process Manager)と連携するのが一般的です。
    “`nginx
    server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ =404; # ファイルが見つからない場合、404を返す
    }
    
    location ~ \.php$ {
        # リクエストをFastCGIサーバー(PHP-FPM)に転送
        # 通常はUnixドメインソケットを使用 (高性能)
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        # または TCPポート
        # fastcgi_pass 127.0.0.1:9000;
    
        fastcgi_index index.php; # ディレクトリへのリクエスト時にデフォルトで使用するファイル
        include fastcgi_params; # 必要なFastCGIパラメータをインクルード (通常 /etc/nginx/fastcgi_params)
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # SCRIPT_FILENAMEパラメータを設定 (PHP-FPMが必要とする)
    }
    

    }
    ``location ~ .php$.phpで終わるリクエストをマッチさせ、fastcgi_passでPHP-FPMのソケットまたはアドレスに転送します。include fastcgi_params;はNginxに含まれる標準的なFastCGIパラメータ定義ファイルを読み込みます。fastcgi_param SCRIPT_FILENAME …;`は、PHP-FPMが実行するPHPスクリプトファイルの絶対パスを伝えるために必須です。

  • Python (Gunicorn/uWSGI) との連携 (uWSGI): PythonのWebアプリケーション(Django, Flaskなど)をuWSGIで動かす場合、NginxはuWSGIプロトコルで通信できます。
    “`nginx
    upstream django_app {
    # uWSGIプロセスのアドレス
    server unix:/tmp/uwsgi.sock; # Unixドメインソケット
    # または TCPポート
    # server 127.0.0.1:8000;
    }

    server {
    listen 80;
    server_name mydjangosite.com;

    location /static/ {
        # 静的ファイルはNginxが直接配信
        alias /path/to/your/static_files/;
    }
    
    location /media/ {
         # メディアファイルもNginxが直接配信
        alias /path/to/your/media_files/;
    }
    
    location / {
        # 動的なリクエストはuWSGIに転送
        uwsgi_pass django_app;
        include /etc/nginx/uwsgi_params; # uwsgi_paramsファイルをインクルード
        # uwsgi_paramsファイルには、WSGIサーバーに渡すためのヘッダー情報などが含まれています。
        # Nginxパッケージに含まれています。
    }
    

    }
    ``uwsgi_passディレクティブでupstreamブロック名または直接uWSGIプロセスのアドレスを指定し、include uwsgi_params;`で必要なパラメータをインクルードします。

同様に、scgi_passディレクティブを使ってSCGIプロトコルでアプリケーションサーバーと連携することも可能です。

Rate Limiting (アクセス制限)

特定のIPアドレスからのリクエストレートを制限することで、DoS攻撃やブルートフォース攻撃を防ぐことができます。

“`nginx
http {
# …
# limit_req_zone キー ゾーン名:サイズ レート;
# キー: どの単位で制限をかけるか (例: $binary_remote_addr はクライアントIP)
# ゾーン名: 定義するゾーンの名前と、キーを保存するための共有メモリのサイズ
# レート: 1秒あたりのリクエスト数 (r/s) または 1分あたりのリクエスト数 (r/m)
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/s;

server {
    # ...
    location /login/ {
        limit_req zone=mylimit burst=10 nodelay; # ゾーン名を使用し、バーストを許可
        # burst: 指定したリクエストレートを超えた場合に、キューに溜め込めるリクエスト数
        # nodelay: キューに溜め込まずに、バースト分も即座に処理を試みる (レートを超えたら拒否されやすい)
        # omit_header: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset ヘッダーを返さない (Nginx Plus)
        # ... その他のlocation設定 ...
    }
}

}
``limit_req_zoneディレクティブで、どの基準で(ここではクライアントIP)、どれくらいのレート(ここでは1秒あたり5リクエスト)で制限をかけるかを定義します。これはhttpコンテキストで一度定義します。limit_reqディレクティブをserverまたはlocationコンテキストで使用して、定義したゾーンを適用します。burst`パラメータは、一時的にレートを超えてリクエストが来た場合に、それらをどれだけキューに入れて待機させるか、または即時処理を試みるかを制御します。

トラブルシューティングと監視

Nginxの設定を変更したり、問題が発生したりした場合、適切にトラブルシューティングと監視を行うことが重要です。

設定ファイルのテスト (nginx -t)

設定ファイルを変更した後にNginxをリロード/再起動する前に、必ず構文エラーがないかテストしましょう。

bash
sudo nginx -t

これにより、設定ファイルのパスが正しければ、設定ファイルの構文チェックが行われます。test is successfulと表示されれば問題ありません。エラーが出た場合は、エラーメッセージをよく読み、指示された行番号などを参考に修正します。

エラーログの確認

Nginxで何か問題が発生した場合、まず確認すべきなのはエラーログです。エラーログの場所は通常 /var/log/nginx/error.log です(設定で変更可能)。

bash
sudo tail -f /var/log/nginx/error.log

このコマンドでリアルタイムにログを追跡できます。権限エラー、ファイルが見つからない、バックエンドへの接続失敗など、様々な情報が記録されます。

アクセスログの確認

アクセスログには、クライアントからの全てのリクエストが記録されます。どのURLにアクセスがあったか、ステータスコード(成功したか、エラーか)、レスポンスサイズ、ユーザーエージェントなどの情報が含まれます。アクセスログの場所は通常 /var/log/nginx/access.log です(設定で変更可能)。

bash
sudo tail -f /var/log/nginx/access.log

特定のアクセスがどのように処理されたか確認したり、不正アクセスの兆候を調べたりするのに役立ちます。

システムログの確認 (journalctl, syslog)

Nginxサービス自体の起動や停止、再起動に関するエラーなど、システムレベルのログはsystemdのジャーナル(journalctl)やsyslogに記録されている場合があります。

bash
sudo journalctl -u nginx.service

このコマンドで、nginxサービスのsystemdジャーナルを確認できます。

プロセスの確認 (ps, top)

Nginxプロセスが正しく実行されているか、CPUやメモリを過剰に消費していないかなどを確認します。

bash
ps aux | grep nginx
top

ps aux | grep nginxでNginxのマスタープロセスとワーカープロセスが表示されるはずです。tophtopコマンドでシステムの全体的なリソース使用状況を確認できます。

接続状態の確認 (netstat, ss)

サーバーが特定のポート(80番、443番など)をリッスンしているか、現在の接続状況はどうなっているかなどを確認します。

bash
sudo netstat -tulnp | grep nginx # または grep 80 または grep 443
sudo ss -tulnp | grep nginx

これらのコマンドは、Nginxプロセスがどのポートでリッスンしているかを表示します。

Nginxの状態監視 (stub_status モジュール)

オープンソース版のNginxには、基本的なサーバー状態(アクティブな接続数、受け付けた接続数、処理されたリクエスト数など)を公開するstub_statusモジュールが標準で含まれています。これを有効にすると、監視ツールと連携しやすくなります。

  1. 設定ファイルでstub_statusモジュールを有効にするLocationブロックを追加します。
    “`nginx
    server {
    listen 80;
    server_name localhost; # このURLは外部に公開しないように注意

    location /nginx_status {
        stub_status on; # ステータス情報を有効化
        allow 127.0.0.1; # ローカルホストからのアクセスのみ許可
        deny all;        # それ以外からのアクセスを拒否
    }
    

    }
    2. 設定をリロードします。bash
    sudo systemctl reload nginx
    3. `curl`コマンドなどでアクセスして確認します。bash
    curl http://localhost/nginx_status
    以下のような情報が表示されます。
    Active connections: 291
    server accepts handled requests
    16630948 16630948 31070465
    Reading: 8 Writing: 18 Waiting: 265
    ``
    *
    Active connections: 現在アクティブなクライアント接続数。
    *
    server accepts handled requests: 起動以来受け付けた接続数、ハンドリングした接続数、処理したリクエスト数。通常 accepts = handled です。
    *
    Reading: ヘッダーを読み込んでいる状態の接続数。
    *
    Writing: レスポンスをクライアントに返送している状態の接続数。
    *
    Waiting`: キープアライブ接続でアイドル状態の接続数。

これは基本的な監視に役立ちます。より詳細なメトリクスが必要な場合は、Prometheus + Node Exporter/Nginx ExporterやDatadogなどの外部監視ツールとの連携を検討します。Nginx Plusにはより高度な監視ダッシュボード機能が搭載されています。

セキュリティに関する考慮事項

Webサーバーはインターネットに直接面しているため、セキュリティは非常に重要です。Nginxを安全に運用するために、以下の点を考慮しましょう。

  • 最小権限の原則: Nginxのワーカープロセスは、必要最低限の権限を持つユーザー(通常 www-datanginx)で実行されるように設定します。これは nginx.confuser ディレクティブで設定します。root権限でWebサーバープロセスを実行しないようにしましょう。
  • 不要なモジュールの無効化: ソースコードからコンパイルする場合、必要ないモジュールは組み込まないことで、攻撃対象となる可能性のある機能を減らせます。パッケージでインストールした場合でも、不要な機能を提供しているLocationブロックなどは削除または無効化しましょう。
  • サーバーバージョンの非表示: デフォルトでは、NginxはレスポンスヘッダーにNginxのバージョン情報を付加します(例: Server: nginx/1.18.0)。これは攻撃者にとって有用な情報となりうるため、非表示にすることが推奨されます。httpコンテキストでserver_tokens off;を設定します。
    nginx
    http {
    # ...
    server_tokens off;
    # ...
    }
  • 適切なアクセス制御: 公開すべきでないディレクトリやファイル(例えば、設定ファイル、.gitディレクトリ、バックアップファイルなど)には、適切なIP制限や認証を設定し、外部からアクセスできないようにします。
    nginx
    location ~ /\.ht { # .htで始まるファイル(.htaccessなど)
    deny all;
    }
    location ~ /\.git { # .gitディレクトリ
    deny all;
    }
  • SSL/TLSの適切な設定: 前述のSSL/TLS設定で解説したように、安全なプロトコルバージョン、強力な暗号スイートのみを許可し、HSTSなどを活用してHTTPSを適切に構成することが不可欠です。
  • 定期的なアップデート: Nginx本体およびシステムライブラリ(OpenSSLなど)の脆弱性は日々発見される可能性があります。利用しているNginxのバージョンを常に最新の状態に保つことで、既知の脆弱性から保護できます。システムパッケージマネージャーを使って定期的にアップデートを実行しましょう。
  • ログの監視: 不審なアクセスパターンやエラーログを定期的に確認し、異常がないか監視します。

まとめ:Nginxを使いこなす次のステップへ

この記事では、高速WebサーバーNginxの基本から、インストール、設定、そして静的ファイル配信、リバースプロキシ、ロードバランシング、SSL/TLS設定といった主要な使い方までを詳細に解説しました。

Nginxの最大の魅力は、その高性能なイベント駆動型アーキテクチャにあります。これにより、少ないリソースで多数の同時接続を効率的に処理でき、特に現代のWebサービスに不可欠な静的ファイル配信リバースプロキシロードバランシングといった役割で真価を発揮します。シンプルな設定ファイル構造も、その導入と管理を容易にしています。

この記事を通じて、あなたはNginxの基本的な動作原理、設定ファイルの構造、そして最も一般的な使い方について理解を深めることができたはずです。これらの知識は、Webサイトやアプリケーションを公開する上で非常に強力な基盤となります。

しかし、Nginxの世界はさらに奥深く、ここで紹介した内容は氷山の一角にすぎません。Nginxをさらに使いこなすために、次に学ぶべきこととして以下を挙げることができます。

  • モジュールの活用: Nginxは様々な機能をモジュールとして提供しています。標準モジュール以外にも、サードパーティモジュールを組み込むことで機能を拡張できます(例: ModSecurityによるWAF機能、Luaスクリプトによる高度なリクエスト処理など)。
  • Nginx Plus: 商用版のNginx Plusは、アクティブヘルスチェック、高度な監視ダッシュボード、JWT認証、サービスディスカバリ連携など、エンタープライズ環境向けのより多くの機能を提供しています。
  • コンテナ環境での利用: Dockerなどのコンテナ環境でNginxを利用する場合の設定やベストプラクティス。
  • マイクロサービスアーキテクチャ: APIゲートウェイとしてのNginxの役割。
  • パフォーマンスチューニング: OSレベルのネットワーク設定やNginxの設定をさらに細かく調整して、最高のパフォーマンスを引き出す方法。
  • 自動化: Ansible, Chef, Puppetなどの構成管理ツールを使ったNginxのデプロイと管理の自動化。

Nginxは、小規模なサイトから大規模な分散システムまで、あらゆる規模のWebインフラを支えることができる汎用性と堅牢性を備えています。この記事が、あなたがNginxを本格的に学び、その高速性と柔軟性を最大限に活用するための第一歩となることを願っています。

実際にサーバーを立ち上げ、設定ファイルを編集し、リロードしながら試行錯誤することが、Nginxを習得する最も良い方法です。公式ドキュメントやコミュニティのリソースも豊富に存在するので、ぜひ活用してください。

さあ、あなたのWebインフラをNginxで加速させましょう!


コメントする

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

上部へスクロール