Iruca Log

Iruca Log

東京に住むWeb系エンジニアによる技術&雑記ブログ

SNSでフォローする!

AWS EC2上のApache HTTPDでHTTP/2に対応する方法まとめ

f:id:iruca21:20170802214118j:plain

こんにちは、irucaです。
最近HTTP/2の機能が気になってきたので自分のサーバでサクッと試してみました。

AWSのEC2インスタンスを使って、Amazon Linuxで動かしています。
CentOS6でも同じ操作になるかと思います。

[root@ip-172-31-25-63 conf.d]# cat /etc/system-release
Amazon Linux AMI release 2017.03

まずHTTP/2の機能を試す前提として、HTTPSで自分のサーバにアクセスできるように準備が整っている必要があります。
www.iruca21.com

こちらの記事を参考に、HTTPS用のSSL証明書作成などを終えておきましょう。


mod_http2有効化のためのhttpdビルド

webサーバとしてApache httpd 2.4 を使う前提で書いています。
自分の前の記事でhttpd24をインストールさせておいて心苦しいですが、

残念ながら私が調べたところ2017年8月現在yumなどのパッケージ管理ツールを使ってApache httpd上でhttp2を簡単に有効化する方法はないです。
mod_http2をインストールすることを念頭に、Apache httpd2.4の最新版をソースからビルドしていく方法をとります。


色んな記事を調べた結果、Amazon Linux上からやる人は下記の記事がもっともハマりポイントが少なく、
最短でhttpdをビルドできました。
blog.apar.jp


この記事で詰まるところがあるとすれば、すでにhttpd v2.4.23は脆弱性が発見されたためアップロードされておらず、
wget http://ftp.riken.jp/net/apache//httpd/httpd-2.4.23.tar.gz
の箇所を
wget http://ftp.riken.jp/net/apache//httpd/httpd-2.4.27.tar.gz

など、最新のバージョンに変更する必要があるくらいです。


こちらを参考に、openssl1.0.2, nghttp2, apr, apr-util, httpdと順を追ってビルド、インストールしていきましょう。
少なくとも私のAmazon Linuxでは全くつまづくことなくhttpdインストールまではできました。

httpd設定

インストールはできましたが、httpd起動・終了やその他細々とした設定がまだできていません。
下記の手順を参考にしながら自分なりにチューニングしてみてください。

httpdにパスを通す

上記手順通りにやれば /usr/local/apache2/ 配下にソースからビルドしたhttpdがインストールされているかと思います。

まずはインストール先のhttpdをPATHに通しておきましょう。

echo "export PATH=\$PATH:/usr/local/apache2/bin" > /etc/profile.d/httpd2-4-27.sh
source /etc/profile.d/httpd2-4-27.sh

サービス起動・終了スクリプトなどを作る

yum install httpd24
でhttpdをインストールしたたときには、ソースコードをビルドしたものだけでなく、サービス起動・終了用のスクリプトやlogrotateの設定、デフォルトのhttpd.confの設定などが入りますが、ソースからビルドしてインストールしたときにはそういったものが入りません。

yumでインストールしたとき相当のファイルも欲しいひとは、下記の方法でhttpdのRPMパッケージに含まれているファイルが得られるのでローカルに移動しましょう。

mkdir /tmp/httpd24-test
cd /tmp/httpd-24-test

yum install yum-utils
yumdownloader httpd24

# rpmの中身をカレントディレクトリに展開
rpm2cpio httpd24-2.4.25-1.68.amzn1.x86_64.rpm | cpio -id

# 必要に応じてファイルを移動させる
cp etc/rc.d/init.d/httpd /etc/rc.d/init.d/
cp etc/logrotate.d/httpd /etc/logrotate.d/


サービススクリプト(/etc/init.d/httpd)がエラーはかなくするために、

ln -s /usr/local/apache2/bin/httpd /usr/sbin/httpd

でシンボリックリンクを張り、
/etc/init.d/httpdを開いて
pidfile=から始まる行を
pidfile=${PIDFILE-/usr/local/apache2/logs/${prog}.pid}
に変えておきましょう。



/etc/httpdに設定ファイル用シンボリックリンクを作成

/usr/local/apache2 配下の設定ファイルがデフォルトで読まれるようになっているのでそちらを常に変更する癖をつけてもよいのですが、
/etc/httpd/ 配下を読む癖がついている人も多いと思うのでシンボリックリンクを張っておきます。
すでに /etc/httpd/conf, /etc/httpd/conf.d ディレクトリができてしまっている人は一度よけておいて、シンボリックリンクの先にファイルを移動させましょう。

