DNSのサービスで *.example.com
のようにワイルドカードのサブドメインを設定し、nginxでワイルドカード部分の文字列を見てルーティング先を切り換える、といった構成を行ったので、メモを残します。
ドメイン名の設定
ムームードメインのムームーDNSを利用していたので、CNAMEの設定でワイルドカードは *
の文字を使用できた。
*.test
としたので、 *.test.example.com
のようなワイルドカードの設定となり、 hoge.test.example.com
などにマッチする。
nginxのVirtualHost設定
nginxでも server_name
ディレクティブで、ワイルドカードの部分は *
の文字を使用できる。
まずはすべてのホスト名にマッチする設定をする。
server { listen 80; root /home/vagrant/www; index index.html; server_name *.test.example.com; location / { try_files $uri $uri/ =404; } }
example.com
の部分は自分の利用したドメイン名に置き換える。
/home/vagrant/www
には適当な動作確認用の index.html
ファイルを作成しておく。
この設定で http://hoge.test.example.com/
にブラウザでアクセスすると、 index.html
の内容が表示される。
正規表現でサブドメインのホスト名部分を抜き出す
ドキュメントの通り、 server_name
ディレクティブでは正規表現を使用できるので、 (?<server_host>.+)
のようなパターンで一致した文字列を変数名で読めるようしてみる。
また、 if
ディレクティブで抜き出したホスト名部分の文字列を使って分岐処理をしてみます。
server { listen 80; root /home/vagrant/www; index index.html; server_name ~^(?<server_host>.+).test.example.com$; location / { if ($server_host != "www") { add_header Content-Type text/plain; return 200 $server_host; } try_files $uri $uri/ =404; } }
この設定では、 www.test.example.com
以外の場合は、ホスト名をレスポンスとして返しています。 www.test.example.com
の場合は、 try_files
ディレクティブにより、 index.html
の内容が返されるようになります。
たとえば、 http://hoge.test.example.com/
にブラウザでアクセスした場合は、 hoge
と表示されます。
ここまでできると、location以下でルーティングは自由にできるので、たとえばホスト名部分によって proxy_pass の先を変更したりもできます。
サブドメインごとに server ディレクティブを記述してルーティングすることもできますが、運用上この形のほうが嬉しい場合があったので、この形で今回はやってみました。
Let's Encryptでワイルドカード証明書を取得して設定する
ここまでの設定だとHTTPですが、Let's Encrypt(certbot)を使ってワイルドカード証明書を設定すると、HTTPSにすることもできます。
certbotコマンドで以下のようにワイルドカード証明書を取得します。
certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --manual -d *.test.example.com --preferred-challenges dns
この場合、ドメインの所有確認のためにTXTレコードの追加が必要になります。画面に表示された指示にしたがって、TXTレコードをDNSに設定しておきます。
証明書を取得できたらnginxに設定します。HTTPの場合は強制でHTTPSにリダイレクトさせるような場合は以下のようになります。
server { listen 80; server_name *.test.example.com; return 301 https://$host$request_uri; } server { listen 443; root /home/vagrant/www; index index.html; server_name ~^(?<server_host>.+).test.example.com$; ssl_certificate /etc/letsencrypt/live/test.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/test.example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { if ($server_host != "www") { add_header Content-Type text/plain; return 200 $server_host; } try_files $uri $uri/ =404; } }