問題
Let’s EncryptでSSLを自動更新したいけど、転送設定が邪魔して証明書が更新できない問題が発生。
ネイキッドドメインからwwwへ転送をかけている状況で、ネイキッドドメインのSSLを更新しようとして、webrootにcertbotがファイルを書き込むも、証明書更新しようとするとwww付きへ転送されてしまってファイルがみつからず、更新できないという状態になります。
背景とやりたいこと
Webサービス(ここでは主にカートシステムやブログサービスの事です)で独自ドメインが使えるけどCNAMEで指定する仕様の時、ネイキッドドメイン(wwwやサブドメイン無しのドメイン)をどうするか問題があります。
ネイキッドドメインに対してCNAMEレコードは設定できない事がほとんどです。(一部のDNSサービスでは出来るようです)
例)
https://www.example.com ←CNAME指定可能なドメイン
https://example.com ←ネイキッドドメイン
出来れば、ネイキッドドメインのURLを直打ちした場合でもwwwサイトが表示されるようにしたいものです。つまり、アドレスバーで「example.com」とだけ打っても「https://www.example.com」に転送されるようにしたいですよね。
「example.com」用のサーバーを立てて、アクセスがあったら「www.example.com」に転送するという方法があります。
その場合、「.htacess」を設置して下記のように転送をかけます。
RewriteEngine on
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]
で、このときネイキッドドメイン側にもSSLがないと転送するまえに「信頼のないサイト」となって転送前にアラートが出てしまいます。怪しいサイトだ!と思われて離脱されることでしょう。
ネイキッドドメインにSSLを適用しつつ、wwwへ転送したい。
SSL証明書は無料のLet’s Encryptを使用したい。できれば自動更新したい。
解決するには
certbotでSSL更新する時だけ、転送設定を解除できればいいのです。
.htaccessをリネームなんかして、SSL更新したあとに、元に戻す。
そして上記を90日の有効期限が切れる前にCronで自動実行したい!
やってみる
シェルスクリプトを作成し、Cronで自動実行するやり方です。(certbotのインストールなどは済んでいる状態とします。)
※ドキュメントルートを/var/www/html/example.com/html としています。
シェルスクリプトを作成
適当な場所に下記のシェルスクリプトを配置します。
ここでは /var/www/html/example.com/certrenew.sh として作成しました。パーミッションは755にしました。
#!/bin/bash
date
mv /var/www/html/example.com/html/.htaccess /var/www/html/example.com/html/.htaccess_bk
certbot certonly --webroot -w /var/www/html/example.com/html --email youraddress@example.com --debug -d example.com
systemctl restart httpd.service
mv /var/www/html/example.com/html/.htaccess_bk /var/www/html/example.com/html/.htaccess
- dateコマンドはログに実行時間を記録するためです
- mvで.htaccessをリネームしています
- このサーバーには複数のサイトがあるので、certbot renewではなくて、certonlyをつかって対象のドメインのみwebroot認証させています。※一連のテストするときは「–dry-run」をオプションでつけると、結果のみ返してくれます。
- apacheを再起動して更新を適用します
- 最後にリネームした.htaccessを元に戻します
Cronの設定
/etc/cron.d/letsencrypt を作成して以下の内容を記述します
0 16 */80 * * root /var/www/html/example.com/certrenew.sh >> /var/www/html/example.com/cert.log 2>&1
80日毎(90日だとギリギリ感があるし、月イチだとlet’s encryptに負荷をかけて申し訳ないので80日としました。※残存30日以下だと更新できます。)の16:00にシェルスクリプトをrootで実行します。実行結果はshと同じ場所にあるcert.logに追記していきます。ここに先ほどのdateで出力した日時が記録されるのでいつ実行されたかわかります。
まとめ
シェルスクリプトを使って、若干めんどくさい更新も自動化できました。