このエントリはMagento Advent Calendar 2017の1日目です。

Magento2系を稼働させる環境を作る際に、切っても切れない関係にあるものがVarnishです。
今回はこのVarnishのバージョン5.2系と、Varnish謹製のSSL/TLSフロントエンドのHitchを使って、HTTP/2に対応した環境を作ってみましょう。

なお、弊社では普段Ubuntu Linuxを使っています。CentOSやRedHat Enterprise Linuxをお使いの方は適当にここから先の内容を読み替えて進めてください。各種コマンドなどは全てUbuntu Linux 16.04 LTSで実行したものを記載しています。

今回作成する構成

今回作成する構成は次の図のような構成です。
サーバー1台の中に以下のプロセスを同居させる形なので、あまり低スペックでないほうが良いでしょう。

サーバーの構成

本格稼働させる環境の場合は、最低でもMySQLくらいは別サーバーに切り出したいところですが、今回はお試しなので良いことにします。 

用意するのもの

最初に用意するものを確認しておきます。
少なくとも以下の2つは必要です。

  • 適当なスペックのサーバー(グローバルIPを持っているものならなんでも)
  • 適当なホスト名(DNSに設定済みであること)

それでは環境を作っていきましょう。

とりあえずMagentoが動く環境を作る

まず最初に、Magentoが動く環境を作ります。
これは以下の記事を参考にするとスムーズに行くでしょう。

 

Magentoを動かすだけであればVirtualBoxとVagrantで作っても構いませんが、今回のメインはその話ではないので割愛します。

HitchとVarnishをインストールする

Ubuntu LinuxにももちろんHitchやVarnishのパッケージは用意されているのですが、バージョンが少し古いものしか用意されていません。
今回はHTTP/2に対応したバージョンを使いたいので、Hitchは1.4系、Varnishは5.2系を使用します。

Varnishのインストールと設定

Varnishの公式リポジトリは、PackageCloudにあります。
Quick Installで指示されているとおり、

curl -s https://packagecloud.io/install/repositories/varnishcache/varnish5/script.deb.sh | sudo bash

を実行し、パッケージをインストールします。

設定ファイルをMagentoからダウンロードする

Varnishが無事にインストールできたら、次は設定を行います。
Varnishを動かす場合、Varnishそのものの設定ファイルを調整する必要があります。独自のシステムやVarnishを想定していないパッケージの場合、この設定ファイルを自力で作成する必要がありますが、現在のMagentoはVarnishの仕様を想定しているので、管理画面から簡単に設定ファイルをダウンロードできます。

設定ファイルのダウンロードは、Magentoの管理画面の「店舗>設定」でアクセスできるシステム設定画面の「システム」セクションにある「フルページキャッシュ」で行います。

Varnish設定ファイルのダウンロード

標準状態では「内蔵キャッシュ」になっているところを「Varnish キャッシュ」に変更すると、「Varnish設定」という項目が出てきます。
ここでVarnishのバージョンに合わせた設定ファイルがダウンロードできます。

なおMagento2.1と2.2ではサポートするVarnishのバージョンが少し異なりますが、Varnish4系の設定ファイルをVarnish5系で使っても問題なく動作します。

設定ファイルを設置する

ダウンロードした設定ファイルをサーバーの以下の場所に配置します。

/etc/varnish/default.vcl

次に、プロセスを起動・停止・再起動などさせるスクリプトを用意します。

/etc/systemd/system/varnish.service

がある場合は、viエディタなどで開きます。もしファイルがない場合は、

/lib/systemd/system/varnish.service

からコピーして配置してください。

このファイルにはVarnishの起動設定が書いてあるのですが、以下の箇所を変更しておきます。

変更前:ExecStart=/usr/sbin/varnishd -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m
変更後:ExecStart=/usr/sbin/varnishd -a :80 -a :81,PROXY -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m -p feature=+http2

この例では、Varnishを80番と81番ポートで待ち受けさせています。
81番の方はPROXY Protocolで待機させ、Hitchから流れてくるデータを処理します。
また、featureでhttp2を有効にしています。このオプションを付けることで、HTTP/2がVarnish上で有効になります。

変更できたら以下のコマンドを実行し、設定ファイルの内容をsystemdに認識させます。

sudo systemctl daemon-reload varnish

Apacheのポート番号を変える

