自社WordPressサイトを完全HTTPS化しました。

2016年4月27日、この「稲葉サーバーデザインWebサイト」を完全HTTPS化(フルHTTPS化、常時SSL化)しました。
完全HTTPS化しようと思った理由は次のとおりです。

  • 無料SSLサーバー証明書発行サービスLet’s Encryptが正式版となった。
  • GoogleがHTTPSをランキングアルゴリズムとして利用している。
  • HTTP/2は実質的にHTTPS通信が必須。
  • WordPressサイトのHTTPS化を試してみたかった。

※今回は、HTTP/2には対応していません。

完全HTTPS化にあたっての作業手順は、次の記事を参考にしました。

・ブログの完全HTTPS化を完了、HTTPからHTTPSへの移行プロセスを共有
https://www.suzukikenichi.com/blog/what-i-have-done-to-switch-my-blog-to-full-https/

作業手順について簡単にまとめておきます。

isdサーバー構成

HTTPS化時点のWebサイトのサーバー構成は次のとおりです。

サーバー IDCFクラウド
OS CentOS 7
Webサーバー  Nginx 1.8.1 + PHP-FPM 
CMS WordPress 4.5

 
 
 
 
 

isd完全HTTPS化の手順

完全HTTPS化の手順はこんな感じです。

  • 1. 前準備
    • 1-1. TCP/443のアクセス許可
    • 1-2. SSLサーバー証明書を取得
    • 1-3. NginxのHTTPSアクセス設定を追加
    • 1-4. ソーシャルメディアのシェア数保存の準備
    • 1-5. データバックアップ
  • 2. HTTP→HTTPSの切り替え
    • 2-1. NginxのHTTPSリダイレクト設定
    • 2-2. WordPressの設定変更
    • 2-3. WordPressデータの内部リンクの変更
    • 2-4. Nginxをreloadして反映
    • 2-5. NginxのProxy Cacheを削除
  • 3. HTTPS切り替え後の確認
    • 3-1. ページ表示を確認
    • 3-2. 残っていたHTTPリンクをHTTPSリンクに変更
    • 3-3. ソーシャルメディアのシェア数保存設定
    • 3-4. HSTS(HTTP Strict Transport Security)の設定
  • 4. 監視、外部サービスの設定変更
    • 4-1. 死活監視サービスPingdomの監視URLを変更
    • 4-2. 死活監視ツールNagios設定変更
    • 4-3. AWS DNSフェイルオーバーの設定変更
    • 4-4. Googleウェブマスターツールの設定変更
    • 4-5. アクセス解析ツールAWStatsの設定変更

ひとつずつ補足します。

1. 前準備

1-1. TCP/443のアクセス許可

これまでHTTPSは一切使用していなかったので、クラウドのファイアウォールとサーバーのiptablesで、TCP/443へのアクセス許可ルールを新たに追加します。
 

1-2. SSLサーバー証明書を取得

今回は、サーバー証明書を、無料の発行サービスLet’s Encryptで取得しました。

(参考)
・Let’s EncryptでSSLサーバー証明書を取得してみた
https://inaba-serverdesign.jp/blog/20151217/lets-encrypt.html

Let’s Encryptで発行される証明書の有効期限は90日間なので、自動更新の設定も行います。

自動更新を実行するスクリプト。
更新時に、一時的にNginxを停止する必要があります。

 # vi /root/bin/update_sslcert.sh

--
#!/bin/sh
#
LOGFILE=/var/log/update_sslcert.log
COMMAND=/usr/local/letsencrypt/letsencrypt-auto
MAILTO=root

echo "===== Update SSL Cert =====" >> ${LOGFILE}
echo "`date` Update SSL Cert start" >> ${LOGFILE}

systemctl stop nginx

${COMMAND} renew --non-interactive >> ${LOGFILE}
LE_STATUS=$?

systemctl start nginx

if [ "$LE_STATUS" != 0 ]; then
    echo "Update SSL Cert failed" >> ${LOGFILE}
    echo "Update SSL Cert failed" |\
    mail -s "Update SSL Cert in `hostname`" ${MAILTO}
fi

echo "`date` Update SSL Cert end" >> ${LOGFILE}

# EOF
--

 # chmod 700 /root/bin/update_sslcert.sh

 

(2016.6.30追記)
現在は、シェルスクリプトは以下のように変更しました。
クライアントコマンドがletsencrypt-autoからcertbot-autoに変更となり、また、サブコマンド renew のオプション -pre-hook, –post-hook でNginxの停止、起動を行うようにしました。

 # vi /root/bin/update_sslcert.sh
 
--
#!/bin/sh
#
LOGFILE=/var/log/update_sslcert.log
COMMAND=/usr/local/certbot/certbot-auto
WEBSERVER_STOP_COMMAND="systemctl stop nginx"
WEBSERVER_START_COMMAND="systemctl start nginx"

