WordPressサイトをhttpsにした際にハマったこと(Lets Encrypt)


By: Nikolay Bachiyski

無料SSL/TLSとして最近話題になっている Let’s Encrypt を試してみたかったので、このブログをhttpsにしてみました。

本ブログはnginx + php-fpmを使ってWordPressを動かしています。

Let’s Encryptの導入自体は手軽にできたのですが、httpsにした後いくつか対応することがあったのでメモしておきます。

1. Let’s Encryptで証明書取得

Let’s Encrypt で手軽に HTTPS サーバを設定する – Qiita

こちらの記事を参考に証明書の取得とnginxへの設定を行いました。

Pythonのバージョンが2.6.6だったのですが、実行時にdebugオプションを付ける必要があると警告が出たので以下のようにしました。

./letsencrypt-auto certonly --webroot --webroot-path /path/to/root -d blog.hello-world.jp.net --debug

2. Nginx設定

参考記事ではhttpで接続があった際にhttpsへリダイレクトする設定が書かれていましたが、httpsでの表示が確認できるまでは既存の設定を残しておくことにしました。

# 既存の設定をそのまま残しておく(あとでリダイレクト設定に置き換える)
server {
        listen      80;
        server_name blog.hello-world.jp.net;
        ・・・
}

# 既存の設定をコピーしつつ、参考記事を元にssl設定を追加
server {
        listen      443 ssl;
        server_name blog.hello-world.jp.net;

        ssl_certificate /etc/letsencrypt/live/blog.hello-world.jp.net/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/blog.hello-world.jp.net/privkey.pem;
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_dhparam /etc/ssl/private/dhparam.pem;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        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:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-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_prefer_server_ciphers on;

        proxy_redirect                          off;
        proxy_set_header Host                   $host;
        proxy_set_header X-Real-IP              $remote_addr;
        proxy_set_header X-Forwarded-Proto      https;
        proxy_set_header X-Forwarded-Host       $host;
        proxy_set_header X-Forwarded-Server     $host;
        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;

        ・・・
}

ここまでできたらNginxの設定を再読み込みします。

/etc/init.d/nginx configtest
# エラーがなければ設定再読み込み
/etc/init.d/nginx reload

これで http://blog.hello-world.jp.net と https://blog.hello-world.jp.net の両方でアクセスできるようになりました。

ただ、httpsのほうは以下のようにcssが読み込めない状態になってしまいました。

https

3. Mixed Contentエラーを修正する

Chromeの開発者ツールで見てみると、コンソールに警告が色々出ていました。

cssだけでなく画像やjsに対しても警告が出ており、これはhttpsページの中にhttp経由でコンテンツを取得しようとしている部分があるのが原因です。

Mixed Content(混在コンテンツ)と呼ばれるものですね。

WordPress側の設定を地道に修正していく必要がありました。

3-1. 記事内のリンクを修正する

画像リンク等、これまでの投稿の中で http://blog.hello-world.jp.net/~ と記述しているものがたくさんあったので、これをhttpsに一括置換する必要があります。

一括置換を実施する前にDBのバックアップをとっておきましょう。

直接DBに対してupdateを実行するのもありですが、「Search Regex」というプラグインを導入して一括置換を行いました。

https2

Searchで調べて変更箇所を確認したら、Replace & Saveで置換を実行します。(800箇所くらいありました)

3-2. ウィジェットの修正

ウィジェットのサイドバーで独自に設定した画像やjsリンクにもhttpの記述があったのでhttpsに修正しました。

3-3. サイトアドレスをhttpsに修正

WordPressドキュメントを見ると

SSL を提供するリバースプロキシにより WordPress がホストされ、自身は SSL なしでホストされる場合、このオプションを設定すると当初すべてのリクエストが無限リダイレクトループに陥ります。これを避けるには HTTP_X_FORWARDED_PROTO ヘッダーを認識するように WordPress を構成してください。ここでリバースプロキシは適切に構成されており、ヘッダーを設定するものとします。
管理画面での SSL 通信 – WordPress Codex 日本語版

とあり、今回の構成だと無限リダイレクトループが発生したので以下のようにwp-config.phpの上部に設定を追記しました。

# wp-config.php
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])-
  && $_SERVER['HTTP_X_FORWARDED_PROTO'] === "https") {
    $_SERVER['HTTPS'] = 'on';
}
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

Nginx側でproxy_set_headerを設定していれば、これでリダイレクトループが発生することなく管理画面にログインできるようになります。

管理画面にログインしたら、「設定」の「一般」でWordPressアドレスとサイトアドレスをhttpsに修正します。

https3

WordPressアドレスをhttpsに変更したことで、cssやjs等のURLもhttpsに変わり、Mixed Content警告は出なくなりました。

4. Nginxのリダイレクト設定を追加

httpsで問題なく表示できることを確認できたので、既存のhttp設定を変更し、httpsにリダイレクトする設定に置き換えます。

server {
        listen 80;
        server_name blog.hello-world.jp.net;
        rewrite ^ https://$server_name$request_uri? permanent;
}

設定後、Nginxの設定を再読み込みします。

/etc/init.d/nginx configtest
# エラーがなければ設定再読み込み
/etc/init.d/nginx reload

これでhttpのURLにアクセスするとhttpsにリダイレクトされるようになります。

5. Let’s Encrypt証明書の自動更新設定

Let’s Encrypt サーバー証明書の取得と自動更新設定メモ | あぱーブログ

を参考にcronで証明書の自動更新を行うように設定しました。

Let’s Encrypt の証明書の有効期限は90日間らしいので2ヶ月に一回更新するようにしています。

rootのcronに以下を記述。

00 05 01 */2 * /path/to/letsencrypt-auto certonly --webroot -w /path/to/root -d blog.hello-world.jp.net --debug --renew-by-default && /etc/init.d/nginx reload

6. Google Search Consoleにhttpsを追加

サイトの http と https のバージョンを別々のプロパティとして追加する必要があります。
ウェブサイト プロパティを追加する – Search Console ヘルプ

とあったので、Search ConsoleにhttpsのURLを追加し、サイトマップの送信を行っておきました。

まとめ

これで一通りWordpressサイトのhttps化ができました。

Let’s Encryptを使うと手軽に導入できるのでいいですね。

また、証明書の更新もコマンドでできるのがいいなぁと思いました。

その他参考にさせていただいた記事