Varnishを起動させる前に、Apacheのポート番号を変えておきます。
標準の設定ではApacheは80番ポートで起動しますが、Varnishが80番ポートを使うので、Apacheは8080番ポートで起動させます。

Ubuntu Linuxの場合は

/etc/apache2/ports.conf

に待ち受けポート番号が書いてあります。
さらに、

/etc/apache2/sites-enabled/<Magento用のconf>

にあるバーチャルホストの設定にもポート番号が書いてあります。この両方を8080に変えておきましょう。

変更できたらApacheを再起動し、続いてVarnishを起動させます。
設定に不備がなければApacheとVarnishが両方とも起動するはずです。

Hitchをインストールする

次はHitchをインストールします。記事執筆時点ではHitchのUbuntu Linux 16.04用のパッケージは

https://launchpad.net/~davividal-s/+archive/ubuntu/backports

でしか見つかりませんでした。ソースからコンパイルしてもいいのですが、今回は手軽に試したいので、このリポジトリのパッケージを利用します。

リポジトリの追加

リポジトリの追加はお作法通りです。

sudo add-apt-repository ppa:davividal-s/backports
sudo apt-get update

と実行すれば基本的にはOKです。

Hitchのインストール

リポジトリが正しく追加できていれば、

sudo apt-get install hitch

でHitchがインストールできると思います。うまくインストールできたらHitchの設定を行います。

設定ファイルの調整

Hitchの設定ファイルは2つあります。

/etc/systemd/system/hitch.service
/etc/hitch/hitch.conf

前者はVarnishと同じところに元ファイルがあるのでコピーします。
後者のファイルは以下のような記述にしておきます。

frontend = "[*]:443"
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: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"
tls-protos = TLSv1.0,TLSv1.1,TLSv1.2
prefer-server-ciphers = on
sni-nomatch-abort = on
backend = "[127.0.0.1]:81"  
write-proxy-v2 = on
workers = 2
backlog = 1024
keepalive = 3600
syslog = on
user = "nobody"
pem-file = "/etc/letsencrypt/live/<ドメイン名>/hitch-bundle.pem"
daemon = on
alpn-protos    = "h2, http/1.1”

ここで重要なのは、

alpn-protos= "h2, http/1.1"

というところです。
この記述を書かないと、HitchがHTTP/2で動作しません。Ubuntu Linuxで標準として使えるHitchはバージョン1.1で、この設定が利用できません。
そのため今回は1.4系を使用したわけです。

VarnishとApacheの設定変更

続いてHitchと連携できるようにVarnishとApacheの設定を変更します。

Varnishの設定ファイルに追記

Varnishの設定ファイルの52行目あたりに以下の追記を行います。

set req.http.x-forwarded-proto = "https";
変更後はVarnishを再起動しておきましょう。
Apacheの設定ファイルに追記

Magentoを動作させるApacheのバーチャルホスト設定

/etc/apache2/sites-enabled/<Magento用のconf>

に以下の内容を追記します。

SetEnvIf X-Forwarded-Proto https HTTPS=on
SetEnv https HTTPS=on

追記できたらApacheを再起動しておきます。

この設定を行う意味

Hitchを通すとHTTPS通信は全てHTTP通信として暗号化が解除された状態でVarnishやApacheに流れます。
それ自体は望ましいのですが、Magentoと組み合わせる場合は少し具合の悪い点があります。

Magentoは流れてきたリクエストがHTTPなのかHTTPSなのかでベースURLのどちらを使うかを判断します。
この判断は以下のPHP上の変数を用いて行っています。

$_SERVER["HTTPS"]

この値が on であるとき、Magentoは通信がHTTPSで行われたものと認識します。たとえそれが443番ポートに来たものでなくとも、前段階でHTTPS通信が解除されたと認識してくれます。
反対に、この値が off である場合は、通信がHTTPSだったとしてもHTTPであるものとみなします。

MagentoのベースURLがすべて "https://" ではじまるURLになっていた場合、Magentoは正しいURLにブラウザを誘導しようとするため、自動的にリダイレクトが起きます。
ところがリダイレクト後でも同じことが繰り返されてしまうため、リダイレクトの無限ループが起きてしまい、サイトに全くアクセスできなくなります。

この問題を回避するために、先程の設定を行うわけです。常時HTTPS化が求められている現在においては、この内容で多少余分に書き過ぎであっても目的を果たすことができます。
また、今回の最終目的であるHTTP/2での通信は多くのブラウザでHTTPS通信が前提として実装されていることも見逃せないポイントです。

