Linux/Apacheのインストール

httpd のソースコードからのビルド(2016-11-22、更新:2017-10-02)


注意:openssl-1.1.0 について

古いopensslとの組み合わせならば問題ないですが、
1.1.0版に対応しているのはhttpd-2.4.26 以降です。
あらかじめ openssl と apache-httpd 双方のバージョンを確認しておきましょう。

はじめに(余談)

Webサーバといえば Microsoft IIS や Apache が有名だと思いますが、
性能を望むならば nginx の導入も視野に入れましょう。

・・・とか2016時点で書いていたのですが、
nginx(エンジンエックス)のシェアが徐々に増え続けているそうですね。
私の場合は、老舗な、ググれば情報が出て来やすいapacheを入れましたが、
好みのサーバを選ぶと良いと思います。

オプションや新機能は次々に出るので、気長に構築しています。

既存のapache-httpd の確認

まず、入っているかどうかの確認から。 既存のバージョンで満足するならば、yum install でよろしいかと。

# httpd -v
# yum info httpd

新たにソースからビルドしたい場合は、パッケージの方は一旦削りましょう。要るファイルがあれば先に退避すること。
(httpd.conf とか、/etc/init.d/httpd とか、/etc/logrotate.d/httpd とか
 Webサイトのコンテンツとか)

# yum remove httpd

srcのダウンロード

Apacheのサイト で適当なURLを探してダウンロード。

# cd 任意のディレクトリ
# wget http://ftp.jaist.ac.jp/pub/apache//httpd/httpd-2.4.23.tar.gz
# wget https://www.apache.org/dist/httpd/httpd-2.4.23.tar.gz.md5
# md5sum httpd-2.4.23.tar.gz
b711ea7d8b75dc8bfdf5a5d7e5253088  httpd-2.4.23.tar.gz
# cat httpd-2.4.23.tar.gz.md5
b711ea7d8b75dc8bfdf5a5d7e5253088 *httpd-2.4.23.tar.gz  ←md5sum と同じ値になること!

・・・当時はmd5sumでしたが、今はもう無いですね。
SHA256ファイルと sha256sumコマンドでもやることは同じです。

特に問題なければ、ファイルを展開、makeまで行いますが、
おそらく、先にAPR 他が必要になります。

前準備?

apache の ./configure の結果、

checking for APR... no
configure: error: APR not found.  Please read the documentation.
configure: error: pcre-config for libpcre not found. PCRE is required and available from http://pcre.org/

色々足りないと言われました。

APR はこちら APRプロジェクトのサイト
aprと、apr-util のダウンロードから展開までは割愛します。 まず apr の展開先で

  # ./configure --prefix=aprパッケージ一式を展開したい場所
  # make
  # make test
  # make install

次は apr-util の展開先で、今度は apr の場所を指定します。

  # ./configure --prefix=apr-utilパッケージ一式を展開したい場所  \
     --with-apr=さっきaprパッケージ一式を展開した場所
  # make
  # make test
  # make install

PCREも同様 pcre.org から拾ってくる。
これは perl のライブラリで、私の環境だと yum install pcre でもできそうです。

  # ./configure
  # make
  # make check
  # make install

この httpd-2.4.23 時点では OpenSSL 1.1.0 に未対応でした。
(httpd のバージョンを上げた話は後述)
make のエラーを一部抜粋。

ab.c: In function 'main':
ab.c:2357:21: warning: implicit declaration of function 'SSLv2_client_method' [-Wimplicit-function-declaration]
                    meth = SSLv2_client_method();

最初はオプション指定で行けるかと思って「CFLAGS="-DOPENSSL_API_COMPAT=0x10000000L"」のように互換バージョン指定してみましたが。 結局 make install で ssl_engine_init.c 周りでエラーになりました。
おとなしく httpd のバージョンを 2.4.26 以降にするか、openssl のバージョンを 1.0.1 以前にしましょう。


あと、後日べつの環境で同じようにインストールしたら

xml/apr_xml.c:35:19: 致命的エラー: expat.h: そのようなファイルやディレクトリはありません
#include <expat.h>

とか出てしまって、とりあえずノリで「yum info expat」とか打ってみたら
それっぽいのが見つかりました(includeヘッダが無いという事なので、expat-devel を yum install しました)
includeヘッダが無い、は結構ありがちなので、試しにノリで yum info してみるのも参考になるかもしれません。

make と install

と、いうわけで、ようやく apache-httpd を入れます。
INSTALLテキストの最初にインストールの手引きの URL が書いてあるので、一読下さい。

また、以前に apache をビルドした環境がある場合は、そこにある

config.nice

の内容を参考に、./configure すると良いです。

前述の通り、--with-apr は私の環境の場合は必須。
性能を求めるなら --with-mpm の検討は必要ですが、後でPHPを使うので*1 今回はこのままデフォルト値 preforkを使っています。

  # ./configure --prefix=Apacheのパッケージ一式を展開したい場所 \
      --with-apr=aprパッケージを展開した場所   \
      --with-apr-util=apr-utilパッケージを展開した場所 
  # make
  # make install

