さくらのクラウド ウェブアクセラレータとwp-sacloud-webaccel プラグインでWordPressサイトまるごとCDN配信(上級編)

さくらのクラウド ウェブアクセラレータとwp-sacloud-webaccel プラグインでWordPressサイトまるごとCDN配信(上級編)

2018年11月1日

前回の記事『WordPressサイトの負荷対策に!さくらのクラウド ウェブアクセラレータとwp-sacloud-webaccel プラグインで画像を手軽にCDN配信(初級編) 』では、WordPressサイト内の画像だけをCDN配信する方法を紹介しました。

しかし前回の方法ではWordPressやサーバ自体のアクセスを軽減できるわけではないので、アクセス集中でのいわゆる「バズ落ち」や、PHPの処理のせいで読み込みに時間がかかる場合への対処としては不完全です。
今回は、

  • 前回紹介した内容で、画像をCDN配信できた
  • 画像のキャッシュだけでは物足りない
  • アクセス集中でサイトが落ちた(レンタルサーバ側の制限を食らった)経験がある
  • ドメインレコードの書き換え権限がある

という方に向けて、WordPressサイトをまるごとキャッシュしてウェブアクセラレータから配信させる手順を紹介します。

実施前の注意

サイトまるごとCDN配信できるサイトは、けっこう条件が限られます。
自分のサイトが以下の状況にあてはまっていないかよく確認し、まずは多少ミスっても支障のない環境を用意してからやってみましょう。
ドメインレコード切替時に、場合により一時サイトがアクセス不可になることもありえます。大事なサイトでぶっつけ本番はおすすめしません。

  1. この方法はドメインのCNAMEレコードを編集しますので、自分でドメインレコードの編集ができない環境では導入できません。
    (例: CPI ACE01でドメインも一緒に管理しているなど)
  2. 公開サイトが「wwwなし」(ネイキッドドメイン)の場合もCNAMEを設定できないため、残念ながらこの方法は使えません。(一部のDNSサービスではできるところもあるようですが大多数は無理…)
    すでにwwwなしでインデックスされているサイトは、リスクを伴いますが少し時間をかけてwwwありでの運用に切り替えるか、初級編で紹介した画像等のみのCDN配信で運用してください。
  3. ドメインをさくらインターネットで取得していて、さくらのドメインメニューで管理している場合は、データが書き換えられない場合があるため、「さくらのクラウド DNS」等、別のDNSサービスの利用が推奨されています。
    詳しくはさくらインターネット 谷口さんのブログ記事の「DNS設定の変更」の欄を参照してください。
  4. JSやCSSはクライアントサイド処理なのでキャッシュされても動きますが、サーバサイドで動的に表示切り替えしている箇所がある場合は対応できません。
    (例えばレスポンシブじゃなくプラグインでPCとスマートフォンでテーマ切り替えしている場合や、ログインユーザーにより表示を変えている場合など。全員同じ表示になっちゃう、という困ったことが起こります。)
  5. SSL証明書を導入してサイトをHTTPSで運用している場合、ウェブアクセラレータ側に証明書を設定する必要があります。
    ここで使える証明書は、「他社サーバへの持ち出し」ができるものに限られます。
    しかし、レンタルサーバ標準の「無料独自SSL」は持ち出しができないものが多いので、有償の証明書を別途取得する必要があります。
    ただし、有料の証明書であっても、発行元によっては他社サーバへの持ち出しができない仕様になっています。
    (例えば、エックスサーバーさんの証明書は価格にかかわらず他社持ち出しが不可のため使えません)
    決してさくらさん1社を推す意図はないのですが、さくらのレンタルサーバの無料独自SSLの証明書はコントロールパネルからダウンロード可能なので、使えます。ちなみに、「さくらのSSL」は一番安価のJPRS DV認証でも持ち出しが可能ですので、使いやすいと思います。

     

    なお、現在エックスサーバーさんなど証明書持ち込み・持ち出しができないサーバを使っている場合、さくらのSSL取得時に必要なCSRは自力で作らなくてはいけません。
    JPRSのサイトに作成手順の説明ページがあります。ターミナルを使って、この中の「OpenSSL (新規/更新)」のPDFファイルの手順通りに鍵ペアとCSRを生成しましょう。



構成

今回の完成形はこのような構成になります。