Let’s Encryptで証明書を取得する

仕上げにSSL証明書を取得します。
お試しなのでLet's Encryptを使います。

certbotのサイトに書いてあるチュートリアルに従ってcertbotをインストールします。
下記のコマンドを叩いていけばインストールできると思います。

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-apache 

Apacheだけであればこのままcertbotで取得できるのですが、Hitchは一工夫加える必要があります。
というのもHitchは前述の設定ファイルをみていただければ分かる通り、SSL証明書に関する設定は1行しかありません。
Apacheであれば、証明書と中間証明書、秘密鍵の3行がありますが、Hitchはこれらを1つにまとめたファイルを使用します。

Varnish公式のチュートリアルを参考にする

有難い事にVarnish公式サイトにはHitchとLet's Encryptを使うチュートリアルが公開されています。
CentOS7用ですが、パッケージのインストール以外はUbuntu Linuxでも使えるので、この内容を参考にしましょう。

Varnishの設定にcertbot用の記述を追加

最初にVarnishの設定ファイルを改造し、certbotに対応させます。

/etc/varnish/default.vcl

に次の内容を書き込みます。

backend certbot {
    .host = "127.0.0.1";
    .port = "888";
}

〜中略〜

sub vcl_recv {

〜中略〜

    if (req.url ~ "^/.well-known/acme-challenge/.*") {
        set req.backend_hint = certbot;
        return(pass);
    }

〜中略〜

}

sub vcl_recv のところは既に default.vcl にあるはずなので、単純に追記でOKです。
backend certbot は新しく書き込んでください。

書き込めたらvarnishを再起動しておきます。

Hitch用のフックスクリプトを用意

Let's Encryptの証明書をHitchが利用できるように1つのファイルに纏めるスクリプトを用意します。

/usr/local/bin/hitch-renew-hook

を作成し、次の内容を書き込みます。

#!/bin/bash
# Full path to pre-generated Diffie Hellman Parameters file
dhparams=/etc/hitch/dhparams.pem

if [[ "${RENEWED_LINEAGE}" == "" ]]; then
    echo "Error: missing RENEWED_LINEAGE env variable." >&2
    exit 1
fi

umask 077
cat ${RENEWED_LINEAGE}/privkey.pem \
${RENEWED_LINEAGE}/fullchain.pem \
${dhparams} > ${RENEWED_LINEAGE}/hitch-bundle.pem

作成したら実行権を与えておきます。

sudo chmod a+x /usr/local/bin/hitch-renew-hook

このスクリプトは、 dhparams.pem というファイルを使用します。
次のコマンドで簡単に作成できるので、作成しておきましょう。

sudo openssl dhparam 2048 -out /etc/hitch/dhparam.pem

certbotで証明書を取得

さて、最後に certbot で証明書を取得しましょう。
certbot コマンドに幾つかパラメータを渡してやることで、証明書を取得できます。

sudo certbot certonly --standalone --preferred-challenges http \
--http-01-port 888 -d <取得したいホスト名> \
--renew-hook="/usr/local/bin/hitch-renew-hook" \
--post-hook="service hitch reload"

フックスクリプトが自動的に証明書や秘密鍵を1ファイルにまとめて配置し、Hitchをリロードします。

これでSSL証明書が手に入りました。

ブラウザでアクセスして、HTTP/2で通信していることを確認する

最後に動作チェックです。
ブラウザの開発者ツールでアクセスし、HTTP/2で通信していることを確認しましょう。

HTTP/2での通信確認

うまくHTTP/2で通信できているようです。
アンチウイルスソフトなどの関係でうまくHTTP/2にならないことがあるケースが報告されています。
もしうまくいかない場合は、一時的にアンチウイルスを止めてみると良いかもしれません(ずっと止めるのはダメですが)。

まとめ

Hitch1.4とVarnish5.2を使ってHTTP/2でコンテンツを配信できるMagento環境の構築手順をご紹介しました。
HTTP/2は従来のHTTP1.xよりも通信効率が良くなるように設計されているため、モバイル端末や常時HTTPSを意識する際には無視できない要素です。

さて、明日は2日目です。kzkick2ndさんによる、「Magento2開発環境構築2017冬」です。お楽しみに。