Webサーバ構築

よしはし

今回の目的

Apacheを用いてWebサーバを構築します。Apacheのインストールはソースから行います。プログラムをソースからインストールすることの利点、欠点を考えます。Webサーバが提供するサービスは馴染みが深いので、サーバを構築した達成感が得られると思います。

今回の内容

講義

演習

Webサーバとは?

WebサーバとはWebの機能を提供するサーバのことです。Webについては、みなさんも普段から使っているので、だいたいの内容はわかっていると思います。しかし、Webサーバがどのように機能しているか理解している人は少ないのではないでしょうか。とりあえず押さえておくべき基本的なWebサーバの動作は次の二つです。

  1. クライアント(Webブラウザなど)から要求されたファイルをそのままクライアントに返す
  2. クライアントから要求されたプログラムを実行し、その結果をクライアントに返す

上から説明します。Webサーバは、わたしたちが見るWebページをファイルとして保存しています。WebブラウザはWebサーバにそれらのファイルを要求します。要求を受け取ったWebサーバはファイルをクライアントに返します。ブラウザはそのファイルを解釈し、わたしたちが見やすいように表示します。例えば、Webブラウザのアドレスバーにhttp://cis.k.hosei.ac.jp/index.htmlと入力しエンターキーを押すと、Webブラウザに法政大学情報科学部のWebページが表示されます。このときの流れは次のようになります。

  1. WebブラウザはWebサーバcis.k.hosei.ac.jpにindex.htmlというファイルを要求する。
  2. Webサーバはその要求に答え、index.htmlをクライアントに返す。
  3. Webブラウザはindex.htmlを表示する。

また、Webには掲示板のような動的なコンテンツがあります。このようなページでは、サーバ上のファイルをそのまま返すという動作だけでは上手く機能しません(掲示板なのに書き込めない!)。動的なページを実現するために、もうひとつの基本的な動作「クライアントから要求されたプログラムを実行し、その結果をクライアントに返す」が使われます。Webサイトを作ったことがある人は、CGI(Common Gateway Interface)という言葉を聴いたことがあるかもしれません。プログラムはCGIを通して実行されます。また、その実行されるプログラムをCGIプログラムと呼び、拡張子は.cgiです。http://www.example.com/bbs.cgiにアクセスした場合、基本的な動作の流れは次のようになります。

  1. WebブラウザはWebサーバwww.example.comにbbs.cgiというファイルを要求する。
  2. Webサーバはその要求がCGIであることを確認し、bbs.cgiを実行する。
  3. Webサーバはその実行結果をクライアントに返す。
  4. Webブラウザは実行結果を表示する。

Apache

今回構築するWebサーバにはApacheを使用します。Apacheはアパッチと読みます。現在、世界で最も使われているWebサーバで、Apacheライセンスに基づいてフリーで公開されています。

特徴

Apacheの特徴には以下のようなものがあります。

この中でいまいち意味が掴めないのは、最後の「モジュールによる機能の拡張」だと思います。

モジュールによる機能の拡張

Apacheは機能がモジュール化されたWebサーバです。新しい機能が必要な時は、その機能を実現するモジュールを動的共有オブジェクト(DSO)としてコンパイルします。すると、サーバの起動時、または再起動時にそのモジュールをロードして、サーバの機能として付け加えることができます。この利点はApacheを再ビルドすることなく機能を拡張できることです。

httpd

httpdとはWebサーバの機能を実現するデーモンです(デーモンとはシステムのバックグラウンドで動作し、システムの機能を実現したり、サービスを提供したりするプログラムです)。Apacheは代表的なhttpdです。また、HTTP(HyperText Transfer Protocol)とはWebサーバとWebクライアント間でやりとりするときに使用されるプロトコルです。通常サーバ側のポート番号は80番です。

パッケージインストールとソースインスール

ソフトウェアのインストール方法には大きく分けてふたつあります。ひとつは、RPMやyumを用いてコンパイル済みのバイナリパッケージをインストールする方法です。もうひとつの方法では、ソースコードを自分でコンパイルしてバイナリファイルを作成し、それをインストールします。

パッケージインストール

パッケージインストールをする利点は、簡単なことです。例えば、RPMを使ってインストールする場合は次のようにコマンドを打つだけです。

rpm -i (インストールしたいパッケージ)

インストールされているパッケージの情報はデータベースに保存されているので、管理も容易です。
また、インストールするパッケージが他のパッケージを必要とする場合、そのパッケージも一緒にインストールしてくれるパッケージマネージャもあります。