設定

色々ありますが、あとで随時更新する前提で。
httpd.conf

LoadModule socache_shmcb_module modules/mod_socache_shmcb.so # 有効にする
LoadModule auth_digest_module modules/mod_auth_digest.so # ダイジェスト認証が欲しいので有効に
LoadModule ssl_module modules/mod_ssl.so   # SSLを使うなら有効にする
LoadModule cgid_module modules/mod_cgid.so # 今回はCGIを使うので有効にする

ServerName 自分のサーバ名orアドレス

<Directory />
   Options None   # ここを追加
   AllowOverride none
   Require all denied
</Directory>

<Directory "/usr/local/apache/htdocs">
   # Options Indexes FollowSymLinks
   Options -Indexes +FollowSymLinks +ExecCGI
   # インデックスは消す、CGI可否は自分の環境に合わせること
 (中略)
 
 # ログの場所はお好みで。ただし あらかじめ mkdir 等を忘れずに。
 ErrorLog  /var/log/自分の好きな場所
 
 <IfModule log_config_module>
   # Formatはデフォ値で良ければそのまま、私は少し変えました
   LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
   
   #CustomLog "logs/access_log" common   # こちらはコメントアウト
   CustomLog "/var/log/自分の好きな場所" combined # 有効にして、ログのPATHも変える
 (中略)
 
 <IfModule alias_module>
   ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"
   # これ以外にも、いくつか足しています。環境に合わせて設定。
   # あと、cgi-bin というPATHは推測できない名前に変えた方が良いかもしれません。
 (中略)
 
 <IfModule cgid_module>
   Scriptsock cgisock  # 有効にする・・・必要ないかも?
 (中略)
 
 <Directory "/usr/local/apache/cgi-bin">
    # 以下を追加。cgi-bin 配下に置く内容に合わせる。
    # あと、前述の通り cgi-bin のPATHは変えてる場合はそれに合わせる
    AddType text/css .css
    AddHandler text/css .css
    AddHandler image/gif .gif
    AddHandler image/jpeg .jpg
    AddHandler image/png .png
  (中略)
  
  # Secure (SSL/TLS) connections
  Include conf/extra/httpd-ssl.conf  # SSLを使うなら有効にする
  
  (以下、ファイルの最後に追記)
  LimitRequestBody    任意の値  # 必須。無制限はまずいので。
  LimitRequestFields  任意の値  # デフォルト値より減らしていいかも
  ServerSignature Off           # 必須。でも今はデフォルトOffですね
  ServerTokens  Prod            # 必須。バージョンは隠す。脆弱性がバレるので。
  TraceEnable  Off              # 特にOnにする理由がなければ、TRACEメソッドは不許可に。
  
  # 以下の2つはクリックジャッキング対策(frame無効化)
  # ブラウザ側が対応していなければ意味は無いのですが、一応。
  Header always append X-FRAME-OPTIONS "DENY"
  Header always append X-Content-Security-Policy "default-src 'self'; allow 'self'; frame-ancestors *.自分のドメイン"
  
  # 同様に、クロスサイトスクリプティング対策
  Header always append X-XSS-Protection "1; mode=block"

extra/httpd-ssl.conf

 ErrorLog 任意の場所
 TransferLog  任意の場所
 
 (必要に応じて色々設定する
   セキュリティ周りは日々更新が必要なので、適当なタイミングで
   最新版のhttpd に差し替えたほうが手っ取り早い気がしています)

  SSLCertificateFile  任意の場所
  SSLCertificateKeyFile  任意の場所

上記の httpd-ssl.conf に合わせて、ひとまずオレオレ証明書を作成

 (デフォルト値に合わせると、conf ディレクト配下でこんなかんじで
   秘密鍵にパスワードをつけるなら、-nodes は外すこと)
 # openssl req -new -x509 -days 3650 -nodes -out server.crt -keyout server.key
 (一応、内容を確認)
 # openssl x509 -in server.crt -text

・・・と当時はやっていたんですが、今(2018夏頃)は各Webブラウザがhttps必須の流れになっちゃったので、
とりあえず動作確認できたら、すぐに正式な証明書を導入したほうが良いかもしれません。
(無料のやつだと、Let's Encryptとかがあります。
会社とかで導入するなら有料のやつを別途調達することになると思います)

話を戻して、次は起動スクリプトですが、
/etc/init.d に置く起動スクリプトは、以前の古い環境(デフォルトでhttpdが入っている)から持ってきちゃいました。*2
探せば手に入りそうですが 、CentOS 7 以降だと、systemd 方式の方がベターですし、ね・・・

ログのローテーションも、同じく古い環境から継承・・・

# cat /etc/logrotate.d/httpd
/var/log/ログのある場所 {
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
        /sbin/service httpd graceful > /dev/null 2>/dev/null || true
    endscript
}

firewall (CentOS 7 の場合)

もしファイアウォールで止めている場合は、通信を許可します。