ln -s /usr/local/apache2/conf /etc/httpd/conf
ln -s /usr/local/apache2/conf.d /etc/httpd/conf.d

/etc/httpd/conf/httpd.conf修正

ソースに付属しているhttpd.confは何かとハマりポイントが多いので先にhttpd.confの下記ポイントを編集してしまいましょう。
/etc/httpd/conf -> /usr/local/apache2/conf へのシンボリックリンクは張り終えている前提です。

#LoadModule ssl_module modules/mod_ssl.so
#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so

の行のコメントアウトをそれぞれ外します。

DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">

の2行を

DocumentRoot "/var/www/html"
<Directory "/var/www/html">

に変更します。
コンテンツを /usr/local/apache2/htdocs に配置する癖をつけてもいいですが、
これもyumなどで今まで入れていた人向けの配慮です。


/etc/httpd/conf.d/ssl.conf

すでにhttpd 2.4をyumなどでインストールしていた状態からソースコードビルドを試した人は、
/etc/httpd/conf.d/ssl.confにすでにファイルがあり、
httpd起動時にこいつの中の文法がエラーになってしまうかと思います。

SSLPassPhraseDialog: file '/usr/libexec/httpd-ssl-pass-dialog' does not exist

と怒られることがあるので、とりあえずssl.confの中を

SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog

SSLPassPhraseDialog builtin

と書き換えましょう。

こちらを参考にしました。
norm-nois.com


ちなみに私はapp.iruca21.comというドメインをHTTP/2テスト環境として整えようとしています。
ドキュメントは/var/www/html/http2/に置くことにします。
その場合、/etc/httpd/conf.d/ssl.confの中身は以下のようになっています。

Listen 443 https

SSLPassPhraseDialog builtin
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

<VirtualHost _default_:443>

ServerName app.iruca21.com:443
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3
SSLHonorCipherOrder on

SSLCertificateFile /etc/letsencrypt/live/app.iruca21.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/app.iruca21.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

Protocols h2 http/1.1
H2Direct on

<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>

BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

# check if http2 is working...
DocumentRoot /var/www/html/http2/
<Directory /var/www/html/http2/ >
    Options Indexes FollowSymLinks MultiViews
    AllowOverride FileInfo AuthConfig
    Order allow,deny
    allow from all
</Directory>

</VirtualHost>

ブラウザから信頼されるSSL証明書をすでにこちらの記事で設定済みです。



コンテンツを配置してみる

試しにこちらのページを参考に、bootstrapを使ったサンプルコンテンツを配置してみます。
techacademy.jp


index.htmlの中身はこんな感じです。

<html>
<head>
  <title>hello http2 world</title>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- BootstrapのCSS読み込み -->
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <!-- jQuery読み込み -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <!-- BootstrapのJS読み込み -->
  <script src="js/bootstrap.min.js"></script>

</head>
<body>

<h1> Hello, HTTP/2 world!</h1>

</body>
</html>


bootstrapをダウンロードしてcss, jsフォルダ内にそれぞれ配置します。
結果として以下のような感じになりました。

[root@ip-172-31-25-63 http2]# pwd
/var/www/html/http2
[root@ip-172-31-25-63 http2]# ls -al
total 24
drwxr-xr-x 5 root root 4096 Aug  1 17:29 .
drwxr-xr-x 9 root root 4096 Aug  1 00:36 ..
drwxr-xr-x 2 root root 4096 Aug  1 12:51 css
drwxr-xr-x 2 root root 4096 Aug  1 12:51 fonts
-rw-r--r-- 1 root root  567 Aug  1 13:04 index.html
drwxr-xr-x 2 root root 4096 Aug  1 12:51 js

起動してブラウザからアクセスしてみる

さて、準備は整ったので設定ファイルの文法を確認してからhttpdを起動して、
ブラウザからアクセスしてみます。

[root@ip-172-31-25-63 http2]# httpd -t
Syntax OK
[root@ip-172-31-25-63 http2]# service httpd start
Starting httpd:                                            [  OK  ]

ちゃんとHTTP/2でアクセスできてるかどうかのChromeでの確認方法はこちらを参考にします。
CloudFrontでHTTP2対応する方法とChromeでの確認方法 - Qiita


さて、どれどれ…

f:id:iruca21:20170802213520g:plain

おお、ちゃんとh2(http2)になってる。
満足だ。

みなさんも自分のウェブサイトをHTTP/2に対応するときの参考にしてみてください。