逆に欠点としては、コンパイルされたバイナリが自分の環境に合わないことがあります。特にApacheのようにコンパイルオプションが多いソフトウェアではそれが顕著に現れます。さらに、バイナリコードはマシンに最適化されていません。RPMパッケージのファイル名にi386と書いてあることに気付いた人もいると思いますが、RPMパッケージをインストールする場合、i386版をインストールします。i386とはIntelが20年近く前に出したプロセッサ386を意味します。Pentium4はこの386と互換性があるので、386用のプログラムも実行することはできます。しかし、Pentium4用に最適化されたプログラムにくらべて実行速度は落ちます。また、すべてのソフトウェアがパッケージ化されているわけではないのに注意しましょう。最新バージョンのソフトウェアも直ぐにパッケージ化されるとは限りません。そのようなソフトウェアをインストールしたい時にはソースからインストールせざるをえません。

(正確に言うと、パッケージインストールにもバイナリではなくソースからインストールするものがあります。有名なのはFreeBSDのportsとGentoo LinuxのPortageシステムです。また、RPMにもSRPMというソースからインストールするパッケージがあります。)

ソースインストール

ソースインストールの利点は、プログラムを自分の環境に合わせることができる点です。これはパッケージインストールの欠点を見事にカバーしています。

欠点は面倒くさいところでしょう。コンパイルオプションを調べたり、プログラムの依存性を調べなくてはいけません。インストールした後も自分でしっかりと管理する必要があります。ソースからインストールしたプログラムのアップデートやアンインストールは手動でやらなければいけません。

以上をまとめて表にしておきます。

パッケージソース
管理簡単大変
機能不十分なプログラムもある自分で設定可能
最適化期待できない自分で設定可能
制限パッケージ化されていないプログラムがある基本的にはない
時間かからないかかる

Webサーバの構築

構築手順

前準備

Webサーバを構築した後に動作確認をやります。今回は、動作確認をノートパソコンのWebブラウザ(IEなど)を用いてやることにしました。そのためには、SSHのポートフォワーディング機能を使う必要があるため、PuTTYの設定を少し変える必要があります。(こんな面倒くさいことをする理由を知りたい人は、前回のSSHサーバ構築の記事を読めばわかるかもしれません。)

以下、作業は自分のサーバマシンにSSHでログインして行います。ログインの仕方等を忘れてしまった人は前回のSSHサーバ構築の記事を参照してください。

Apacheがインストールされていないか確認

Linuxをインストールしたときに、Apacheがインストールされていないかどうかチェックします。チェックするために下のコマンドを実行します。

yum list httpd

これを実行して下のように表示された場合、Apacheはインストールされていません。次のソースコードのダウンロードに進んでください。

Looking in Available Packages:
Name                                Arch   Version                  Repo
--------------------------------------------------------------------------------
httpd                               i386   2.0.50-2.1               updates-released

Looking in Installed Packages:
Name                                Arch   Version                  Repo
--------------------------------------------------------------------------------

下のように表示された場合、Apacheがインストールされていますので、まずはそれをアンインストールします。

Looking in Available Packages:                                                 
Name                                Arch   Version                  Repo       
-------------------------------------------------------------------------------
                                                                               
Looking in Installed Packages:                                                 
Name                                Arch   Version                  Repo       
-------------------------------------------------------------------------------
httpd                               i386   2.0.50-2.1               db         

Apacheのアンインストールは次のようにします。rootで作業する必要があるので、su -を実行してrootになります。

su -
yum remove httpd

この後は一般ユーザで作業するので、一般ユーザに戻ります。

exit

ソースコードのダウンロード

Apacheの最新版のソースコードをダウンロードします。ソースコードはhttp://httpd.apache.org/download.cgiからダウンロードできます。ダウンロードをするときは物理的に近い場所にあるミラーサイトからにしましょう。学内でなら、http://storage.cis.k.hosei.ac.jp/のミラーからダウンロードできます。

wget http://storage.cis.k.hosei.ac.jp/pub/apache/httpd/httpd-2.0.50.tar.gz

ソースコードの解凍

ダウンロードしたソースコードはtar.gzという形式で圧縮されているので、それを解凍します。

tar zxvf httpd-2.0.50.tar.gz

READMEとINSTALL

カレントディレクトリにhttpd-2.0.50というディレクトリがあらわれます。ここに解凍されたソースコードが入っています。

cd httpd-2.0.50

