Nginx バーチャルホスト:1台のサーバーで複数のウェブサイトをホストする

Nginx のバーチャルホスト(サーバーブロック)を活用して、1台のサーバーで複数のウェブサイトやサブドメインを効率的にホストする方法を解説します。このガイドでは、ディレクトリ設定、設定ファイルの作成、サーバーブロックの有効化、Nginx のテストまでをステップバイステップで説明。サブドメイン、デフォルトサーバーブロック、HTTPS 統合、専用ログのベストプラクティスも学べます。実践的な例とトラブルシューティングのヒントで、マルチサイト Nginx ホスティングをマスターし、リソース使用を最適化してウェブサーバー管理を効率化しましょう。

Nginx バーチャルホスト:1台のサーバーで複数のウェブサイトをホストする

1台のサーバーで複数の小規模サイトを運用するのは、Nginx では一般的な作業です。会社のサイト、ドキュメントサイト、ステージングアプリ、カスタマーポータルなどがすべて同じマシンに配置されることもあります。Nginx はこれらを server ブロックで分離します。Apache ユーザーは同じ概念をバーチャルホストと呼ぶことが多いため、チュートリアルやホスティングパネルでは両方の用語が使われます。

重要なのはシンプルです。Nginx はポート、IP アドレス、Host ヘッダーを確認し、一致する server ブロックを選択します。間違ったサイトが読み込まれる場合、その原因はたいてい謎ではありません。多くの場合、DNS レコードの欠落、server_name のタイポ、デフォルトサーバーがリクエストをキャッチしている、または同じ名前を主張する2つのファイルが原因です。

Nginx サーバーブロック(バーチャルホスト)の理解

Nginx の サーバーブロック は、Nginx 設定ファイル(nginx.conf またはインクルードファイル)内で定義される設定ディレクティブです。各 server ブロックは特定のバーチャルホストの設定を定義し、特定のドメインまたはドメインセットへのリクエストに対して Nginx がどのように応答するかを指示します。Nginx は listen ディレクティブを使用してリッスンする IP アドレスとポートを指定し、server_name ディレクティブを使用してこのサーバーブロックが応答するドメイン名またはホスト名を識別します。

リクエストが来ると、Nginx は HTTP リクエストの Host ヘッダーを調べ、設定されたサーバーブロックの server_name ディレクティブと比較します。そして、一致するサーバーブロックで定義されたコンテンツを提供します。server_name が一致しない場合、Nginx は通常、デフォルトサーバーブロック(最初の server ブロック、または明示的に default_server とマークされたもの)にフォールバックします。

前提条件

始める前に、以下が整っていることを確認してください。

  1. Nginx がインストールされていること: Nginx がサーバーにインストールされ、実行されている必要があります。インストールされていない場合は、システムのパッケージマネージャーを使ってインストールできます(例:Ubuntu/Debian では sudo apt update && sudo apt install nginx、CentOS/RHEL では sudo yum install nginx)。
  2. ドメイン名: ホストしたい少なくとも2つのドメイン名(例:example1.comexample2.com)またはサブドメイン(例:blog.example.comapp.example.com)が必要です。これらのドメインの DNS A/AAAA レコードはサーバーのパブリック IP アドレスを指している必要があります。
  3. 基本的なディレクトリ構造: ウェブサイトファイルを配置する場所の計画。一般的な方法は /var/www/yourdomain.com/html です。
  4. sudo 権限: Nginx 設定ファイルを変更するには sudo アクセスが必要です。

ステップバイステップのセットアップガイド

2つのバーチャルホスト example1.comexample2.com をセットアップしましょう。

ステップ 1: ウェブサイト用のディレクトリ構造を作成する

まず、各ウェブサイトのルートディレクトリを作成します。ここに HTML、CSS、JavaScript、その他の静的ファイルが保存されます。一般的な場所は /var/www/ です。

sudo mkdir -p /var/www/example1.com/html
sudo mkdir -p /var/www/example2.com/html

# 所有権をユーザーに設定($USER をユーザー名に置き換え)して編集を許可
sudo chown -R $USER:$USER /var/www/example1.com/html
sudo chown -R $USER:$USER /var/www/example2.com/html

# ウェブサーバーに読み取り権限を設定
sudo chmod -R 755 /var/www

次に、各ディレクトリにシンプルな index.html ファイルを作成してセットアップをテストします。

/var/www/example1.com/html/index.html の場合:

<!-- /var/www/example1.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Welcome to Example1.com!</title>
</head>
<body>
    <h1>Success! This is Example1.com.</h1>
    <p>This virtual host is working correctly.</p>
</body>
</html>

/var/www/example2.com/html/index.html の場合:

<!-- /var/www/example2.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Welcome to Example2.com!</title>
</head>
<body>
    <h1>Success! This is Example2.com.</h1>
    <p>This virtual host is also working!</p>
</body>
</html>

ステップ 2: Nginx サーバーブロック設定ファイルを作成する

Nginx は通常、/etc/nginx/sites-enabled/ ディレクトリ内のファイルからサーバーブロック設定を読み込みます。これらのファイルは通常、/etc/nginx/sites-available/ に保存された設定へのシンボリックリンクです。この分離により、まだアクティブでない設定を保存したり、サイトを簡単に有効化/無効化したりできます。

example1.com 用の新しい設定ファイルを作成します:

sudo nano /etc/nginx/sites-available/example1.com.conf

以下の内容を追加します:

# /etc/nginx/sites-available/example1.com.conf
server {
    listen 80;
    listen [::]:80;

    root /var/www/example1.com/html;
    index index.html index.htm index.nginx-debian.html;

    server_name example1.com www.example1.com;

    location / {
        try_files $uri $uri/ =404;
    }

    access_log /var/log/nginx/example1.com_access.log;
    error_log /var/log/nginx/example1.com_error.log;
}

ディレクティブの説明:

  • listen 80;: Nginx はポート 80(標準 HTTP)をリッスンします。listen [::]:80; は IPv6 用です。
  • root /var/www/example1.com/html;: このサーバーブロックのドキュメントルートを指定します。Nginx はこのディレクトリ内のファイルを探します。
  • index index.html ...;: ディレクトリがリクエストされたとき(例:誰かが example1.com/ にアクセスしたとき)に Nginx が提供するデフォルトファイルを定義します。
  • server_name example1.com www.example1.com;: これは重要です。example1.com または www.example1.com へのリクエストに対して、このサーバーブロックの設定を使用して応答するよう Nginx に指示します。
  • location / { ... }: 特定の URI へのリクエストを処理する方法を定義するブロック。try_files はファイルを直接提供しようとし($uri)、次にディレクトリ($uri/)、最後に 404 Not Found エラーを返します。
  • access_logerror_log: この特定のサイト用の個別のログファイルを指定します。これはデバッグや分析を容易にする良い習慣です。

次に、example2.com 用の同様の設定ファイルを作成します:

sudo nano /etc/nginx/sites-available/example2.com.conf

以下の内容を追加します:

# /etc/nginx/sites-available/example2.com.conf
server {
    listen 80;
    listen [::]:80;

    root /var/www/example2.com/html;
    index index.html index.htm index.nginx-debian.html;

    server_name example2.com www.example2.com;

    location / {
        try_files $uri $uri/ =404;
    }

    access_log /var/log/nginx/example2.com_access.log;
    error_log /var/log/nginx/example2.com_error.log;
}

ステップ 3: サーバーブロックを有効にする

これらの設定を有効にするには、sites-available ディレクトリから sites-enabled ディレクトリへのシンボリックリンクを作成します。これにより、Nginx は起動時にこれらのファイルをインクルードします。

sudo ln -s /etc/nginx/sites-available/example1.com.conf /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/example2.com.conf /etc/nginx/sites-enabled/

ステップ 4: Nginx 設定をテストする

リロードする前に、Nginx 設定に構文エラーがないかテストすることが重要です。これにより、タイポが原因で Nginx が再起動に失敗するのを防ぎます。

sudo nginx -t

成功を示す以下のような出力が表示されるはずです:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

エラーが表示された場合は、それぞれの設定ファイルで修正し、sudo nginx -t を再実行して合格するまで続けてください。

ステップ 5: Nginx を再起動する

Nginx を再起動またはリロードして新しい設定を適用します。reload は通常、アクティブな接続を切断せずに新しい設定を読み込めるため推奨されます。

sudo systemctl reload nginx
# または、リロードが機能しない場合や新規インストールの場合:
sudo systemctl restart nginx

ステップ 6: DNS レコードを更新する

example1.comwww.example1.comexample2.comwww.example2.com の DNS A レコードがすべて Nginx サーバーの IP アドレスを指していることを確認してください。正しい DNS エントリがなければ、ブラウザはウェブサイトの場所を見つけられません。

DNS の伝播が完了すると(数分から数時間かかる場合があります)、ウェブブラウザで http://example1.comhttp://example2.com にアクセスし、それぞれの index.html ページが表示されるはずです。

高度なシナリオとベストプラクティス

サブドメインのホスティング

サブドメイン(例:blog.example.comshop.example.com)のホスティングは、別のドメインをホスティングするのとまったく同じように機能します。サブドメインを server_name として新しいサーバーブロックを定義するだけです。

blog.example.com の例:

# /etc/nginx/sites-available/blog.example.com.conf
server {
    listen 80;
    listen [::]:80;

    root /var/www/blog.example.com/html;
    index index.html;

    server_name blog.example.com;

    location / {
        try_files $uri $uri/ =404;
    }
}

ディレクトリ(/var/www/blog.example.com/html)を作成し、index.html を作成し、シンボリックリンクを作成し、Nginx をリロードすることを忘れないでください。

デフォルトサーバーブロック

サーバー上の他の server_name ディレクティブと一致しないドメイン名へのリクエストをキャッチする デフォルトサーバーブロック を用意するのは良い習慣です。これにより、未知のリクエストが Nginx が見つけた「最初の」バーチャルホストによって処理されるのを防ぎ、または汎用の「サイトが見つかりません」ページを提供できます。

通常、nginx.conf または sites-enabled の最初の server ブロックが暗黙的にデフォルトになります。default_server を使用して明示的に設定できます:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;
    # アンダースコア `_` は存在しないドメイン名で、実際のリクエストと一致することはありません。
    # localhost を使用することもできます。

    root /var/www/default_site/html;
    index index.html;

    location / {
        return 444; # 未知のホストには Nginx 固有の 444 エラー(応答なし)を返す
        # または、汎用のランディングページを提供:
        # try_files $uri $uri/ =404;
    }
}

警告: default_server ブロックを定義する場合、特定の listen ポートで default_server フラグを持つ server ブロックが1つだけであることを確認してください。そうしないと、Nginx が警告をログに記録します。

HTTPS(SSL/TLS)によるバーチャルホストの保護

本番ウェブサイトでは、HTTPS を有効にすることが不可欠です。これには、SSL/TLS 証明書の取得(例:Certbot を使用した Let's Encrypt)と、証明書を使用してポート 443 をリッスンするよう Nginx を設定することが含まれます。

典型的な HTTPS サーバーブロックは次のようになります(証明書取得後):

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example1.com www.example1.com;

    root /var/www/example1.com/html;
    index index.html;

    ssl_certificate /etc/letsencrypt/live/example1.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example1.com/privkey.pem;

    # その他の SSL 設定(暗号スイート、プロトコルなど)を含める
    include /etc/nginx/snippets/ssl-params.conf;

    location / {
        try_files $uri $uri/ =404;
    }
}

# オプション:このドメインの HTTP から HTTPS へのリダイレクト
server {
    listen 80;
    listen [::]:80;
    server_name example1.com www.example1.com;
    return 301 https://$host$request_uri;
}

すべてのトラフィックを HTTPS 対応のものにリダイレクトすることだけを目的とした、別の HTTP サーバーブロックを持つことが一般的です。

Certbot を使用する場合、これらのブロックを作成または編集してくれることがあります。それは便利ですが、結果のファイルを読むべきです。自動化された証明書ツールは、自分では選ばなかった場所にリダイレクトロジックを追加することがあり、重複したリダイレクトはトラブルシューティングを難しくする可能性があります。

各サイトのログ

例で示したように、各バーチャルホストに専用の access_logerror_log ファイルを割り当てることはベストプラクティスです。これにより、結合されたログをふるいにかけることなく、個々のウェブサイトの問題をデバッグし、トラフィックを分析することがはるかに容易になります。

設定ファイルの構造