MAILTO=root
 
echo "===== Update SSL Cert =====" >> ${LOGFILE}
echo "`date` Update SSL Cert start" >> ${LOGFILE}
 
${COMMAND} renew \
  --pre-hook "$WEBSERVER_STOP_COMMAND" \
  --post-hook "$WEBSERVER_START_COMMAND" \
  --non-interactive >> ${LOGFILE}
STATUS=$?
  
if [ "$STATUS" != 0 ]; then
    echo "Update SSL Cert failed" >> ${LOGFILE}
    echo "Update SSL Cert failed" |\
    mail -s "Update SSL Cert in `hostname`" ${MAILTO}
fi
 
echo "`date` Update SSL Cert end" >> ${LOGFILE}
 
# EOF
--

 
(2016.6.30追記ここまで)

シェルスクリプトの定期実行のため、cronで週に一度、毎週水曜の14:50に実行するようにします。
仕様では、証明書を更新できるのは有効期限の30日以内で、期限まで30日以上あるときは更新コマンドを実行しても、証明書ファイルは更新されません。
このため、更新処理は週に一度実行するようにしました。
(毎日だと多すぎるけど、月に一度だと万一更新に失敗したときに期限切れとなってしまうため)

 # crontab -e

--
# Update SSL Cert
50 14 * * 4 /root/bin/update_sslcert.sh > /dev/null
--

 

※平日の昼間にしたのは、何らかの不具合でWebサーバープロセスが停止したままとなってもすぐ対処できるようにするためです。

1-3. NginxのHTTPSアクセス設定を追加

HTTPSアクセス用のConfigを追加します。
HTTPS通信に関する設定のみ抜粋すると、次のような感じです。

 # vi /etc/nginx/conf.d/vhost_ssl_inaba-serverdesign.jp.conf