httpd-2.0.50の中をlsで見てみましょう。

ls
ABOUT_APACHE    LAYOUT         README.platforms  config.layout  libhttpd.dsp
Apache.dsp      LICENSE        VERSIONING        configure      modules
Apache.dsw      Makefile.in    acconfig.h        configure.in   os
BuildBin.dsp    Makefile.win   acinclude.m4      docs           server
CHANGES         NOTICE         apachenw.mcp.zip  emacs-style    srclib
INSTALL         NWGNUmakefile  build             httpd.spec     support
InstallBin.dsp  README         buildconf         include        test

READMEというファイルがあることに気付くと思います。READMEファイルがある場合、まずはそれに目を通すのが基本です。

less README

READMEを読むと、インストール方法はINSTALLファイルに書いてあるとあります。これにも目を通します

less INSTALL

ちゃんとしたインストールドキュメントの場所が書いてあります。また、せっかちな人のためのインストール方法が書かれています。本来はインストールドキュメントをしっかり読むべきなのですが、今回は割愛します。

configure

configureを用いて、コンパイルオプションとインストールオプションを設定します。設定の仕方は./configureを実行する時にコマンドの引数としてオプションを与えます。./configureに--helpオプションを与えると、どのようなオプションがあるかを表示します。

./configure --help

なんかすごい速さで表示されました。これでは普通の人は全部見れませんね。このようなときは次のようにします。

./configure --help | less

どのようなオプションがあるかは分りましたが、個々のオプションの説明が簡単すぎてよく分りません。こういう場合、より詳しいインストールドキュメントを読むと良いでしょう。

今回はこっちで勝手にオプションを指定します。

"./configure" \
"--prefix=/usr/local/httpd" \
"--enable-layout=Apache" \
"--with-mpm=prefork" \
"--enable-modules-shared=all" \
"--enable-so" \
"--enable-deflate" \
"--enable-proxy" \
"--enable-suexec" \
"--with-suexec-caller=httpd" \
"--with-suexec-logfile=/var/log/httpd/suexec_log" \
"--with-suexec-docroot=/home" \
"--disable-asis" \
"--disable-auth_anon" \
"--disable-auth_dbm" \
"--disable-dav" \
"--disable-dav-fs" \
"--disable-imap" \
"--disable-status"

このような長ったらしいのは直接打つのではなく、コピペでやりましょう(上のコマンドとオプションをコピーして、PuTTYに右クリックでペーストします)。

configureの実体はディレクトリhttpd-2.0.50内にあるスクリプトファイルです。そのため、実行する時に./を頭につけます。

オプションの説明

--prefix=/usr/local/httpd
全体のインストール先を/usr/local/httpdにします。
--enable-layout=Apache
インストールパスを指定するためのレイアウトを使用します。使用できるレイアウトはconfig.layoutファイルにあるものです。またconfig.layoutにはどのようにインストールされるかの詳細が書いてあります。
--with-mpm=prefork
preforkというマルチプロセッシングモジュール(MPM)を有効にする。MPMは他にworkerなどがあります。詳しくはhttp://httpd.apache.org/docs-2.0/mpm.htmlを参照してください。
--enable-modules-shared=all
全てのモジュールをダイナミックロードできる形(DSO)でコンパイルとインクルードします。このあとに--disable-MODULEとして指定したモジュールは取り除くことができます。allのほかにmostやモジュール名を=の後に置く事ができます。
--enable-MODULE
MODULEモジュールをコンパイルして、インクルードします。モジュールをDSOとしてコンパイルする場合はモジュール名の後に=sharedオプションを指定します。
--with-suexec-xxx
suEXECの設定オプションです。suEXECについては後で説明します。
--disable-MODULE
コンパイルされてインストールされるモジュールを取り除きます。

個々のモジュールの説明はhttp://httpd.apache.org/docs-2.0/mod/を参照して下さい。

make

configureが終了したら、次はコンパイルです。コンパイルするにはmakeコマンドを実行します。

make

make install

コンパイルが終ったら、作成されたプログラムをインストールします。インストールはrootで行います。

su -
cd /home/(ユーザ名)/httpd-2.0.50
make install

たとえば、一般ユーザの名前がhogeなら下のようになります。

su -
cd /home/hoge/httpd-2.0.50
chown -R root:root .
make install

これで、インストール作業は終了です。次は設定です。

これより後はrootで作業します。

httpd.confの編集

