yuw27b’s blog

技術メモと雑記

CADDYで手軽にHTTP/2サーバを立てる

CADDYとは

公式サイト
Caddy - The HTTP/2 Web Server with Fully Managed TLS

GitHub
GitHub - mholt/caddy: Fast, cross-platform HTTP/2 web server with automatic HTTPS

公式サイトから抜粋:

  • Windows, Mac, Linuxと、Androidで動く
  • Apacheやnginxのような細かな設定はできないかわりに、設定に関する専門知識は不要
  • 静的なファイルのサーブを主目的にしていて、環境の移行も簡単

ローカルでちょっとテストするのに使えるかなー、と思って興味を持ったのですが、
もう少し本格的なサーバなのかも?という印象。
HTTP/2で動かすのは本当に簡単で、PHPもHTTP/2でサービスさせることができました。


以下、Macでの設定〜起動までの手順です。
※他のOSでは試していませんが、サーバ自体が実行ファイル形式になっているので、基本的には同じような方法で動かせるのではないかと思います。

ダウンロードとインストール

Download Caddy
本体の「Caddy Core」をダウンロードします。

f:id:yuw27b:20151108212649p:plain

ダウンロードしたフォルダ直下にある「caddy」が実行ファイルです。
好きな場所に置いて、シェルからコマンドを実行できるようにパスを通しておきます。

ターミナルから、サーバのドキュメントルートにしたいディレクトリに移動して、

$ caddy

でサーバが起動します。
デフォルトでは「2015」番ポートを使うようになっているので(来年になったら変わるとか?)、ブラウザで「http://localhost:2015/」にアクセスしてみます。
「index.html」があればその内容が表示されるはずです。なくても「404 Not Found」が出ていればサーバは動いています。
f:id:yuw27b:20151108212725p:plain
↑デフォルトの404画面はすごくシンプル。

HTTP/2でサービスさせるために、SSLの設定をする

HTTP/2に対応させるにはSSLの設定をして、HTTPSを使用する必要があります。

2017年2月追記:
CADDYに、自動的に自己証明書を生成するオプションが追加されましたので、テスト用途であれば以下の証明書の準備は不要になりました。便利です!
公式ページ:tls - Caddy Directives (追記ここまで)

今回は、ローカルのテストサーバということでセキュリティは考えずに、opensslで自己証明書を用意します。

※証明書について詳しいことは省きますが、以下が参考になりました:
オレオレ証明書をopensslで作る(詳細版) - ろば電子が詰まっている
OpenSSLコマンドによる公開鍵暗号、電子署名の方法 - Qiita

鍵ファイルを置きたいディレクトリに移動してopensslのコマンドを実行します。

$ openssl genrsa -aes128 -out server.key 2048
$ openssl req -new -key server.key -sha256 -out server.csr
$ openssl x509 -in server.csr -days 365 -req -signkey server.key -sha256 -out server.crt

※openssl reqのところで、いろいろ入力項目が出てきますが、パスワード以外はすべて空欄のままで問題ありませんでした。

これで鍵セットは完成ですが、暗号化されたままだとうまく動かなかったので、キーを復号したものも作りました。

$ openssl rsa -in server.key -out server.noencrypt.key

これでSSLの準備は完了です。
(※復号化しないと動かなかったのは、何かミスっているような気もするのですが、ローカルサーバなので追求していません。)

とりあえず、サーバもSSL keyもコンテンツもこんな感じで一ヶ所にまとめました。

f:id:yuw27b:20151108213106p:plain

もちろんどこに何を置いてもいいのですが、まとめておいたほうがパスの指定などがやりやすいかな、という印象です。

caddyfileを用意して細かな設定をする

CADDYでは「caddyfile」というテキストファイルに様々な設定を記述することができます。
設定可能な項目は公式サイトの以下のページにまとまっています。かなりたくさんあります。
The Caddyfile - Caddy

シンプルなHTTP/2(HTTPS)のローカルサーバの場合:

localhost:2015 {
  tls ./sslkey/server.crt ./sslkey/server.noencrypt.key
  root ./public/
}

毎回ドキュメントルートに移動してサーバを起動するのも面倒なので、「root」をcaddyfileに記述しました。
※caddyfile内に記述するパスは、カレントディレクトリからのパスです。上の例では相対パスになっていますが、もちろん絶対パスでも大丈夫です。

2017年2月追記:
CADDYに自己証明書を自動生成させる場合は、

  tls self_signed

と記述します。(追記ここまで)

caddyfileを保存したら、ファイルの内容をcaddyに渡して実行します:

$ caddy -conf="/path/to/Caddyfile"

もしくは、

$ cat Caddyfile | caddy

ブラウザから、今度は「https://localhost:2015」にアクセスしてみます。(証明書の警告が出ると思いますが、無視して接続を選択します。)
f:id:yuw27b:20151108213220p:plain

ブラウザが対応していれば、HTTP/2での接続になっているはずです。
ChromeのDevToolsで見てみると、「Protocol」のところが「h2」となっているのが確認できます。
f:id:yuw27b:20151108213238p:plain


HTTP/1.1 vs HTTP/2

簡単なテストとして、画像を10枚配置したHTMLを作ってアクセスしてみました。
上がHTTP/1.1で下がHTTP/2です。HTTP/2では10枚が並列に読み込まれています。

f:id:yuw27b:20151108213259p:plain
(ローカルサーバにしては時間がかかっていますが、差が分かりにくいのでブラウザのほうでわざと速度を落としています。)

FastCGIを使う

CADDYでは、そのままでは静的なファイルのサーブしかできませんが、リクエストをFastCGIにプロキシすることで、PHPの実行が可能になります。
fastcgi - Caddy Directives

まず、PHPFastCGIマネージャであるphp-fpmを起動しておきます。
php-fpmが9000番ポートでサービスしている場合、caddyfileを以下のように記述します。

localhost:2015 {
  tls ./sslkey/server.crt ./sslkey/server.noencrypt.key
  root ./public/
  fastcgi /api 127.0.0.1:9000
}

この設定では、「/api」以下のリクエストを、FastCGIにプロキシします。

phpinfo()を呼び出すと以下のようになりました。
f:id:yuw27b:20151108213315p:plain


おわりに

テストサーバとしてやりたかったことはこれで全部できたので、ひとまずここまで。

処理速度やどのくらいのトラフィックをさばけるのか、というパフォーマンス面と、まだいろいろなことができそう、という機能面を、もう少し調査できたらまた続編を書いてみたいと思います。