なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ 書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

nginx + ngx_mruby での、 Let's Encrypt の SSL 証明書の動的読み込み

この記事を見て、やってみようと思ったのでメモしとこうかなと。
タイトルに Let's Encrypt のと含めてますが、他でも問題ない(はず)です。

HTTP/2 への mruby 活用やこれからの TLS 設定と大量証明書設定の効率化について


とりあえず、まずは ngx_mruby をインストールするところから。
(昨日あたりに、 nginx の Mainline 1.9.11 がでたっぽい)

$ cd /path/to/work
$ wget http://nginx.org/download/nginx-1.9.10.tar.gz
$ tar xzvf nginx-1.9.10.tar.gz
$ git clone git@github.com:matsumoto-r/ngx_mruby.git
$ cd ngx_mruby
$ git submodule init
$ git submodule update
$ ./configure --with-ngx-src-root=/path/to/work/nginx-1.9.10
$ make build_mruby
$ make generate_gems_config
$ cd ../nginx-1.9.10
$ ./configure --prefix=/usr/local/nginx --add-module=/path/to/work/ngx_mruby --add-module=/path/to/work/ngx_mruby/dependence/ngx_devel_kit
$ make
$ sudo make install

これで、 nginx に ngx_mruby をインストールすることが出来ました。

証明書は、すでにあるものを使います。

$ cd /etc/letsencrypt/
$ sudo bash -c "cd live; ls"
example.com example.org

example.com の中に、 fullchain.pemprivkey.pem が入ってます。

次に、 nginx の方の設定。
これは、スライドにあったパスを書き換えるだけ。

mruby_ssl_handshake_handler_code '
    ssl = Nginx::SSL.new
    ssl.certificate     = "/etc/letsencrypt/live/#{ssl.servername}/fullchain.pem"
    ssl.cerfiticate_key = "/etc/letsencrypt/live/#{ssl.servername}/privkey.pem"
';

で、再起動。

$ sudo service nginx restart

しかし、この状態で https://example.com にアクセスすると、 SSL 接続エラーとなります。
nginx のログを見ると、

2016/02/10 03:50:45 [error] 8258#0: *8 ngx_mruby : mruby ssl handler: cert [/etc/letsencrypt/live/example.com/fullchain.pem] not exists or not read while SSL handshaking, client: 123.456.789.123, server: 0.0.0.0:443
2016/02/10 03:50:45 [crit] 8258#0: *8 SSL_do_handshake() failed (SSL: error:1408A179:SSL routines:ssl3_get_client_hello:cert cb error) while SSL handshaking, client: 123.456.789.123, server: 0.0.0.0:443

どうやら fullchain.pem が読み込めていない様子。
そのため、 fullchain.pem を読み込めるようにする必要があります。

ということで、 Let's Encrypt で作った証明書を見に行きます。

$ cd /etc/letsencrypt/
$ sudo bash -c "cd live/example.com; ls -l"
total 0
lrwxrwxrwx 1 root root   44 Feb 10 03:19 cert.pem -> ../../archive/example.com/cert1.pem
lrwxrwxrwx 1 root root   45 Feb 10 03:19 chain.pem -> ../../archive/example.com/chain1.pem
lrwxrwxrwx 1 root root   49 Feb 10 03:19 fullchain.pem -> ../../archive/example.com/fullchain1.pem
lrwxrwxrwx 1 root root   47 Feb 10 03:19 privkey.pem -> ../../archive/example.com/privkey1.pem

実体は別の場所にあるようなので、そこへ行ってみます。

$ cd ../../
$ sudo bash -c "cd archive/example.com; ls -l"
total 0
-rwx------ 1 root root 4096 Feb 10 01:15 cert1.pem
-rwx------ 1 root root 4096 Feb 10 01:15 chain1.pem
-rwx------ 1 root root 4096 Feb 10 01:15 fullchain1.pem
-rwx------ 1 root root 4096 Feb 10 01:15 privkey1.pem

root 以外だと読み込めないようになっているので、 ngx_mruby からも
読み込めるようにする必要があります。

とりあえずは、 root 以外のユーザーでも読み取れるようにするか、
nginx の属しているグループで読み取れるようにする必要があります。

前者はいろいろあれなので、後者の方法で読み取れるようにします。

ということで、 nginx が属しているグループに対して、読み取り権限を付与します。
通常、 nginx グループが作られているので、それに対して設定していきます。
(live ディレクトリにも設定しておいてください。)

$ sudo chgrp nginx -R archive/
$ sudo chgrp nginx -R live/
$ sudo chmod 750 -R archive/
$ sudo chmod 750 -R live/

これで、アクセスするとエラーが出なくなり、
無事 SSL 証明書の動的読み込みができるようになります。

ちなみに原因は、静的に指定した際は sudo service nginx start 等の場合は
root ユーザーで読み込まれるけども、
今回の場合は nginx の worker process が証明書を見に行くため。
そのため、 root でのみアクセス可能な場合は、 nginx では見れないから、
読み込めないよとエラーが出ていました。