Help us understand the problem. What is going on with this article?

CentOS7にapache2.4とphp7.2(RC)とmysql8.0.3(RC)をインストールしてhttp/2で通信する

More than 1 year has passed since last update.

おことわり

この記事は、あんまよくわかってないことにチャレンジしてみた結果の備忘録です。
あまりよくないやり方とか、間違ってる内容が含まれる可能性がありますので、参考にされる際はご注意ください。:bow_tone1:
※むしろ、ここはこうしたほうがいいよとかそういう指摘ございましたら是非

また、作業をある程度自動化できるように、シェルコマンドの羅列には行の最後に && \ を追記しています。
シェルスクリプトにまとめるか、Dockerfileにしちゃえばって話な気もするけど、それはまた別途。

モチベーション

  • 新しい技術に触れてみたい
  • 普段yumでしかやらないので、configureとかmakeとかよくわかってない
  • 台風

環境

  • OS:CentOS7(CentOS Linux release 7.3.1611 (Core))の上にたてたCentOS7(CentOS Linux release 7.4.1708 (Core))
# docker images | grep "centos"
centos              latest              196e0ce0c9fb        6 weeks ago         197MB

以下のシェルスクリプトを実行すると、上のcentosイメージを使ってランダムな名前を付けた使い捨てのCentOSコンテナを建てて、そこにシェルログインする。このコンテナ上でインストールや動作確認などを実施。

centos.sh
#!/bin/bash

CONTAINER_NAME=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n1)

docker run --privileged --name ${CONTAINER_NAME} -d centos /sbin/init
docker exec -ti ${CONTAINER_NAME} bash

最終的に手動でインストールしたもの、バージョン

インストールする順番に上から並べる。

名前 バージョン prefix DLページ 備考
OpenSSL 1.0.2l /opt/openssl https://www.openssl.org/source/ 言わずもがな、オープンソースのSSL通信用ライブラリ
nghttp2 1.27.0 /opt/nghttp2 https://github.com/nghttp2/nghttp2/releases/tag/v1.27.0 http2のライブラリ。apacheでhttp/2で通信するために利用する。
curl 7.56.1 /opt/curl7-56 https://curl.haxx.se/download.html http/2での通信の動作確認に使う。CentOSにデフォルトでインストールされているバージョン(7.29.0)だとhttp/2のエクステンションが使えないので、最新をインストールしなおす。
apr 1.6.3 /opt/apr https://apr.apache.org/download.cgi apacheをインストールするのに使う。ApachePortableRuntime
apr-util 1.6.1 /opt/apr-util https://apr.apache.org/download.cgi 上同
apache 2.4.29 /opt/httpd24 https://httpd.apache.org/download.cgi#apache24 apacheの最新。http/2で通信する(mod_http2を有効にする)には、2.4.14以降が必要
mysql 8.0.3-0.1.rc /var/lib/mysql https://dev.mysql.com/downloads/mysql/8.0.html mysqlの最新。どうもRHEL向けにはrpmしか配ってないようなので、rpmを使う。
php 7.2.0RC4 /opt/php7 https://downloads.php.net/~pollita/ phpの最新。10/26時点でRC5が最新。11/30にGA予定

上記以外でインストールに必要なものは、yumでがつっとやる。

手順

dockerイメージを建ててシェルログイン後から。
なお、インストール以外に必要な作業は今回は省く(時刻設定やfirewallなど)。
また、すべての作業はrootで行われる。

yumupdate && 必要なものをyumインストール

yum -y update && \
yum -y upgrade && \
yum -y install epel-release gcc gcc-c++ make cmake autoconf git telnet wget pcre which lsof libaio net-tools numactl && \
yum -y install zlib-devel bzip2-devel libcurl-devel libxml2-devel expat-devel pcre-devel ncurses-devel 

※最終的に不必要なものとか、動作確認に使うものとかも含まれてる

/opt配下にprefixとして利用するディレクトリを作成する

cd /opt && \
mkdir httpd24 apr apr-util openssl php7 curl7-56

