WordPressサイトをhttpsにした際にハマったこと(Lets Encrypt)
無料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が読み込めない状態になってしまいました。
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」というプラグインを導入して一括置換を行いました。
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に修正します。
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にhttpsのURLを追加し、サイトマップの送信を行っておきました。
まとめ
これで一通りWordpressサイトのhttps化ができました。 Let's Encryptを使うと手軽に導入できるのでいいですね。
また、証明書の更新もコマンドでできるのがいいなぁと思いました。
その他参考にさせていただいた記事
- Let's Encrypt 総合ポータル
- WordPressで作ったブログをSSL化した時にやった事 | P2P today ダブルスラッシュ
- 既存のWordPressサイトを常時SSL化させる手順 | cms helog - CMS構築を目的にPHPをベースとしたWordPress、CakePHPやPEARなどオープンソースを中心に解説しています
- 当 Blog を SSL 対応させたので手順や修正が必要になった点などをまとめ | WWW WATCH
- WordPress をフロント Nginx のリバースプロキシ下で運用する場合に 管理画面を SSL に強制する設定 - tilfin's note
- https,nginx,リバースプロキシ使用でWordpressがリダイレクトループにハマった時 | ゲオログ by リバネスCIO 吉田丈治 @geeorgey
- nginxで静的ファイルを返す設定、あってますか? | Zafiel
- nginxで訪問者のIPをリバースプロキシから後ろのサーバーへ渡す設定 | Zafiel
- Let's Encrypt を支える ACME プロトコル - Block Rockin’ Codes