最近、WordPressサイト(このサイトです)の高速化の一環として、WebサーバのApacheからNginxへの変更と、HTTP/2の対応を行いました。
その環境でのLet’s Encryptでの証明書更新や、新規取得にちょっと詰まったので、やり方をまとめておきます。
HTTP/2とは?
まず、高速化の手法だ!ということで、何となくHTTP/2化したのですが、それが何なのか分かっていなかった・・・というのが、今回、困った原因でした。まず、HTTP/2とは何?という話から始めようと思います。
HTTP/2の説明は、さくらのナレッジのこちらの記事が参考になります。
この記事から分かるのは、HTTP/2は、HTTP/1.1までとは異なり、クライアント〜サーバ間がバイナリでのやり取りをすること、ストリームという概念が導入され、サーバは1つのリクエストに対して、そのレスポンスを返す前に別のリクエストを処理できるという2点ということです。
後者については、今までは複数のサーバプロセスを立ち上げて並列処理したいたところ、1つのプロセス内での並列が可能になったわけで、それだけサーバの処理性能が上がり(待ち時間の無駄がなくなり)、高速処理につながるというわけですね。
また、最近は肥大化の傾向にあるHTTPヘッダのデータがHTTP/2では圧縮して送信されるため、高速化するということもあるようです。
悩んでいたこと
Nginxに新たなドメイン(サブドメイン)での設定を追加し、Let’s Encryptでの新規証明書発行を行おうとしていたのですが、それが上手く行かない。
それなら・・・、ということで、Webブラウザでhttp://aaa.com
(新規ドメイン)へのアクセスをしてみると、なんとバイナリファイルがダウンロードされるという謎現象でした。
この謎現象は、訳も分からずにNginxでの設定をこのような設定にしていたから。
server {
listen 80 http2;
server_name aaa.com;
(以下省略)
}
80番ポートでaaa.comを待ち受けていて、それがhttp2になっているのでバイナリでの処理を行おうとする。だから、ブラウザ(Chrome)はバイナリファイルのダウンロードになる。
でも、既にSSL証明書を取得して、httpへのアクセスは問答無用にhttpsにリダイレクトしていたサイトはなぜ大丈夫だったか?というと、https側のserver
設定でhttp2を有効にしていてバイナリのやり取りになっても、ブラウザがそれに対応しているから。
つまり、HTTP/2の仕様としてバイナリでのやり取りをhttpでもhttpsでも行うというのは問題ないのですが、Chromeをはじめとするブラウザの対応としてはhttpsでのみHTTP/2にきちんと対応していて、httpでのHTTP/2対応はやる気が無いということらしいのです。
どう設定すれば良いのか?
ということで、httpでの通信はLet’s Encryptの証明書取得・更新時の通信と、httpsへのリダイレクトだけにして、それは従来どおりHTTP/1.1での通信にする。そして、実際に高速化を行いたいhttpsでの通信はHTTP/2にするというのが、良さそうです。
Nginxの設定ファイルはこのようになります。
server {
listen 80;
server_name aaa.com;
location ^~ /.well-known/acme-challenge
default_type "text/plain";
root /home/dggc43576856891/html;
}
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name aaa.com;
(以下省略)
}
/.well-known/acme-challenge
のくだりはLet’s Encryptでのドメイン認証時の通信に必要な設定です。ドメイン認証時は/home/dggc43576856891/html
にファイルを自動作成させ、そのファイルに対して証明書を取得したいドメインでLet’s Encryptからアクセスできればドメイン認証完了になります。
SSL証明書の取得
この環境でSSL証明書を取得する場合、使用するコマンドは下記のとおりです。
letsencrypt certonly --webroot
対話型での操作になり、証明書を取得したドメインと、webrootパス(上記のNginxの設定では、/home/dggc43576856891/html
)の2つを入力すればOKです。
証明書の取得後、Apacheでは自動的に諸々の設定が行われますが、Nginxでは自分で下記のような設定が必要です。(これはSSLを使用するための最低限の設定です。)
server {
listen 443 ssl http2;
ssl on;
server_name aaa.com;
ssl_certificate /etc/letsencrypt/live/aaa.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/aaa.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/aaa.com/fullchain.pem;
(以下省略)
}
Apacheが有効だったときに取得した証明書の更新
Nginxが有効(80番ポートを使っている)な場合に上記のように証明書を取得した場合、あとはほったらかしていても自動的に証明書は更新されます(Ubuntu 18.04 LTS)。
ただ、Apacheを使っていたときに取得した証明書の更新を、Nginxを使うようになった後に行う場合は、ドメインごとに下記の設定ファイル(/etc/letsencrypt/renewal/{domain}.conf
)の変更が必要になります。
変更箇所のみを示します。
[renewalparams]
authenticator = webroot
[[webroot_map]]
aaa.com = /home/dggc43576856891/html
authenticator
としてapache
が指定されているのをwebroot
に変更することと、[[webroot_map]]
のドメインに対応する値としてwebrootのパス(ここでは/home/dggc43576856891/html
を指定することの2点です。