※mysqlはrpmインストールでデフォルトに設定されている/var/lib/配下にインストールされる

ソースを持ってきて展開する

cd /usr/local/src && \
wget http://ftp.riken.jp/net/apache//httpd/httpd-2.4.29.tar.gz && \
wget http://ftp.riken.jp/net/apache//apr/apr-1.6.3.tar.gz && \
wget http://ftp.riken.jp/net/apache//apr/apr-util-1.6.1.tar.gz && \
wget https://github.com/nghttp2/nghttp2/releases/download/v1.27.0/nghttp2-1.27.0.tar.gz && \
wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2l.tar.gz && \
wget https://curl.haxx.se/download/curl-7.56.1.tar.gz && \
wget https://downloads.php.net/~remi/php-7.2.0RC4.tar.gz && \
for TARGET in $(ls) ; do tar zxvf $TARGET ; done && \
chown -R root:root /usr/local/src/*

OpenSSLをインストールし、パスを通す。

cd openssl-1.0.2l && \
./config \
--prefix=/opt/openssl \
shared zlib && \
make && \
make install && \
echo /opt/openssl/lib > /etc/ld.so.conf.d/openssl102l.conf && \
ldconfig && \
ln -s /opt/openssl/bin/* /usr/local/bin/ && \
cd ..

確認

# openssl version
OpenSSL 1.0.2l  25 May 2017

# ldconfig -p | grep "openssl"
        libssl.so.1.0.0 (libc6,x86-64) => /opt/openssl/lib/libssl.so.1.0.0
        libssl.so (libc6,x86-64) => /opt/openssl/lib/libssl.so
        libcrypto.so.1.0.0 (libc6,x86-64) => /opt/openssl/lib/libcrypto.so.1.0.0
        libcrypto.so (libc6,x86-64) => /opt/openssl/lib/libcrypto.so

nghttp2をインストールし、パスを通す

env OPENSSL_CFLAGS="-I/opt/openssl/include" OPENSSL_LIBS="-L/opt/openssl/lib -lssl -lcrypto" && \
./configure \
--prefix=/opt/nghttp2 && \
make && \
make install && \
echo /opt/nghttp2/lib > /etc/ld.so.conf.d/nghttp2.conf && \
ldconfig
cd ..

確認

# ldconfig -p | grep "nghttp"
        libnghttp2.so.14 (libc6,x86-64) => /opt/nghttp2/lib/libnghttp2.so.14
        libnghttp2.so (libc6,x86-64) => /opt/nghttp2/lib/libnghttp2.so

curl-7.56.1をhttp2エクステンションを追加してインストールし、curl7-56コマンドで実行できるようにする。

cd curl7-56 && \
./configure \
--prefix=/opt/curl7-56 \
--with-ssl=/opt/openssl \
--with-nghttp2=/opt/nghttp2 && \
make && \
make install && \
ln -s /opt/curl7-56/bin/curl /usr/local/bin/curl7-56 && \
ln -s /opt/curl7-56/bin/curl-config /usr/local/bin/curl-config-7-56 && \
cd ..

確認

# curl --version
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.28.4 zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets

# curl7-56 --version
curl 7.56.1 (x86_64-pc-linux-gnu) libcurl/7.56.1 OpenSSL/1.0.2l zlib/1.2.7 nghttp2/1.27.0
Release-Date: 2017-10-23
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy

curl7-56のほうはnghttp2がリンクされており、HTTP2が使えることが確認できる。またOpenSSLも自分でインストールしたものがリンクされている。

apacheをインストールするためのaprとapr-utilをインストールする。

cd apr-1.6.3 && \
./configure --prefix=/opt/apr && \
make && \
make install && \
cd ..
cd apr-util-1.6.1 && \
./configure \
--prefix=/opt/apr-util \
--with-apr=/opt/apr && \
make && \
make install && \
cd ..

apacheをインストールし、http/2で通信できることを確認する。

※configureのオプションについては、お好みで追加など

インストール

cd httpd-2.4.29 && \
./configure \
--prefix=/opt/httpd24 \
--enable-http2 \
--with-nghttp2=/opt/nghttp2 \
--enable-ssl \
--with-ssl=/opt/openssl \
--with-apr=/opt/apr \
--with-apr-util=/opt/apr-util \
--enable-so \
--with-pcre=builtin \
--with-expat=builtin \
--enable-mpms-shared=all && \
make && \
make install && \
ln -s /opt/httpd24/bin/* /usr/local/bin/ && \
cd ..

SSL通信をするために自己証明書を作成

http/2はSSL通信が必須。Let'sEncryptとかを試してもいいけど、今回は自己証明書で。
※curlは自己証明書を使ってるSSL通信に対して警告を吐く。無視する場合は -k オプションを使う。

cd /opt/httpd24
mkdir cert && cd cert
openssl genrsa 2048 > server.key
openssl req -new -key server.key > server.csr  #commonnameは適当に、それ以外は空でおk
openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt
chmod 400 server.*

※openssl req は対話的にやる必要があります、注意

config修正

以下の部分を修正する。

httpd.conf

cd /opt/httpd24/conf && \
mkdir .backup && \
cp -pri httpd.conf .backup/httpd.conf.org && \
vi httpd.conf
===
#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
#LoadModule http2_module modules/mod_http2.so
#LoadModule ssl_module modules/mod_ssl.so
↓
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule http2_module modules/mod_http2.so
LoadModule ssl_module modules/mod_ssl.so
===

===
#ServerName www.example.com:80
↓
ServerName www.example.com:80
===
#localhostでよかったかも、自己証明書のcommon nameと合わせておいたほうが、何かとよいかもしれない?

===
#Include conf/extra/httpd-ssl.conf
↓
Include conf/extra/httpd-ssl.conf
===

httpd-ssl.conf

cd extra && \
mkdir .backup && \
cp -pri httpd-ssl.conf .backup/httpd-ssl.conf.org && \
vi httpd-ssl.conf

===
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
↓
SSLCipherSuite 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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
===

===
SSLProtocol all -SSLv3
↓
SSLProtocol -All +TLSv1 +TLSv1.1 +TLSv1.2
===

デフォルトで書いてある、
<VirtualHost _default_:443>
~
</VirtualHost>
をすべてコメントアウト
以下を追記。

<VirtualHost *:443>

  <IfModule http2_module>
    ProtocolsHonorOrder On
    Protocols h2 http/1.1
  </IfModule>

  ServerName www.example.com:443
  DocumentRoot "/opt/httpd24/ssl_htdocs/"

  SSLEngine on
  SSLCertificateFile "/opt/httpd24/cert/server.crt"
  SSLCertificateKeyFile "/opt/httpd24/cert/server.key"

  <Directory "/opt/httpd24/ssl_htdocs/">
    Options +Indexes +Includes +FollowSymLinks
    AllowOverride All
    Require all granted
  </Directory>

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

  SetEnvIf    Request_URI "\.(gif|jpg|png|css|js)$" nolog
  ErrorLog    /var/log/error_log
  CustomLog   /var/log/access_log combined env=!nolog

  Header add Strict-Transport-Security "max-age=15552000"

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

</VirtualHost>

ドキュメントルートを作成

mkdir /opt/httpd24/ssl_htdocs

起動

# apachectl -t
Syntax OK

# apachectl #apache起動。停止する場合は、 apachectl stop

# lsof -i:80
COMMAND   PID   USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
httpd   13919   root    3u  IPv4 248445154      0t0  TCP *:http (LISTEN)
httpd   13920 daemon    3u  IPv4 248445154      0t0  TCP *:http (LISTEN)
httpd   13921 daemon    3u  IPv4 248445154      0t0  TCP *:http (LISTEN)
httpd   13922 daemon    3u  IPv4 248445154      0t0  TCP *:http (LISTEN)

# lsof -i:443
COMMAND   PID   USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
httpd   13919   root    4u  IPv4 248445160      0t0  TCP *:https (LISTEN)
httpd   13920 daemon    4u  IPv4 248445160      0t0  TCP *:https (LISTEN)
httpd   13921 daemon    4u  IPv4 248445160      0t0  TCP *:https (LISTEN)
httpd   13922 daemon    4u  IPv4 248445160      0t0  TCP *:https (LISTEN)

止めるときは、apachectl stop
※systemctlに登録するとかは、別で。いったん動けばおk

動作確認

# 動作確認用のファイルを作成
echo "test.html 80" > /opt/httpd24/htdocs/test.html
echo "test.html 443" > /opt/httpd24/ssl_htdocs/test.html

curl http://localhost/test.html
 => test.html 80 を出力

curl https://localhost/test.html -k
 => test.html 443 を出力

curl7-56 https://localhost/test.html -k
 => test.html 443 を出力

# ログ確認
tail /opt/httpd24/logs/ssl_request_log
[29/Oct/2017:12:42:31 +0000] 127.0.0.1 TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 "GET /test.html HTTP/1.1" 14
[29/Oct/2017:12:43:19 +0000] 127.0.0.1 TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 "GET /test.html HTTP/2.0" 14

上記ログで、http/1.1 http/2 それぞれで通信できたことを確認できた。
※時刻が気になる場合はちゃんと設定しておきましょう。

PHP7.2をインストール

※configureのオプションはお好みで足してください

インストール

cd /usr/local/src/php-7.2.0RC4 && \
./configure \
--prefix=/opt/php7 \
--with-apxs2=/opt/httpd24/bin/apxs \
--enable-mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-curl=/opt/curl7-56 \
--with-openssl=/opt/openssl
make && \
make install && \
cd ..

確認

# 確認用ファイル作成
echo "<?php phpinfo(); ?>" >/opt/httpd24/ssl_htdocs/phpinfo.php

# curlで接続
curl7-56 https://localhost/phpinfo.php -k
 => phpinfoがどばどばーっとでてくる。ちゃんと生成されてるっぽいのでまぁいっかと思ったけど、念のため内容をファイルにリダイレクトしローカルに持ってきてブラウザから確認。php7.2(RC)がインストールされて動いてることが確認できた。

# log
tail /opt/httpd24/logs/ssl_request_log -n 1
[29/Oct/2017:12:47:57 +0000] 127.0.0.1 TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 "GET /phpinfo.php HTTP/2.0" 80510

MySQLインストール

MySQLだけ、rpmで配布されているものを利用。
※mysqlのソースインストールでググると、ソースからcmakeでインストールしてる記事が大量に出てくるんだけど今回はrpm利用。

公式DLページから自分の環境にあったものを選ぶ。
今回は「Red Hat Enterprise Linux 7 / Oracle Linux 7 (x86, 64-bit), RPM Bundle」をもってきて、必要なものをrpmで入れる。

mkdir /usr/local/src/mysql8 && \
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.3-0.1.rc.el7.x86_64.rpm-bundle.tar && \
tar xvf mysql-8.0.3-0.1.rc.el7.x86_64.rpm-bundle.tar && \
rpm -Uvh mysql-community-server-8.0.3-0.1.rc.el7.x86_64.rpm mysql-community-client-8.0.3-0.1.rc.el7.x86_64.rpm mysql-community-common-8.0.3-0.1.rc.el7.x86_64.rpm mysql-community-libs-8.0.3-0.1.rc.el7.x86_64.rpm

で、とりあえず最低限必要なものはOK.

起動、動作確認

systemctl start mysqld.service
 => A temporary password is generatedのメッセージがでるので、初期パスワードを確認する。mysqld.logに書いてある。

mysql -uroot -p
Enter password: => ログに出力された初期パスワードを入力。

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '[パスワード]'; 
 => rootのパスワードを変更。以後自由。

以上で、CentOS7上に最新のapache+php+mysqlの構成、および動作確認までができました。

補足

何回も試行錯誤してコンテナぽこじゃが建ててるとどんどんゴミコンテナがたまってくので、以下のシェルスクリプトで一斉お掃除。

remove-container-all.sh
#!/bin/bash
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)
hstn
おべんきょ
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした