1つの nginx サーバで複数のサブドメインのアクセスを振り分ける

1台の VM があって、1つの nginx サーバが立ち上がっているところで、

の両方のサブドメインへのアクセスを、それぞれのバックエンドサーバに振り分ける。コレを Virtual Host 設定と呼ぶらしい。


バックエンドサーバは、それぞれ nginx があるサーバ内で

で起動してあることとする。サーバ自体は Express.js 製でも Flask 製でも、なんでも良い。


初めに、ドメインに対して DNS 設定をしておく。各サブドメインが同じ VM の Public IP を向くように A レコードを追加しておく。

example-1.example.com    A    140.100.0.0
example-2.example.com    A    140.100.0.0

こんなノリで。


まずは設定ファイルのエントリポイントとなる nginx.conf。コイツは特に変更点なく、conf.d/*.confInclude するようになっていれば良い。

user  www-data;
worker_processes  1;

error_log  /var/log/nginx/error.log  warn;
pid        /var/run/nginx.pid;

events {
  worker_connections 1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;
  
  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;
  
  sendfile  on;
  keepalive_timeout  65;
  
  # 各種設定を読み込む
  include  /etc/nginx/conf.d/*.conf;
}

続いて、conf.d/ 配下に2つの .conf ファイルを作る。サブドメインごとの設定ファイルだ。

server {
  listen       80;
  # Let's Encrypt 証明書発行後に有効にする
  #listen       443 ssl;
  server_name  example-1.example.com;
  # Let's Encrypt 証明書発行後に有効にする
  #ssl_certificate       /etc/letsencrypt/live/example-1.example.com/fullchain.pem;
  #ssl_certificate_key   /etc/letsencrypt/live/example-1.example.com/privkey.pem;
  
  location / {
    proxy_pass http://127.0.0.1:3000;
  }
}

server_name にサブドメインを指定しているところがミソ。その他は proxy_pass でバックエンドサーバに通信を流している。

後ほど Let's Encrypt の certbot で SSL 証明書を発行するので、その後に使うための listen 443 ssl;ssl_certificate 部分をコメントアウトしてある。

最後に、2つ目のサブドメインの .conf。書いてある内容は1つ目のサブドメインの .conf とほぼ同じ。

server {
  listen       80;
  # Let's Encrypt 証明書発行後に有効にする
  #listen       443 ssl;
  server_name  example-2.example.com;
  # Let's Encrypt 証明書発行後に有効にする
  #ssl_certificate       /etc/letsencrypt/live/example-2.example.com/fullchain.pem;
  #ssl_certificate_key   /etc/letsencrypt/live/example-2.example.com/privkey.pem;
  
  location / {
    proxy_pass http://127.0.0.1:5000;
  }
}

当然ながら、server_name で指定しているサブドメインが異なるのと、proxy_pass で指定しているバックエンドサーバのポート番号が違う。


この時点で、

$ nginx -t
$ systemctl restart nginx

で構文チェックを行い、nginx を再起動してやれば、まずは HTTP (80番ポート) で

にそれぞれアクセスが振り分けられていることが確認できるはずだ。


あとは Let's Encrypt でそれぞれのサブドメインの SSL 証明書を作ってあげる。以前紹介した certbot-auto を使っているが、方法はどれでも良い。

$ ./certbot-auto certonly --webroot -w /var/www/html -d example-1.example.com -m example@example.com --agree-tos -n
$ ./certbot-auto certonly --webroot -w /var/www/html -d example-2.example.com -m example@example.com --agree-tos -n

それぞれ fullchain.pemprivkey.pem が出力されているはずなので、先程の .conf ファイル内のコメントアウト部分を有効にして、HTTPS にも対応させて nginx を再起動する。

コレで HTTPS にもアクセスができるようになり、

それぞれの URL が異なるバックエンドサーバの内容を返せるようになったはずだ。