大規模なデプロイメントでは、Nginx 設定ファイルを次のように整理することを検討してください:

  • nginx.conf: メイン設定、conf.d/*.confsites-enabled/* をインクルード。
  • conf.d/: サーバー全体の一般的な設定(例:Gzip、キャッシュ)。
  • snippets/: 再利用可能な Nginx 設定スニペット(例:SSL パラメータ、共通の location ブロック)。
  • sites-available/: 各ウェブサイトの個別の server ブロック。
  • sites-enabled/: sites-available/ 内のアクティブな設定へのシンボリックリンク。

一般的な問題のトラブルシューティング

  • 403 Forbidden エラー: これは通常、Nginx がウェブサイトのファイルやディレクトリへの読み取りアクセス権を持っていないことを意味します。ファイルとディレクトリの権限を再確認してください(例:sudo chmod -R 755 /var/www/yourdomain.com/html、Nginx ユーザー(通常は www-data または nginx)が読み取れることを確認)。
  • 404 Not Found エラー: サーバーブロックの root ディレクティブが正しいディレクトリを指していること、およびその場所に index.html ファイルが存在することを確認してください。また、try_files が正しく設定されていることを確認してください。
  • 間違ったサイトが読み込まれる: これは多くの場合、server_name ディレクティブの問題を示しています。server_name がアクセスしようとしているドメイン名と完全に一致していることを確認してください(www. やサブドメインを含む)。また、DNS レコードを確認してください。
  • Nginx が起動/リロードに失敗する: Nginx をリロードまたは再起動する前に、必ず sudo nginx -t を使用して設定をテストしてください。エラーメッセージは、構文エラーが発生した行とファイルを特定します。
  • DNS の問題: IP アドレスではサイトにアクセスできるが、ドメイン名ではアクセスできない場合、それはほぼ間違いなく DNS の問題です。dig または nslookup を使用して、ドメインの A レコードが正しいサーバー IP を指していることを確認してください。

DNS が準備できる前のテスト

Nginx 側をテストするために、パブリック DNS を待つ必要はありません。カスタム Host ヘッダーでリクエストを送信できます:

curl -H "Host: example1.com" http://203.0.113.10/
curl -H "Host: example2.com" http://203.0.113.10/

203.0.113.10 をサーバー IP に置き換えてください。各コマンドが正しいテストページを返す場合、サーバーブロックのマッチングは機能しています。両方のコマンドが同じページを返す場合、両方のファイルが有効になっているか、server_name が正しいか、デフォルトブロックがリクエストをキャッチしていないかを確認してください。

HTTPS の場合、TLS は HTTP Host ヘッダーが処理される前に SNI を使用するため、テストは少し異なります:

curl --resolve example1.com:443:203.0.113.10 https://example1.com/

このコマンドは、TLS と HTTP に example1.com を使用しながら、サーバー IP に接続するよう curl に指示します。これは、DNS を変更する前に新しい HTTPS バーチャルホストをテストする最も迅速な方法の1つです。

保守可能なマルチサイトパターン

いくつかの静的サイトの場合、上記の例で十分です。複数のアプリケーションをホストする場合は、繰り返しを減らし、真に共有される部分のみを集中化します。たとえば、共通のセキュリティヘッダー、圧縮、SSL パラメータをスニペットに配置しますが、各サイトの rootserver_name、upstream、ログは独自のファイルに表示されたままにします。

すべての行を読まずに、あるドメインから別のドメインに大きな本番ブロックをコピーしないでください。そうすることで、server_name のミス、間違った証明書パス、共有ログファイルが忍び込むのです。実用的なレビューチェックリストは短いです:

  • server_name にユーザーが入力するすべてのホスト名が含まれていますか?
  • root または proxy_pass は、前のサイトではなく、このサイトを指していますか?
  • アクセスログとエラーログは、このサイトを単独でデバッグするのに十分に分離されていますか?
  • リロード前に nginx -t は合格しますか?
  • curl -H "Host: ..." または curl --resolve は期待されるサイトを返しますか?

最後に

Nginx バーチャルホストは、各サイトに明確なサーバーブロック、正しい server_name、予測可能なデフォルトフォールバックがある場合に信頼性があります。ファイルは退屈に保ってください。リロードする前にすべての変更をテストしてください。サイトが重要な場合は専用ログを使用してください。ほとんどのマルチサイト Nginx の問題は、DNS、TLS/SNI、またはサーバーブロックのマッチングのどの部分が失敗したかを証明できれば、簡単に解決できるようになります。