Apacheをインストールしたディレクトリ/usr/local/httpdのしたにconfというディレクトリがあります。そこにApacheの設定ファイルhttpd.confがあります。それを自分の環境に合うように設定します。httpd.confで設定する個々の項目のことをディレクティブといいます。今回変更するディレクティブは、以下のとおりです。

httpd.confを書き換えるので、何かあったときのために初期設定を保存しておきます。

cp /usr/local/httpd/conf/httpd.conf /usr/local/httpd/conf/httpd.conf.default

以下の作業はviでhttpd.confを開いた状態で行います。

vi /usr/local/httpd/conf/httpd.conf

Userディレクティブの変更

Userディレクティブでは、サーバがリクエストに応答する際に利用されるユーザIDを指定します。今回はhttpdというユーザを新たに作成し、それをUserディレクティブに設定します。Userディレクティブはデフォルトではnobodyになっているので、httpdに書き換えます。

User nobody
↓
User httpd

Groupディレクティブの変更

Groupディレクティブでは、リクエストに応答される際に所属するグループを指定します。今回はhttpdグループです。Groupディレクティブはデフォルトでは#-1になっています。

Group #-1
↓
Group httpd

ServerAdminディレクティブの変更

ServerAdminディレクティブでは、クライアントに返すエラーメッセージに載せるe-mailアドレスを指定します。自分のメールアドレス(大学のメールアドレス)を書いておきましょう。

ServerAdmin you@example.com
↓
ServerAdmin 自分のメールアドレス

ServerNameディレクティブの変更

ServerNameディレクティブではホストネームとポートを指定します。これはサーバが自分自身を認識するのに使われます。今回はホストネームは自分のIPアドレスです。ServerNameディレクティブは290行目付近にあります。コメントがついていますので外してください。

#ServerName www.example.com:80
↓
ServerName 192.168.1.1xx:80

ErrorLogディレクティブの変更

エラーログを保存するファイルを指定します。多くのサービスはログを通常/var/log以下に保存するので、それに習い/var/log/httpdというディレクトリの下にApacheのログを保存します。エラーログは/var/log/httpd/error_logに保存するように設定します。

ErrorLog logs/error_log
↓
ErrorLog /var/log/httpd/error_log

CustomLogディレクティブの変更