--
server {
    listen      443 ssl;

    server_name inaba-serverdesign.jp;
    root   <wordpress_root_dir>;

    # SSL
    ssl on;
    ssl_certificate      /etc/letsencrypt/live/inaba-serverdesign.jp/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/inaba-serverdesign.jp/privkey.pem;

    ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers          ALL:!ADH:!EXPORT:!SSLv2:+HIGH:+MEDIUM:!RC4:!LOW:!EXP:!e
NULL:!aNULL;
    ssl_prefer_server_ciphers   on;

    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;

    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
...
--

 

Diffie-Hellman(DH) key agreement プロトコルの暗号化パラメータファイルを作成します。
サーバーのスペックにもよりますが、30秒から5分ぐらいかかります。

 # mkdir /etc/nginx/ssl
 # openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

 

Nginxに反映するため、再起動します。
この時点では、WebコンテンツのHTTPS化は行っていないので、リダイレクトの設定は行いません。

 # nginx -t
 # systemctl restart nginx

 

1-4. ソーシャルメディアのシェア数保存の準備

このWebサイトは、WP Social Bookmarking Lightプラグインを利用してソーシャルブックマークボタンを設置していました。
数は少ないですが、HTTPS化してもシェア数表示を維持したかったので、SNS Count Cacheを使用しました。

(参考)
・[試] 表示速度改善のその先へ!進化するWordPressプラグイン SNS Count Cache
https://marubon.info/intro-update-wordpress-plugin-sns-count-cache-3-5403/

HTTPS化する前に、このプラグインをインストールしておきます。

シェアボタンを表示するHTMLコードとCSSは次の記事を参考にしました。
ありがとうございました。

・WordPressプラグイン「SNS Count Cache」を利用してオリジナルのシェアボタンを設置しました
http://jimeishi.net/sns-count-cache-sharebutton
(↑記事が見れなくなりました。)

フロントエンドの知識がほとんどないので、今回のHTTPS化作業の中では、このシェアボタンの表示、とくにCSSまわりの設定が一番苦労しました。
最終的には、CSSをsb.cssとして保存し、header.php <header> </header> 内でFont AwesomeアイコンのCSSとsb.cssへのlinkを追加することで解決しました。

 # vi header.php

--
<head>
...
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link rel="stylesheet" href="<?php echo get_template_directory_uri(); ?>/sb.css" type="text/css" />
...
</head>
--

 

この状態で、各Webページのシェアボタンが正しく表示されることを確認します。
 

1-5. データバックアップ

HTTPS化ではコンテンツデータやWordPress Configの設定変更を行うので、万一失敗したときに元に戻せるよう、バックアップをとっておきます。

MySQL DBデータのdumpと、WordPressディレクトリのコピーを行いました。
 

2. HTTP→HTTPSの切り替え

このブロックの設定作業中は、Webページにアクセスできなくなったり、表示が乱れたりします。
本当は、HTTPSでの表示が問題ないことを確認してから、最後にリダイレクトの設定を行うつもりでしたが、僕の環境では、このブロックはまとめて行う必要がありました。
 

2-1. NginxのHTTPSリダイレクト設定

http://~ へのアクセスをすべて https://~ にリダイレクトします。


 # vi /etc/nginx/conf.d/vhost_inaba-serverdesign.jp.conf

--
server {
    listen 80;
    server_name inaba-serverdesign.jp;
    return 301 https://$host$request_uri;

...
--

もうひとつ、NginxのProxy Cache設定を行っている場合は、

proxy_set_header X-Forwarded-Proto https;

の設定が必要です。
(僕はこの設定が抜けていて、リダイレクトループが発生してしまいました。)

(参考)
・WordPressをhttps化してnginx reverse proxy配下で使うには
https://blog.admkazuya.org/archives/243

 # vi /etc/nginx/nginx.conf

--
    proxy_set_header Host            $http_host;
    proxy_set_header X-Remote-Addr   $remote_addr;
    proxy_set_header X-Forwarded-Proto      https; // ★追記
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
--

 

※この時点ではHTTPS化の設定途中なので、Nginxのreloadは行いません。
 

2-2. WordPressの設定変更

wp-config.phpで強制HTTPS通信の設定を追記します。

 # vi wp-config.php

-- 先頭のほうに
<? 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);
...
--

 

また、WordPressのサイトアドレスをHTTPSに変更します。

WordPress管理画面の 設定 > 一般 で
「WordPress アドレス (URL)」と「サイトアドレス (URL)」
を http://inaba-serverdesign.jp から https://inaba-serverdesign.jp に変更します。
 

2-3. WordPressデータの内部リンクの変更

固定ページやブログ記事内の http://inaba-serverdesign.jp で記述された内部リンクを置換します。
これは、参考記事と同様に、WordPressのSearch Regexプラグインを使用しました。

‘http://inaba-serverdesign.jp/’ を
(’https://inaba-serverdesign.jp/’ ではなく)’//inaba-serverdesign.jp/’ として、「Search」して変更内容を確認します。
→436件ありました。

確認後、「Replace & Save」で置換を実行します。
 

(2016.9.1追記)
SlideShareのスライドを記事中に埋め込んでいるページで、HTTPSとHTTPの混在でうまく表示されない箇所があったので
‘http://www.slideshare.net/’ を ‘//www.slideshare.net/’ として、置換しました。
(2016.9.1追記ここまで)

2-4. Nginxをreload

HTTPS化のひととおりの設定を行ったので、NginxをreloadしてHTTPSリダイレクト設定を反映します。

 # nginx -t
 # systemctl reload nginx

 

2-5. NginxのProxy Cacheを削除

NginxのProxy Cache設定を行っている場合は、キャッシュを削除します。
僕はNginx Cache Controllerプラグインを使用しているので、WordPress管理画面でキャッシュ削除を行いました。
 

3. HTTPS切り替え後の確認

3-1. ページ表示を確認

ここまでの設定で、WebサイトがHTTPSで表示できるようになっているはずです。
WebブラウザからWebサイトの表示を確認します。
HTTPでアクセスしたときに、自動的にHTTPSページにリダイレクトされることも確認します。

また、Google Chromeのディベロッパーツールで警告が表示されていないか、確認します。

うまく表示されないときは、Webブラウザに表示されるエラーメッセージや、サーバー上のWebサーバー(Nginx)のアクセスログ、エラーログのメッセージをヒントにして対応します。
 

3-2. 残っていたHTTPリンクをHTTPSリンクに変更

「2-3. WordPressデータの内部リンクの変更」で記事の内部リンクを置換しましたが、Google Chromeのディベロッパーツールでチェックしたところ、「Mixed Content:~」の警告がいくつか出ていました。

記事以外の部分、ロゴとフッターウィジェットエリアに、’http://inaba-serverdesign.jp/’ の内部リンクが残っていたので、
‘http://inaba-serverdesign.jp/’ を ‘//inaba-serverdesign.jp/’ に
変更しました。
 

3-3. ソーシャルメディアのシェア数保存設定

SNS Count Cacheプラグインで
「HTTPからHTTPSへのスキーム移行モード:有効」
とします。

この設定により、SNS Count Cacheプラグインが、疑似的にHTTPページとHTTPSページのシェア数を合計して表示してくれるようになります。
 

3-4. HSTS(HTTP Strict Transport Security)の設定

HSTSは「2回目以降のアクセスでHTTPのURLをブラウザに打ち込んでも、HTTPSでアクセスさせる仕組み」とのことで、その設定を行います。

 # vi vhost_ssl_inaba-serverdesign.jp.conf

--
...
    add_header Strict-Transport-Security max-age=15768000;
...
--

 # nginx t
 # systemctl reload nginx

 

※完全HTTPSサイトの場合は、この設定を行うと、Qualys SSL Labsによる SSL Server Testのレイティングがアップします。
 

4. 監視ツール、外部サービスの設定変更

監視ツールや外部サービスを使用していれば、あわせて変更します。
 

4-1. 死活監視サービスPingdomの監視URLを変更

ヘルスチェックURLを、’https://’ から ‘http://’ に変更します。
 

4-2. 死活監視ツールNagios設定変更

監視ツールNagiosでも、HTTPの死活監視を行っていたので、’https://’ から ‘http://’ に変更します。
また、SSLサーバー証明書の有効期限の監視を追加しました。

(参考)
・NagiosでSSLサーバー証明書の有効期限を監視
https://inaba-serverdesign.jp/blog/20150825/nagios_ssl_certificate_sni.html
 

4-3. AWS DNSフェイルオーバーの設定変更

AWS Route 53でDNSフェイルオーバーの設定を行っていたのですが、HTTPページに対してヘルスチェックを行っていたので、HTTPSページをチェックするよう変更します。

AWS Management Consoleでは、ヘルスチェックの既存エントリーでProtcolを変更できなかったので、HTTPSプロトコルでチェックする新しいヘルスチェックエントリーを作成し、Aレコードのヘルスチェックエントリーの紐づけを変更しました。
 

4-4. Googleウェブマスターツールの設定変更

Googleウェブマスターツールでは、サイトマップが必要なので、まず、HTTPSページのサイトマップを新たに作成します。
WordPress Google Sitemapプラグインを使用しているので、Settings 画面で
「create a new sitemap file or update the existing one」
で新しいサイトマップを作成します。

Webブラウザからサイトマップにアクセスして、サイトマップ内の各ページのURLが ‘https://’ となっていることを確認します。
https://inaba-serverdesign.jp/sitemap.xml

Googleウェブマスターツールは、HTTPサイトとHTTPSサイトを別に扱うので、新たにHTTPSサイトの登録を行います。
 

4-5. アクセス解析ツールAWStatsの設定変更

アクセス解析ツールAWStatsを使用している場合は、必要に応じて設定変更を行います。

僕はHTTPとHTTPSでアクセスログファイルを分けているので、2つのアクセスログファイルをマージして解析するよう変更します。
(HTTPSにリダイレクトしているので、リダイレクト情報が不要であれば、HTTPSのアクセスログファイルのみ解析するよう変更してもよいでしょう。)

また、ソーシャルメディアのシェア数保存のため、シェアボタンの表示でFont Awesomeアイコンを使用するようにすると、拡張子woff, woff2へのアクセスが生まれ、これらが「ページアクセス」としてカウントされるようになってしまいました。
拡張子woff, woff2へのアクセスは「ページアクセス」としてはカウントしないよう設定しました。

 # vi /usr/local/AWStats/cgi-bin/awstats.inaba-serverdesign.jp.conf

--
NotPageList="css js class gif jpg jpeg png bmp ico rss xml swf ttf eot woff woff2"
--

 

isdまとめ

自社WordPressサイトを完全HTTPS化したときの手順をまとめました。

SSLサーバー証明書の取得、WebサーバーNginxやWordPressの設定変更以外にも、関連して監視ツールやアクセス解析など、いろいろ作業がありました。

念のため、事前にサーバーをコピーして検証環境で手順を確認してから本番環境のHTTPS化に臨んだのですが、それでも、いくつか予期しないことが起きました。
コンテンツ量の多いWebサイトだと、移行時に数時間のダウンタイムは覚悟しておいたほうがよさそうです。

完全HTTPS化の効果ですが、まだ1週間も経っていないので「Googleの検索ランキングが上がった」とか「アクセス数が増えた」という目に見える効果はありません(笑)

Webページの表示速度については、HTTPSのせいか?ほんの少しだけ遅くなったような気がしますが、ソーシャルメディアのボタンとシェア数の表示を各SNSへの外部アクセスからSNS Count Cacheによる内部キャッシュへのアクセスに変更したので、TwitterやFacebookのアイコン表示待ちがなくなったのはよかったです。

次はHTTP/2対応にチャレンジしたいと思います。
 

(関連記事)
・Let’s EncryptでSSLサーバー証明書を取得してみた
https://inaba-serverdesign.jp/blog/20151217/lets-encrypt.html

・NagiosでSSLサーバー証明書の有効期限を監視
https://inaba-serverdesign.jp/blog/20150825/nagios_ssl_certificate_sni.html

・自社WebサイトをHTTP/2対応しました。
https://inaba-serverdesign.jp/blog/20160511/website_http2_nginx.html
 

Follow me!