ポイントとしては、

  • 公開用ドメイン(この例だと https://www.example.com)を、ウェブアクセラレータに向ける
  • 実際のデータ(WordPress本体や画像など一式)は、オリジンサーバ(この例だと https://origin.example.com ※サブドメイン部分は好きに決めていいし、別ドメインでもいい)に置く
  • オリジンサーバは、原則としてサーバ管理者とウェブアクセラレータ経由のアクセスに限定し、一般の閲覧ユーザーが直接アクセスしない想定

といったところです。

「オリジンサーバ」の「オリジン (origin)」という単語は「起源」や「源」という意味ですが、ここでは「大元のデータが置いてある場所」という意味です。
ウェブアクセラレータ(CDN)は、オリジンサーバのデータをキャッシュして閲覧ユーザーに見せます。キャッシュがない、もしくは許可されていなければ、オリジンサーバのデータをそのまま見せます。

手順1. オリジンサーバの設定

おそらくこの記事を読む方は、既存のサイトにCDNを導入するパターンの方が多そうな気がします。
ということで今回は、すでにレンタルサーバでWordPressサイト( https://www.example.com )を運用しているものとして話を進めます。

ほとんどのレンタルサーバをオリジンサーバとしてそのまま使用できると思いますが、各社の仕様によって若干やり方が異なります。
ドメインやサブドメインのドキュメントルートを自由に設定できるホスティングサービスと、そうでないサービスがあります。前者の例としてさくらのレンタルサーバ、後者の例としてエックスサーバーを挙げて説明します。

さくらのレンタルサーバの例

さくらのレンタルサーバの場合は、マルチドメイン設定時に、www以下のどこでも任意の場所をドキュメントルートに設定できます。
ですので、オリジンサーバ用のサブドメイン origin.example.com を作成した際、ドキュメントルートを www.example.com のルートと同じ場所に指定することで、データの移動をすることなくそのまま使えます。

エックスサーバーの例

エックスサーバーの場合は、ドメイン・サブドメインごとに領域が完全に分かれており、ドメイン追加時に自動でディレクトリが作成されます。ユーザー側でドキュメントルートを自由に変更することはできません。

そのため、オリジンサーバ用のサブドメイン origin.example.com を作成すると、
/example.com/public_html/origin/
というディレクトリが生成され、ここにデータを移す必要があります。

が、それはとても面倒ですしリスクも高い!
ということで、私はオリジンサーバ用のサブドメインは作らず、www.example.com の領域をそのままオリジンサーバとして使うことにしました。
ただし、 www.example.com はこの先の手順でCNAMEを変えた際にエックスサーバーから切り離されてしまうので、実際にはwwwなしの example.com を使うことになります。

手順2. ウェブアクセラレータの設定

途中までは前回「初級編」 と同じです。
今回はドメイン種別で「独自ドメイン」を選択します。

各設定項目はこのように。

「オリジンサーバ」の指定ですが、手順1. で origin.example.com を作成した場合と、「エックスサーバーの例」のように、example.com を使うことにした場合とで入力内容が異なるので注意してください。
「ホストヘッダ」は入力任意ですが、設定しないことでトップページでリダイレクトループが起こる現象を確認していますので(環境によるかもしれませんが)、公開ドメイン名を入れておきます。

登録が完了すると、「CNAME先|サブドメイン」のところに (固有の文字列).user.webaccel.jp. のサブドメイン名が発行されます。

手順3. SSL証明書の追加

前述の通り持ち出し可能な証明書を取得している必要があります。
証明書発行元から .crt ファイルか、それに準ずるものが発行されているはずなので、テキストエディタで開くと

——BEGIN CERTIFICATE——
[英数字たくさん羅列]
——END CERTIFICATE——

という内容になっていると思いますので、そのまま証明書欄にコピペします。
次に中間証明書を貼り付けます。「中間証明書なんかもらってないよ!」という場合も多いと思いますが、発行元のサイトにあるはずなのでよく探してください。

例えば、JPRS発行の証明書の場合、「JPRS 中間証明書」とかでググると中間証明書のダウンロードページが見つかります。

このページでダウンロードした .cer ファイルをテキストエディタで開き、同様にコピペします。

Let’s Encrypt の中間証明書はこちらのページからどうぞ。
執筆現在、「Intermediate Certificates」の「Let’s Encrypt Authority X3 (IdenTrust cross-signed)」を使えばよいはずです。

秘密鍵は、証明書発行のときに使ったものをエディタで開いて同様にコピペします。
「秘密鍵が正しいPEM形式ではありません。」というエラーが出たら、こちらの方法でPEM形式に変換した後、ペーストします。

なお、さくらのレンタルサーバを使用している場合は、証明書も秘密鍵もコントロールパネルからダウンロードできます。

さくらのウェブアクセラレータの Let’s Encrypt を使う場合の注意 ※2021.11.10 追記

2021年1月28日から、さくらのウェブアクセラレータでLet’s Encrypt を用いた無料・自動更新のSSL証明書が使えるようになりました。便利になりましたね!
ただし、アクセラレータのLet’s Encrypt では、www ありの証明書しか発行されません。www なしのドメインでもHTTPS接続したい、wwwなしのHTTPS → wwwあり にリダイレクトしたいという場合は、wwwなしのDNSが向いているサーバーの方でもSSL証明書を取得・設定しておく必要がありますのでご注意ください。

さらに注意点として、オリジンサーバにエックスサーバーを利用する場合、エックスサーバーの Let’s Encrypt は wwwあり、wwwなし 両方のAレコードがエックスサーバーに向いていないと使えません。(正確には、取得はできるけど更新ができない)
ですので、エックスサーバーが用意している有料独自SSLを契約して使うことになります(最安はCore SSLの年間1,100円)。

ここでさらなる注意点として、SSL申し込み時のコモンネームは、必ず「wwwあり」にすること。wwwありで申し込むと、wwwあり/wwwなし どちらも有効になります。wwwなしのみで取得すると、エックスサーバーの仕様上、wwwありでのアクセスが

「無効なURLです。
プログラム設定の反映待ちである可能性があります。
しばらく時間をおいて再度アクセスをお試しください。」

という画面になり、コンテンツを表示できなくなります。

手順4. ドメイン所有権の確認 (txtレコード追加)

ウェブアクセラレータの設定を有効化するため、ドメインの所有権の確認が必要です。
いきなり公開ドメイン名のCNAMEを変更しても有効化できますが、さすがに恐ろしいので、所有権の確認だけ先にやります。

ウェブアクセラレータの該当サイトの「設定」をクリックすると、
「ドメインの所有権を確認するため、 有効にする際は事前にサイトの公開ドメイン名のCNAMEを *********.user.webaccel.jp. と設定するか、TXTに webaccel=*********.user.webaccel.jp と設定してください。 」
と表示されていますので、この通りにします。

利用しているDNSサービスのレコード編集画面で、公開ドメイン名のtxtレコードを追記します。
私はムームーDNSを使っているのでこんな感じです。

お名前とか、他のサービスでもだいたい同じような感じのはずです。

txtレコードを追加後、ウェブアクセラレータ設定画面でサイトのステータスを有効に切り替えできればドメイン認証は成功です。
「設定の更新に失敗しました」と出る場合はDNSキャッシュのせいか、記述が間違っているので確認してみてください。

手順5. WordPressにwp-sacloud-webaccel プラグインを導入

ここは「初級編」と同じですので、そちらの説明を参照し、「APIキーの発行」とあわせて実施してください。

「キャッシュ設定」で、キャッシュ対象ページを設定します。
はじめは60秒とか短めの秒数で、トップページのみなど、影響範囲が少なそうな設定で試してみると良いですね。

手順6. 公開ドメインのAレコードを削除、CNAMEレコードを設定

いよいよ公開ドメイン www.example.com のトラフィックをウェブアクセラレータ経由に切り替えます。

なお、さくらのレンタルサーバの無料独自SSL(有料でもSNI SSLの場合は同様)を使っている場合は一時停止が必要です。
私のオリジンサーバはこの環境ではないため詳細確認が取れていませんが、お使いの方はさくらインターネット 谷口さんのブログ記事の「さくらのレンタルサーバ設定」の欄を参照してください。

再度ムームーDNSのセットアップ画面を開き、wwwのAレコードの記述を削除します。
あわせて、www にCNAMEレコードを追加し、値に「*********.user.webaccel.jp」を設定します。

ムームードメインの場合は、末尾の「.(ドット)」は自動的に付与される仕様なので、不要です。(ドットがあるとエラーで保存できない)
「.(ドット)」の自動補完があるか否かは使っているDNSサービスによるので、事前に確認しておきましょう。

ムームードメインのTTLは3,600秒(1時間)で固定ですので、1時間待てばウェブアクセラレータに向くはずです。

ブラウザのデベロッパーツールで確認して、Viaヘッダーが http/1.1 sv**-tky(osk)**-jp … というようなものになっていて、x-cache の項目が出ていればウェブアクセラレータ経由に切り替わっています。

何度かブラウザをリロードして、cache-control の項目で、s-maxage の値がプラグインの設定ページで指定した秒数に、x-cache の項目が HIT になれば、キャッシュ成功です!

手順7. WordPressのテーマ内のCSSや画像、静的ファイルなどもキャッシュする

wp-sacloud-webaccel プラグインの設定で「メディアファイルをキャッシュする (.htaccessファイルを利用します ) 」にチェックを入れた場合、 /wp-content/uploads/ 直下に キャッシュ指定用の .htaccessファイルが自動生成されます。
内容はこんな感じ。

# BEGIN wp-sacloud-webaccel
<IfModule mod_headers.c>
Header set Cache-Control "s-maxage=86400, public"
</IfModule>
# END wp-sacloud-webaccel

s-maxageの値に、管理画面で指定したキャッシュ秒数が入っています。

しかし、/wp-content/uploads/ 以下にあるファイル以外はキャッシュ対象となりません。
テーマ内で使用している画像やCSS,JSファイルもキャッシュさせたい場合は、wp-sacloud-webaccel プラグインが生成した .htaccessファイルをコピーして、/wp-content/themes/ に置いてあげればOKです。

他にも、WordPress外に静的ファイルを置いている場合などは、同様に.htaccessを設置しましょう。

手順8. 部分的にキャッシュ除外したい投稿・ページがある場合

除外対象の投稿で ‘sacloud_nocache’ というカスタムフィールド名で、値に ‘1’ を指定して保存します。

※除外機能は私が対応した案件でどうしても必要になったため機能追加して、後日本家にマージしてもらったものです。

本当はチェックボックスとかで指定できると良いのでしょうが、UIを作るところまでの余裕がなかったので、今はカスタムフィールドに手書きしてもらう形になっています。
だれかUI作ってくれると嬉しいな!!

その他の注意事項

  • wp-sacloud-webaccel プラグインを使う場合、谷口さんの記事に書かれている「キャッシュ設定」「phpファイルのキャッシュ有効化」の内容はプラグインがよしなにやってくれるため実施不要です。
  • ちなみにWordPressには nocache_headers() というキャッシュを無効にするヘッダーを出力する関数が用意されていて、管理画面側ではデフォルトでこの関数が実行され、"cache-control: no-cache, must-revalidate, max-age=0" が返るようになっています。
    他にもメールフォームや会員管理的なことをやるプラグインがこの関数を使って意図せぬキャッシュを防いだりしていることがあります。(例えば、Contact Form 7やMW WP Formなどで使われてます)特定の画面を自前でキャッシュ対象外にしたい際は、nocache_headers関数を実行してあげましょう。
  • .htaccessで静的ファイルのキャッシュ秒数を指定する場合、s-maxage で秒数を指定します。max-ageと書いてしまうと適用されません。
  • 今回はオリジンサーバのすべてのトラフィックをウェブアクセラレータに流す構成になっているので、管理画面など、キャッシュ対象でないページのアクセスも課金対象になります。
    これを防ぐには、管理画面はオリジンサーバのドメイン(https://origin.example.jp/)でアクセスできるようにしておくなどの工夫が必要です。
    が、それなりに面倒ですし、関係者のトラフィック量など知れてますし、別にいいかなと思っております。

ニッチなハマりポイント(関係ない人も多いかも)

  • オリジンサーバのドメインと公開ドメインが異なる場合、末尾のスラッシュ(トレイリングスラッシュ)なしで公開ドメインにアクセス時、オリジンサーバへリダイレクトされる現象が発生した
    → WordPressのパーマリンク末尾にスラッシュが含まれている場合は発生しない(例)/%postname%/
    → パーマリンクの末尾にスラッシュがない場合は発生 (例)/archives/%post_id%
    この現象は他のCDNでも発生するようです
    ※参考サイトはCloudFrontの事例ですが、現象としては同じでした。

この記事ではmod_rewriteで対応していますが、私が遭遇したケースでは、ウェブアクセラレータの設定画面の「ホストヘッダ」に公開ドメインを入れ、クラウドサーバの.confファイルのVirtualHostの設定のところも、ServerNameで公開ドメイン指定する記述を追記することで解消しました。

<VirtualHost *:443>
DocumentRoot /www/origin/htdocs
ServerName www.example.com
</VirtualHost>

もっとニッチなハマりポイント

ヘッダーにcache-controlの値は正しく入っているけど、なぜか全ページpragma: no-cacheも一緒にくっついてきて、全然キャッシュが有効にならない問題が発生していました。
そのサイトに入っていた「Global Content Blocks」というプラグインが、なぜかinitフックっていう、ログインしてなくても漏れなく使われるフックを使ってsession_startしていたため、強制キャッシュ無効に。。。
そのプラグインの役割的に、全ユーザーに対しセッション管理が必要な理由が見当たらなかったため、処理を削除して対応しました。
当該プラグインはすでに公開停止されており、新規での導入は非推奨です。

参考サイト