letsencryptの更新に cert-bot を使っています。便利で大変助かっておりますが、先日バーチャルホスト環境で一部サービスの証明書更新のみ失敗する事例にあたりましたので、記録しておきます。誰かのお役に立てれば幸いです。
事例
- nginxバーチャルホスト環境の証明書更新に一部サービスだけが失敗していた
- 同じサーバに同居している他のサービスは何故か更新成功
- 使っていた authenticator は nginx
- エラーメッセージは以下のような感じ
Attempting to renew cert (【ドメイン名】) from /etc/letsencrypt/renewal/【設定ファイル名】.conf produced an unexpected error: Failed authorization procedure. 【ドメイン名】 (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://【ドメイン名】/.well-known/acme-challenge/【チャレンジ用ファイル名】: "【サーバからのレスポンスボディ:404の内容】". Skipping.
原因
- cert-botが更新すべきnginx.confファイルの間違えて識別していたため、ドメイン検証用の一時ファイルにアクセスできずにエラーになっていた
- 何と間違えたか? フロント用ではなくバックエンド用のconfファイルを更新していた
- バックエンドのconfを更新しているため、フロントからドメイン検証用ファイルへのアクセスが通らずに404になっていた
- なぜ間違えたか? ドメイン名と相違が大きいファイル名になっていた
対策
- confファイル名を「【ドメイン名】.conf」 に変更して
cert-auto renew
を再実行した(nginx reload
必要かも ) - フロント用の conf ファイルを更新対象と識別して、ドメイン認証が通過し、証明書が更新された
原因詳細
本当のドメイン名じゃないけど、以下のような状況でした。
- サービスURL:
subdomain.domain.jp
- フロント用confファイル名:
subdomain.conf
- バックエンド(php-fpm)用confファイル名:
subdomain.backend.conf
cert-bot renew
を実行すると、ログに以下の記述が。。。
2018-11-16 10:58:55,885:DEBUG:certbot_nginx.parser:Writing nginx conf tree to /etc/nginx/conf.d/subdomain.backend.conf:
バックエンド用のconfに対して、ドメイン証明用ファイルのパスを通すための location ディレクティブを追記していました。
それは letsencrypt のサーバからアクセスできんわ。。
certbotのプログラムでいうところの、このあたりで、バーチャルホストファイルの識別をしています。
ランキング処理までは追っかけてませんが、要はconfの内容とファイル名からランキングを付けて正しいconfファイルを識別しているみたい。バックエンド用のconfは .backend
が後ろについているため、ロンゲストマッチだとすると、ドットの分だけドメイン名により似ていると認識されたのかもしれません。
ログメッセージにはDNS疑えってしきりに書いてあったので、結構悩みました。。。