astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

nginx + ngx_mruby でSSL証明書の動的読み込みを実現して、作業がとても楽になった話

こんにちは。並河(@namikawa)です。

随分と寒くなってきたんで、そろそろ銀座界隈のオススメのラーメン屋の紹介でもしようと思・・・うわなにをするやめくぁwせdrftgyふじこlp;

・・・はい。今日は、ちょっと前にやった nginx + ngx_mrubySSL証明書の動的読み込みを実現して、作業がとっても楽になったワンって話をしようと思います。

前提の話

弊社では、転職ナビという400近く存在する多くのドメインを持つサイトがあり、そのSSL処理をフロントの nginx で行なっています。

過去、そのバーチャルホストの設定がドメインごとにベタ書きされていた経緯があり、その辺の共通化・書き直しを少しずつやっていて、正規表現や環境変数を駆使することで、随分と設定は共通化できたりするのですが、どうにもならなかったのがSSL証明書の設定である、

  • ssl_certificate
  • ssl_certificate_key

の2項目です。色々とドキュメントを読んだのですが、これらの設定値には変数が使えないんですよね。 さて、どうしたものか。と色々と調べていたら、

どうやら、この2つのいずれかのモジュールを組み込むことで、動的に設定値を生成できるらしいということを知りました。

個人的には、Ruby の方が近しい存在ではあるので、ちょっと ngx_mruby を使って、動きを試してみました。

ngx_mruby モジュールを組み込んだ nginx パッケージを作る

弊社では、サーバのOS・ディストリビューションに Ubuntu を使っているので、 それ用の nginx パッケージを作成します。パッケージの作成については、以下の手順で行いました。

(尚、8月初旬にやった作業なので、バージョン関連の記載が古いと思うので、お試しの際は現行のバージョンにあわせてくださいませ。)

# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

# cat /proc/version
Linux version 4.4.0-31-generic (buildd@lgw01-16) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2.1) ) #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016

ちなみに、動作を確認した環境は上記な感じのサーバとなります。

# apt-get update
# apt-get install git build-essential devscripts ruby rake bison libssl-dev libxslt-dev libgd-dev libgeoip-dev libperl-dev

まずは、パッケージDBをアップデートして、必要なパッケージをインストールします。

# wget -qO - http://nginx.org/keys/nginx_signing.key | apt-key add -
# echo 'deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx' >> /etc/apt/sources.list
# echo 'deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx' >> /etc/apt/sources.list

nginx 公式のリポジトリを追加。

# apt-get update

# cd /usr/local/src
# apt-get build-dep -y nginx="1.11.3"
# apt-get source nginx="1.11.3"

パッケージビルドを行うための準備と、source パッケージを持ってきます。

# git clone --branch v1.18.2 --depth 1 https://github.com/matsumoto-r/ngx_mruby.git

# cd /usr/local/src/ngx_mruby
# ./configure --with-ngx-src-root=/usr/local/src/nginx-1.11.3
# make build_mruby
# make generate_gems_config

ngx_mruby を git リポジトリから持ってきて、ビルドします。

# cd /usr/local/src/nginx-1.11.3
# vim debian/rules

nginx のディレクトリに移り、vim 等で rules ファイルを編集します。

--add-module=/usr/local/src/ngx_mruby \
--add-module=/usr/local/src/ngx_mruby/dependence/ngx_devel_kit \

ファイルを開いて、 COMMON_CONFIGURE_ARGS の部分に上記の2行を追記します。

# dpkg-buildpackage -r -uc -b

ここまでで準備は完了。で、パッケージビルドします。

# ll /usr/local/src/*.deb
-rw-r--r-- 1 root root  1222032 Aug  2 09:22 /usr/local/src/nginx_1.11.3-1~xenial_amd64.deb
-rw-r--r-- 1 root root 11912660 Aug  2 09:22 /usr/local/src/nginx-dbg_1.11.3-1~xenial_amd64.deb
-rw-r--r-- 1 root root    11620 Aug  2 09:22 /usr/local/src/nginx-module-geoip_1.11.3-1~xenial_amd64.deb
-rw-r--r-- 1 root root    14988 Aug  2 09:22 /usr/local/src/nginx-module-image-filter_1.11.3-1~xenial_amd64.deb
-rw-r--r-- 1 root root    91038 Aug  2 09:22 /usr/local/src/nginx-module-njs_1.11.3.0.1.0-1~xenial_amd64.deb
-rw-r--r-- 1 root root    24314 Aug  2 09:22 /usr/local/src/nginx-module-perl_1.11.3-1~xenial_amd64.deb
-rw-r--r-- 1 root root    13162 Aug  2 09:22 /usr/local/src/nginx-module-xslt_1.11.3-1~xenial_amd64.deb

はい、 nginx のパッケージ(.debファイル)が完成しました。

余談ですが、この ngx_mruby では openssl 1.0.2 以上が必要になるので、Ubuntu 16.04 以前では、別途 openssl 1.0.2 以上のインストールが必要になります。

パッケージインストール&設定

# deb -i /usr/local/src/nginx_1.11.3-1~xenial_amd64.deb

サクッとインストールしてしまった後は、 "/etc/nginx.conf" や "/etc/nginx/sites-*" あたりの設定ファイルの server ディレクティブに、

ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;

mruby_ssl_handshake_handler_code '
    ssl = Nginx::SSL.new
    ssl.certificate     = "/etc/nginx/ssl/#{ssl.servername}/#{ssl.servername}.crt"
    ssl.certificate_key = "/etc/nginx/ssl/#{ssl.servername}/#{ssl.servername}.key"
';

こんな感じで記載します。 SSL証明書を読み込む際に、mrubyがフックされるような仕組みなので、 ssl_certificatessl_certificate_key のファイルについては何でもOKです。 上記設定を記載後に、 nginx を起動(or 再起動)するだけで、動作確認できるかと思います。

もし何か問題があれば、 nginx のログを確認しましょう。よくあるというか私もひっかかったのは、SSL証明書のパーミッションの問題です。SSL証明書ファイルは、 nginx プロセスからでも読めるパーミッションにする必要があります。

実際に運用してみて

めちゃくちゃ作業が楽になりました。

実際にサイト(ドメイン)追加の際、他の設定は共通化しているので、SSL証明書を配置するだけです。CMS的な似たような(設定が同様な)ドメイン・サイトの運用をするユースケースでは、すごく有用だと思います。

今年の9月くらいから、3ヶ月ほど本番環境で運用していますが、特に大きな問題は出ておらず、安定して動いています。

作者の matsumotory さんの資料によると、「性能はngx_mrubyのhello worldベンチで10%減程度」とのことなので、ここが許容できる場合は、かなり良いモジュールですね。

今日はここまで。それでは!=͟͟͞͞(๑•̀=͟͟͞͞(๑•̀д•́=͟͟͞͞(๑•̀д•́๑)=͟͟͞͞(๑•̀д•́

Copyright © astamuse company, ltd. all rights reserved.