AlpineLinuxでLetsEncrypt

2018年9月12日

Drupal8 立ち上げの続きです。この頃のブラウザは、ブログの編集画面で HTTPS じゃないと「この接続は安全ではありません……」がやたらと出てきます。PC に限った話かもしれませんが、煩わしいのとやっぱり安全も重要です。

KUSANAGI 環境なら provision で Let’s Encrypt の証明書取得までやってくれますが、当然 Alpine Linux にはありません。そこで certbot を利用して証明書を取得、nginx に設定して HTTPS 化することにします。

$apk search certbot
certbot-0.14.0-r0</code>

$apk add certbot

$cat /etc/apk/repositories
#/media/cdrom/apks
http://mirror.clarkson.edu/alpine/v3.6/main
http://mirror.clarkson.edu/alpine/v3.6/community
#http://mirror.clarkson.edu/alpine/edge/main
#http://mirror.clarkson.edu/alpine/edge/community
#http://mirror.clarkson.edu/alpine/edge/testing

http://dl-3.alpinelinux.org/alpine/v3.6/main
http://dl-3.alpinelinux.org/alpine/v3.6/community
#http://dl-3.alpinelinux.org/alpine/edge/main
#http://dl-3.alpinelinux.org/alpine/edge/community
#http://dl-3.alpinelinux.org/alpine/edge/testing


Alpine Linux 3.6.2 にはパッケージがあります。もし見付からない場合は、上記のように /etc/apk/repositories の /community 行にあるコメント(#) を外して下さい。デフォルトでは /main 以外は全てコメントアウトされています。

http://dl-3.alpinelinux.org/alpine/edge/ の様な「edge」リポジトリを有効にすると、非安定版ですが各パッケージのより新しいバージョンがインストール出来ますので、もし上手く動作しない場合は試してみるのもいいと思います。

certbot は python スクリプトなので、一緒にだだーっと python 関連のパッケージが入ります。2系が入りますが、先に python3 導入してたらどうなるのかな。

証明書取得のコマンドは以下の通り。

certbot certonly --webroot -w ドキュメントルートの絶対パス -d 取得ドメイン [-d サブドメイン ...]

certonly は証明書の取得だけ行う指定です。ヘルプを見ると、apache の SSL 設定を一緒にやってくれるオプションもあるみたいです。いまのパッケージだとまだ実装していないようですが。

–webroot は稼働中の httpd を利用する指定で、-w で指定したドキュメントルートに .well-known/acme-challenge/ を作成して一時ファイルを出力して、認証サーバーから HTTP アクセすることで確認を取ります。

稼働中の nginx を止める必要無く認証出来るので、こちらが一般的なやり方かと思います。Let’s Encrypt の証明書は 90日で失効しますので、定期的に更新しないとなりません。更新のタイミングで httpd を止めるのも困りますから、こちらで設定するのがおすすめです。

同じ証明書で認証したいサブドメインがあれば、-d を複数指定します。例えばこのブログのドメインなら、-d ikumi-u.net -d www.ikumi-u.net のようになります。ただし、名前解決出来るようになっていないと失敗しますのでネームサーバーの設定を忘れずに。

途中でメールアドレスの登録と利用規約への承認を求められます。メールアドレスは、証明書を作るドメインのものでなくても受け取れるものなら大丈夫です。最後に Congratulation が表示されれば成功です。

上手く認証出来ない場合は nginx の server ディレクティブを確認して下さい。リダイレクトしていないか、ドメイン名で正引き出来る server_name と一致しているかなど注意が必要です。

あとは nginx の設定を変更して HTTPS を有効にします。以前に作った www.conf を元に ssl.conf を HTTPS 接続用に作ります。例えばこんな感じです。

server {
        listen 443 ssl;
        server_name     example.com www.example.com;
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/nginx/dh2048.pem;
        ssl_ciphers
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
        ssl_session_timeout 2d;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security max-age=15768000;

        location / {
                root /var/www/html;
                index index.php;
                try_files $uri $uri/ @rewrite;
                expires max;
        }

        location @rewrite {
                rewrite ^/(.*)$ /index.php?q=$1;
        }

        location ~ \.php$ {
                root /var/www/html;
                fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }
}


続いて HTTP アクセスをリダイレクトする設定で、既存の www.conf を書き換えます。

server {
        listen  80;
        server_name     example.com www.example.com;
        return 301 https://$host$request_uri;
}


これで HTTP アクセスされると自動で HTTPS へリダイレクトされるようになります。安全でよろしいですね。nginx を再起動する前に nginx -t で設定が間違っていないか確認します。大量に変更した時は打ち間違えも多いので確認は必要です。

と、やっぱりエラーが出ました。ssl.conf の8行目、ssl_dhparam のファイルが無いというエラーです。うん、確かにこれないですね。/etc/nginx/nginx.conf のデフォルト設定でこのファイル名になってますが、作った覚えはない。無ければ作りましょう。openssl の以下のコマンドで作成します。

openssl dhparam -out /etc/ssl/nginx/dh2048.pem 2048

無事に作成されたら、再び nginx -t で確認して、エラーが無ければ再起動します。設定が上手くいっていれば、Drupal8 が HTTPS の鍵付きサイトで表示されます。これならブラウザの警告も出なくて安心です。

最後に証明書の定期更新の設定をしておきます。コマンドは以下のようになります。

/usr/bin/certbot renew --post-hook "/sbin/rc-service nginx restart"

–post-hook は renewal された場合に実行してくれるコマンドで、nginx サービスを再起動しています。定期実行なので cron にお任せする場合、/etc/periodic/monthly/ に置いておけばやってくれます。ルート権限の cron は /etc/crontabs/root に設定があります。毎月1日の5時に実行されるようです。

自分はこのデフォルト設定から変更することをおすすめしています。多少なりとも負荷分散になってくれればいいなぁと。

 

以上で HTTPS 化が出来ました。ここまでにネット上の様々な方の情報に助けられています。特に「Let’s Encrypt 総合ポータル」と「Nginxで起動中のサーバーにLet’s Encryptを導入してhttps化するためのSSL証明書を発行する」の両サイトには勉強させて頂きました。ありがとうございました。

次はいよいよ Drupal でサイト構築です。