Let’s Encrypt の設定変更

以前に ACMEv1 問題のことで Alpine Linux のアップグレードをしました。これで安心と思っていたら、なんとこんなメールが……

Hello,
Your certificate (or certificates) for the names listed below will expire in 19 days (on 28 May 20 17:00 +0000). Please make sure to renew your certificate before then, or visitors to your website will encounter errors.
We recommend renewing certificates automatically when they have a third of their
total lifetime left. For Let’s Encrypt’s current 90-day certificates, that means
renewing 30 days before expiration. See
https://letsencrypt.org/docs/integration-guide/ for details.

more…

ようするに、あと19日で証明書の有効期限切れちゃうけど、更新しなくていいの? やり方分からないんだったら以下の説明見てね~、っていう親切なメールです。ウソんっ!? と焦ってコンソールから手動で certbot による更新を試したところ、今度は下のようなエラーが。

An unexpected error occurred:
MemoryError: Cannot allocate write+execute memory for ffi.callback(). You might be running on a system that prevents this. For more information, see https://cffi.readthedocs.io/en/latest/using.html#callbacks
Please see the logfiles in /var/log/letsencrypt for more details.

マジかぁーっ!! 更新できてないやん……あかんヤツや……というわけでエラーログを見ると、python3 がメモリに書き込みアクセスできないとかで openssl 経由での通信に失敗している様子。プロセスの不正なメモリ書き換えを許可しない、Gentoo や Arch で使われている、カーネルセキュリティの機能のようで、GrSecurity とかいうものらしい。

それから方々調べてみましたが、わたしのつたない Linux知識と英語力ではどう解決すればいいやら分からず。python3 関連ということで、pip 経由でライブラリのアップデートをしたり、新しくパッケージ入れたりしましたが、結局どうにもならず。

諦めかけていましたが最後に初心に返ってみようと Let’s Encrypt の公式サイトを見に行ったところ、更新クライアントがいろいろ紹介されていました。その中にあった、acme.sh というシェルスクリプトのクライアントに興味がわいて、ネットで調べてみると以下の記事が見つかりました。

Alpine でも apk のパッケージにちゃんと含まれていて、apk add でサクッと導入できました。後は上の記事にあるとおりに

/usr/bin/acme.sh --issue -d <取得するドメイン> -d <ついでにサブドメイン> -w <ドキュメントルート>

を実行して、エラーなく終了すればいくつかファイルが作成されます。サイズも 0バイトではないのでちゃんとできているようです。Alpine で運営しているサイトのドメインだと、以下の7つのファイルが作成されました。

ca.cer
fullchain.cer
ikumi-u.com.cer
ikumi-u.com.conf
ikumi-u.com.csr
ikumi-u.com.csr.conf
ikumi-u.com.key

記事の中にある openssl コマンドできちんとした証明書か確認するのもよいでしょう。取得時にエラー出てなければ大体問題ありませんが。続いて以下のコマンドで証明書ファイルをインストールします。nginx を使っているので必要なファイルは fullchain と key の二種類だけです。

/usr/bin/acme.sh --install-cert -d ikumi-u.com --keypath <配置先>/ikumi-u.com.key --fullchainpath <配置先>/ikumi-u.com.fullchain

certbot で作成した証明書ファイルと同じパスを指定して上書きすれば、nginx の設定を変更しなくてすみますが、今回は別のディレクトリに配置することにしました。それに合わせて ssl.conf の該当箇所を書き換えます。

ssl_certificate <配置先>/ikumi-u.com.fullchain;
ssl_certificate_key <配置先>/ikumi-u.com.key;

これで nginx をリロードしてエラー無く稼働してくれれば、晴れて証明書の更新ができた状態で元に戻った、よかったよかったということになります。

さて、今回は certbot で取得していたドメインの証明書更新で acme.sh を使うように切り替えたわけですが、最初から新規で取得する場合などは、お知らせメールの登録なども必要になるかと思います。今回それで助けられているわけですし。以下の方の記事でコマンドのパラメーターなどが詳しく紹介されています。

実際には –install コマンドとか使ってないので、メールアドレスの登録がちゃんとできるのかとか、どこかで試してみないといけないかなぁとは思いますがやってません! 現状が改善すればよかろう。

証明書の更新は、/usr/bin/acme.sh –renewAll コマンドで実行します。有効期間に余裕があってまだ更新しなくていい場合は、更新しないで次回更新予定日を表示して終了します。cron で設定するでもよし、Alpine風に /etc/periodic/ にスクリプト置くでもよしです。わたしは certbot の頃から weekly にスクリプトを置いていましたので、それで実行するようにしています。

更新実行後は、先に書いた証明書のインストールコマンドで –reloadcmd “/sbin/rc-service nginx restart" というパラメーターを付けて実行すれば、nginx がリロードされて無事証明書の更新が完了します。

まー今回はいろいろと勉強になりました。python3 は certbot のためだけに導入しているので、そのうちアンインストールしてもいいかななんて思っています。