# firewall-cmd --list-all
(確認して、なければ追加。以下はゾーンがpublicの場合)
# firewall-cmd --add-service=http --zone=public --permanent
# firewall-cmd --add-service=https --zone=public --permanent
# firewall-cmd --reload
# firewall-cmd --list-all

動作確認

init.d が追加済みなら、以下のように。
そうでなければ、bin/httpd -k start で起動しましょう。*3

# service httpd start

https はオレオレ証明書なので、大抵のWebブラウザでエラーになりますが、強制的に見ることを選択することはできるかと。

このあと、PHP のインストールの予定です。


バージョンアップ作業

遅ればせながら httpd-2.4.26 以降へバージョンを上げて OpenSSL 1.1.0 対応です。
私の環境ではこんな流れです。

  • opensslが新旧入っているので、configure で新しい方のPATHを指定する
  • opensslが lib64 に入っているので、そのPATHも指定する

前回のビルド環境が残っているので、 config.nice をコピーして、そのまま使います。
最新の apr、apr-util、httpd を入手、展開して、ビルドしました。

(まず apr-1.6.x.gz を展開した場所で)
# cp [前回の aprの場所]/config.nice  .
# ./config.nice  LDFLAGS=-L/usr/local/lib64
# make
# make test
# make install
(つぎに apr-util-1.6.x で)
# cp [前回の apr-utilの場所]/config.nice  .
# ./config.nice \
  --with-openssl=/usr/local  \
  --with-crypto  \
  LDFLAGS=-L/usr/local/lib64
# make
# make test
# make install
(さいごに httpd-2.4.2x の直下で)
# cp [前回の httpdの場所]/config.nice  .
# ./config.nice  --with-ssl=/usr/local
# make
# make install

あとは再起動して、無事に動きました、が、
うちの環境はプロキシ(squid)を導入してしまったので、httpd にSSL接続しないんですよね...
...無事に動きました!


ここは紆余曲折の過程なので、読み飛ばしてOKです

最初は、とりあえず httpd のバージョンだけ上げて make してみたのですが、 早速、コンパイルエラーになってしまいました。

httpd-2.4.27/support/ab.c:562: undefined reference to `SSL_in_init'

え~・・・reference が undefined な訳は無いのですが・・・
想定の斜め上のエラーになってしまいました。 とりあえず、config.log を確認してみます

configure:25233: WARNING: Your APR does not include SSL/EVP support. To enable it: configure --with-crypto
(中略)
configure:26008: checking for OpenSSL
configure:26021: checking for user-provided OpenSSL base directory
configure:26037: result: /usr/local

指定したディレクトリ(result: /usr/local)を見に行っているっぽいですが、
APR側で足りないオプション(--with-crypto)があると警告されています。httpd だけでなくapr もバージョン上げないとダメか?
ちなみに、 ./configure --help で確認すると、上記オプションは
(apr ではなく)apr-util の方で見つかります。
with-crypto のほかに、with-openssl も指定して再ビルドが必要です。
(私の環境は openssl が 1.0.1と 1.1.0 両方あるので、PATH指定しないと違うバージョンを見に行ってしまう)

それを踏まえて、最新の apr と apr-util を入れなおします。*4

・・・入れなおしましたが、まだ httpd の make でエラーになります。
あらためて、make エラーになる直前の行を見てみると、
何だか SSL_ini_init 他の入っている
lib64/libssl* を見に行っていないような雰囲気です。つまり、
「-L/usr/local/lib」 はあるけど、
「-L/usr/local/lib64」 が見当たらない...
それで、ようやく前述の LDFLAGS の追記に至りました。
ポイント(?)は httpd ではなく、apr を configure する時に LDFLAGS 指定が必要だったところでしょうか。

(ちなみに、makeではなく、起動時に lib64 を読みに行かない場合は、
ldconfig の設定が抜けている可能性がありますのでご注意を。その場合は /etc/ld.so.conf 等を更新しましょう)

・・・バージョン上げるだけなのに随分手間がかかりました、
なんてメモしがいのある環境なんでしょう。


あと、これはついでなのですが、
2017.09現在で httpd にパッチも出ていたので当てました。
(Optionsbleed という脆弱性だそうです)

(httpd のソースファイル直下で、取得した patchファイルをあてる)
# patch -p0 < CVE-2017-9798-patch-2.4.patch
(あとは make して、make install)

*1 PHPのINSTALLテキストを参照。prefork(複数プロセスで動く)よりworker(複数スレッドで動く)の方が高性能な場合が多いが、スレッドセーフなモジュールであるか確認が必要。
*2 余談:そこで status 確認に使ってる lynx も追加で yum install しました。
*3 余談:モジュールをアップデートした場合は、restartではなく、stop(graceful-stop)を使用する。restart は親プロセスは再起動しないので、動的リンクの内容が変わっていた場合など、上手く読み込めない場合がある。(例:Cannot load modules ~: undefined symbol:)
*4 古い apr-util 1.5 と OpenSSL 1.1.0だとコンパイルエラーになるので(crypto/apr_crypto_openssl.lo 等)、apr-util 1.6.0 にしました