サーバーへのリクエストのログを保存するファイルとログのフォーマットを指定します。CustomLogディレクティブは500行目あたりにあります。/var/log/httpd/access_logに保存するようにします。またログのフォーマットはcommonです。CustomLogはいくつかありますが、コメントアウトされていない(#で始まらない行)もののうち、末尾がcommonとなっているものを編集してください。

CustomLog logs/access_log common
↓
CustomLog /var/log/httpd/access_log common

これでhttpd.confの編集は終了です。変更を保存し、viを終了してください。個々のディレクティブの詳しい説明はhttp://httpd.apache.org/docs-2.0/mod/quickreference.htmlを参照してください。

デーモンの設定ファイルは/etc以下に置かれるのが普通ですので、/etc/httpdの下にhttpd.confを置くことにします。また、/usr/local/httpd/confに/etc/httpd/httpd.confのシンボリックリンクを貼っておきます。

mkdir /etc/httpd
mv /usr/local/httpd/conf/httpd.conf /etc/httpd
cd /usr/local/httpd/conf
ln -s /etc/httpd/httpd.conf httpd.conf

ユーザとグループの作成

groupadd -g 300 httpd
useradd -g 300 -u 300 -c "Apache Daemon User" -M httpd

ログを保存するディレクトリの作成

mkdir /var/log/httpd
chown httpd: /var/log/httpd

httpd.confのチェック

/usr/local/httpd/bin/apachectl -t

これを実行して

Syntax OK

と表示されればOKです。何かエラーが表示された場合は、httpd.confの設定が間違ってると思われます。

ファイアウォールの設定

iptablesを編集して、TCPポート80番を開けます。-A INPUT -p tcp -m tcp --dport 22 -j ACCEPTの下に-A INPUT -p tcp -m tcp --dport 80 -j ACCEPTを加えます。

vi /etc/sysconfig/iptables
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp --icmp-type any -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT (←この行を追加)
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited

ファイアウォールの再起動

/etc/init.d/iptables restart

動作確認(静的ページ)

Apacheを起動します。

/usr/local/httpd/bin/apachectl start

ノートパソコンのWebブラウザで次のアドレスのページを表示させます。

http://localhost:10080/

「あなたの予想に反して、このページが見えているでしょうか?」という文が表示されたでしょうか。表示されたら、次はCGIの動作チェックです。不幸にも表示されなかった人は、ログやIEのメッセージを頼りに間違えた場所を特定します。Apacheのログは/var/log/httpd以下にあります。

以下はIEに表示されるエラーメッセージごとの対処方法です。

ページを表示できません

iptablesの設定が間違っている可能性があります。この場合、httpdにリクエストが届く前にパケットが殺されているので、Apacheのログには残りません。

ページが見つかりせん

404エラーです。アドレスが間違っている、もしくはファイルが存在していない可能性が高いです。

Forbidden

許可のないファイルにアクセスしています。この場合、Apacheのerror_log(/var/log/httpd/error_log)にエラーログが残ります。パーミッションがhttpdがアクセスできるようになっているか確認して下さい。

ログを見る

ログを見るには次のコマンドが便利だと思います。

tail -5 /var/log/httpd/access_log

tailはファイルの終わりの部分を表示します。今回はオプションで-5を渡しているので終わりの5行を表示します。新しいログはファイルの後ろに追加されるので、tail -5は最新の5つを表示することになります。

エラーログを見る

以下のエラーログはあくまで一例です。実際には環境等によってエラーメッセージは変わりますし、もしかしたら全く新しいエラーログが出ているかもしれません。そのような場合でもエラーメッセージをよく読み、何がエラーの原因なのか自分で考えるようにしましょう。

tail -5 /var/log/httpd/error_log
[Sat Jul 24 19:44:14 2004] [error] [client 192.168.1.2] (13)Permission denied: access to /~you/cgi-bin/index.cgi denied

このエラーの場合、you、cgi-binディレクトリまたはindex.cgiのうちのどれかがhttpdからアクセスできないようになっています。これらのパーミッションを調べてみてください。ここでのyou、cgi-bin、index.cgiなどは環境によって変わります。重要なのは(13)Permission denied: access toというエラーメッセージが多くの場合パーミッション設定のミスによって現れるということです。

[Sat Jul 24 19:46:47 2004] [error] [client 192.168.1.2] Premature end of script headers: test.cgi, referer: http://192.168.1.50/~you/cgi-bin/

これはtest.cgiが関わっているエラーです。また/~you/cgi-binにも問題がありそうです。CGIによって起こされるエラーなのでsuEXECにも何か関係がありそうです。suEXECのログを見てみます。

tail -5 suexec_log

すると、下のようなエラーメッセージがありました。

[2004-07-24 19:46:47]: directory is writable by others: (/home/you/public_html/cgi-bin)

どうやらcgi-binディレクトリが第3者によって書き換えられるようになっているのためにエラーが起こったみたいです。cgi-binのパーミッションを変更して、他ユーザが書き換えできないようにしましょう。

[Sat Jul 24 19:49:02 2004] [error] [client 192.168.1.2] Premature end of script headers: test.cgi

これはtest.cgiというCGIプログラムによって起きたエラーです。この場合、実際のエラーはsuEXEXCによって起こされている可能性がありますので、suEXECのログを見てみましょう。

tail -5 suexec_log
[2004-07-24 19:49:02]: file is writable by others: (/home/you/public_html/cgi-bin/test.cgi)

このようなログがあった場合、CGIプログラムのパーミッションでそのプログラムの持ち主以外がそのプログラムへの書き込み権を持っていると考えられます。suEXECはそのような状態を許していません。パーミッションを持ち主以外は書き込めないように変更しましょう。
また、次のようなログがsuexec_logにあるかもしれません。

[2004-07-24 19:55:28]: target uid/gid (500/500) mismatch with directory (500/500) or program (500/300)

このエラーはCGIプログラムのユーザIDまたはグループID、もしくはそのプルグラムが置いてあるディレクトリのユーザIDまたはグループIDがsuEXECのターゲット(普通はそのページの管理者)のユーザID、グループIDと異なるために発生します。ユーザIDとグループIDを適切なものに設定しましょう。(このエラーログの例の場合、CGIプログラムのグループIDが300になっているのがおかしいです)

動作確認(動的ページ)

CGIプログラムは/usr/local/httpd/cgi-binディレクトリに置きます。今回、テスト用に簡単なCGIプログラムを作成します。

vi /usr/local/httpd/cgi-bin/test.cgi
#!/usr/bin/perl
print "Content-type: text/plain\n\n";
print "$_\t$ENV{$_}\n" for (keys %ENV);

CGIは実行ファイルなので、そのようにパーミッションを変更します。

chmod 755 /usr/local/httpd/cgi-bin/test.cgi

ノートパソコンのWebブラウザで次のアドレスにアクセスしてください。

http://localhost:10080/cgi-bin/test.cgi

下のような感じにブラウザで表示されればOKです。表示されなかった場合は上のエラーログの記事を参照してください。

SCRIPT_NAME	/cgi-bin/test.cgi
SERVER_NAME	192.168.1.xx
SERVER_ADMIN	you@example.com
HTTP_ACCEPT_ENCODING	gzip, deflate
HTTP_CONNECTION	Keep-Alive
REQUEST_METHOD	GET
HTTP_ACCEPT	image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
SCRIPT_FILENAME	/home/httpd/cgi-bin/test.cgi
SERVER_SOFTWARE	Apache/2.0.50 (Unix)
QUERY_STRING	
REMOTE_PORT	xxxx
HTTP_USER_AGENT	Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
SERVER_PORT	80
SERVER_SIGNATURE	<address>Apache/2.0.50 (Unix) Server at 192.168.1.xx Port 80</address>

HTTP_ACCEPT_LANGUAGE	ja
REMOTE_ADDR	192.168.1.xx
SERVER_PROTOCOL	HTTP/1.1
PATH	/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
REQUEST_URI	/cgi-bin/test.cgi
GATEWAY_INTERFACE	CGI/1.1
SERVER_ADDR	192.168.1.xx
DOCUMENT_ROOT	/home/httpd/public_html
HTTP_HOST	192.168.1.xx

起動スクリプトの作成

Apacheがちゃんと動いていることは確認できました。しかし、Apacheを起動するのに毎回手動で

/usr/local/httpd/bin/apachectl start

とやるのはあまりよくありません。もしサーバマシンを再起動したら、Apacheは自動的に起動されません。そこで、起動スクリプトを作成し、起動時にApacheを起動するようにします。作成するとは言っても、自分でいちから書く必要はありません。たいていの場合、起動スクリプトはすでに用意されています。Apacheの場合もソースコードディレクトリのbuild/rpmの下にhttpd.initという名前で用意されています。

用意されている起動スクリプトを、他のデーモンの起動スクリプトが置いてあるディレクトリ(/etc/init.d)にコピーします。

cp /home/(ユーザ名)/httpd-2.0.50/build/rpm/httpd.init /etc/init.d/httpd

一般ユーザがhogeの場合は下のようになります。

cp /home/hoge/httpd-2.0.50/build/rpm/httpd.init /etc/init.d/httpd

起動スクリプトを編集します。Apacheのインストール先に合うようにパスを書き換えます。

vi /etc/init.d/httpd
変更するところとその変更後の値
apachectl=/usr/local/httpd/bin/apachectl
httpd=${HTTPD-/usr/local/httpd/bin/httpd}
CONFFILE=/etc/httpd/httpd.conf

起動スクリプトを使って再起動します。

/etc/init.d/httpd restart

エラーが出たらエラーメッセージをヒントに起動スクリプトを再編集します。

起動スクリプトを有効にするために、以下の2つのコマンドを実行します。

chkconfig --add httpd
chkconfig --level 345 httpd on

起動スクリプトが有効かどうか確認します。

chkconfig --list | grep httpd

以下のように表示されればOKです。

httpd           0:オフ  1:オフ  2:オフ  3:オン  4:オン  5:オン  6:オフ

logrotate

ログファイルを放って置くとファイルが肥大化し扱いにくくなってしまいます。そのためlogrotateを用いて定期的にログファイルをローテーションし、そのようになるのを回避します。Apache用のlogrotate設定ファイルもすでに用意されています。それを、他のデーモンのlogrotate設定ファイルが置いてあるところ(/etc/logrotate.d)にコピーします。

cp /home/(ユーザ名)/httpd-2.0.50/build/rpm/httpd.logrotate /etc/logrotate.d/httpd

/etc/logrotate.confを編集し、ログをどのくらい期間でローテーションし、どのくらいの世代を残すか等の設定をします。今回は月に一度ローテーションし、24世代残すようにします(つまり2年分のログを残すわけですね)。

vi /etc/logrotate.conf
weekly
↓
monthly
rotate 4
↓
rotate 24
create 0664 root utmp
↓
create 0660 root utmp

Userディレクティブ

各ユーザごとに自分のホームディレクトリでWebページを管理したいという願いをかなえるのがUserディレクティブです。Userディレクティブに指定したディレクトリをユーザのホームディレクトリの下に置けば、http://www.example.org/~user/index.htmlといった感じでWebサイトをみることができます。下の設定を/etc/httpd/httpd.confのUserDirディレクティブが設定されているところ(370行目あたり)の下に追加します。

<Directory /home/*/public_html>
    AllowOverride NONE
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>
vi /etc/httpd/httpd.conf
# directory if a ~user request is received.
#
UserDir public_html
(ここに追加)
#
# Control access to UserDir directories.  The following is an example

これで、ユーザのホームディレクトリにpublic_htmlというディレクトリを作成し、そこにWebページを保存すれば、そのページは外部に公開されます。この際、ホームディレクトリ、public_htmlのパーミッションはhttpdがアクセスできるようにする必要があります(たとえば755(rwxr-xr-x))。また、Webで公開するファイル、およびそのファイルが置かれているディレクトリのパーミッションもhttpdがアクセスできるようにしとかなければなりません。

CGIが実行できるようにAddHandlerディレクティブのコメントをはずします(870行付近)。

AddHandler cgi-script .cgi

httpd.confを編集したのでApacheを再起動します。

/etc/init.d/httpd restart

実際に表示されるか試してみましょう。以下の作業は一般ユーザで行います。なお、ここでホームディレクトリのパーミッションを755にしますが、これはセキュリティ上良くありません。これの対策方が、この後に出てくる「ホームディレクトリのパーミッション」というところにありますので、必ず参照してください。

chmod 755 ~
cd
mkdir public_html
cd public_html
vi index.html

viでindex.htmlを以下のように編集します。

<html>
<head><title>TEST</title></head>
<body>Foo Bar Baz Hoge</body>
</html>

Webブラウザのアドレスバーに以下のように入力します。

http://localhost:10080/~(ユーザ名)/

たとえばユーザ名がhogeだったら、下のようになります。

http://localhost:10080/~hoge/

Foo Bar Baz Hogeという言葉がちゃんと表示されましたでしょうか。

CGIが動くかどうかもテストしましょう。

mkdir ~/public_html/cgi-bin
chmod 755 ~/public_html/cgi-bin
cd ~/public_html/cgi-bin
vi test.cgi

test.cgiを次のように編集し、保存してviを終了させます。

#!/usr/bin/perl
print "Content-type: text/plain\n\n";
print "$_\t$ENV{$_}\n" for (keys %ENV);

test.cgiは実行ファイルなので、パーミッションを変更します。

chmod 755 test.cgi

Webブラウザのアドレスバーに以下のように入力します(ユーザがhogeの場合)。

http://localhost:10080/~hoge/cgi-bin/test.cgi

suEXEC

現在の設定ではCGIプログラムはApacheを実行するユーザ(今回はhttpd)の権限で実行されます。この場合、CGIプログラムからアクセスされるファイルはhttpdがアクセスできるようになっていなければなりません。パーミッションを緩めればそれだけセキュリティも甘くなってしまいます。また、CGIプログラムの中にはファイルやディレクトリを作るものもあります。その作られたファイルやディレクトリの所有者はCGIプログラムの実行ユーザになってしまうので、一般ユーザが自分のホームディレクトリ下にあるディレクトリやファイルを削除できないという現象が生じてしまいます。ApacheではsuEXECという機能をつかうことによりCGIプログラムの所有者のユーザ権限でCGIを実行させることができます。これにより上の問題は解決されます。

suEXECはデフォルトではインストールされないので./configureのときに明示的にenableにしなければなりません。今回はそのようにしていますのでこのまま作業を続けることが可能です。

suEXECを可能にするためにCGIプログラムのパーミッションを700(rwx------)にします。

chmod 700 ~/public_html/cgi-bin/test.cgi

これでちゃんとCGIが動くか動作確認します。

suEXECについての詳しい情報はhttp://httpd.apache.org/docs-2.0/suexec.htmlを参照してください。

ホームディレクトリのパーミッション

現在、httpdからpublic_htmlにアクセスできるようにするために、ユーザのホームディレクトリのパーミッションは755(rwxr-xr-x)になっています。しかし、この設定だと他のユーザ全てからホームディレクトリの中が見えてしまいます。これではセキュリティ的に良いとは言えません。そこで、httpdはアクセスできるが他のユーザからはアクセスできないようにホームディレクトリの設定を変更します。

ユーザがrootの状態で、以下のコマンドを実行します。

chgrp httpd /home/(ユーザ名)
chmod 750 /home/(ユーザ名)

たとえば、ユーザ名が"hoge"だった場合は、以下のようなコマンドになります。

chgrp httpd /home/hoge
chmod 750 /home/hoge

htmlファイルが見られるか、CGIが実行されるかを確認してください。

上のコマンドを実行すると、ホームディレクトリのパーミッションが750(rwxr-x---)になるので、他のユーザから中を見られることはありません。これだとhttpdもアクセスできなさそうですが、ホームディレクトリのグループIDはhttpdなのでグループhttpdのメンバであるhttpdはアクセス可能です。ホームディレクトリの中のディレクトリやファイルのグループIDはhttpdではないので、ホームディレクトリの中ではhttpdがアクセス可能であるべきファイルのパーミッションは第三者が読めるようになっていなくてはなりません(suEXECを使う場合、CGIプログラムは除きます)。

  1. httpdはindex.htmlにアクセス可能ですが、他の一般ユーザもアクセスできてしまいます。
  2. httpdは/home/hogeにアクセスする権限がないのでindex.htmlを読み込むことはできません。
  3. httpdはindex.htmlにアクセス可能です。他の一般ユーザは/home/hogeの中身を見ることはできません。

ACLを使用する場合

間違えるとLinuxが起動できなくなるので、今回はこの方法を使用しません!

Linuxカーネル2.6からPOSIX ACL(Access Control Lists)という機能が追加されました。これによりファイルやディレクトリへの各ユーザもしくはグループでのアクセス制御を行えるようになります。これを使えば、上のようにホームディレクトリのグループIDをhttpdにすることなくpublic_htmlにアクセスすることが可能になります。

ACLを使用するために、/etc/fstabの1行目を次のように書き換えます。

vi /etc/fstab
LABEL=/                 /                       ext3    defaults        1 1
↓
LABEL=/                 /                       ext3    defaults,acl          1 1

マウントしなおすため、とりあえずリブートしましょう。

reboot

再起動が終了したら、ユーザでログインした後に以下のコマンドを実行します。これでhttpdがホームディレクトリにアクセスできるようになります。

(ユーザでログイン)
setfacl -m u:httpd:rx ~

「ACLを使用する場合」でホームディレクトリのグループをhttpdにしている場合は、ホームディレクトリのグループを自分のものに戻しましょう。この状態ならば、自分のホームディレクトリのグループをhttpdにする必要はありません。

chgrp (ユーザ名) ~

自分のユーザ名がhogeだった場合は次のようなコマンドになります。

chgrp hoge ~

仕組みとしては先の方法と同じで、違いはホームディレクトリへのアクセスをグループID、ACLどちらで与えているかだけです。そのため、ホームディレクトリ中のhttpdがアクセスすべきファイルやディレクトリは第三者が読めるようになっている必要があります(suEXECを使う場合、CGIプログラムは除きます)。

ドキュメントルートの変更

ドキュメントルートとはWebサーバ上でのルートディレクトリのことです。http://www.example.com/index.htmlのindex.htmlファイルが置いてある場所がドキュメントルートです。デフォルトでは/usr/local/httpd/htdocsになっています。ここにファイルを置いてサービスを提供することもできますが、管理面、運営面で都合が悪いです。また、セキュリティ的にも良いとは言えません。そんなわけなので、ドキュメントルートは変更するべきです。ドキュメントルートはhttpd.confのDocumentRootディレクティブ(310行目あたり)で設定されています。今回はドキュメントルートを/home/httpd/public_htmlに設定します。

DocumentRoot "/usr/local/httpd/htdocs"
↓
DocumentRoot "/home/httpd/public_html"

また、httpd.confを見ていくと、httpd.confの330行あたりにある<Directory>も変更しなければいけないことがわかります(コメントのところに英語で書いてある)。

<Directory "/usr/local/httpd/htdocs">
↓
<Directory "/home/httpd/public_html">

設定ファイルを変更したのでApacheを再起動します。

/etc/init.d/httpd restart

あとは新しいドキュメントルート/home/httpd/public_htmlにindex.htmlを置くだけです。置いたらWebブラウザでちゃんと表示されるか確認してみましょう。以下の作業はrootで行います。

mkdir -p /home/httpd/public_html
echo "<html><body><h1>TEST</h1></body></html>" > /home/httpd/public_html/index.html
chown -R httpd: /home/httpd

Reference