httpd.confについて調べたのでまとめたよ

最近学科の友人3人とサーバ/セキュリティについての勉強会を週1で行っていて、毎回何か調べてくることになっており、今回は apache の設定について少し調べてきました。初心者がまとめたので間違っている部分があるかもしれませんが、勉強の役に立てて頂ければ幸いです。

  • httpd.confはどこにある?
  • 最小限のhttpd.conf
  • 3つのセクション
    • セクション1: GlobalEnvironment
    • セクション2: MainServerConfiguration
    • セクション3: VirtualHosts
  • モジュールの追加
  • 外部設定ファイルの読込み
  • サーバリソースの監視方法

httpd.confはどこにある?

OSによって異なりますが、以下の階層に置いてある可能性が高いです。

| CentOS、FedoraなどRed Hat系 | /etc/httpd/conf/ | | SUSE系、MacOSX | /etc/apache2/ | | ソースからインストールした場合 | /usr/local/apache2/conf/ |

最小限のhttpd.conf

httpd.conf は標準でもコメント含めて1000行くらい記述してあることが多いですが、以下の少ない設定でも動作します。httpd.confの理解を目的とするのであれば、小さな設定から徐々に設定項目を増やしていくことをお勧めします。ちなみにhttpd.confは再起動した時点で反映されます。

Listen 80ServerRoot "/etc/httpd"DocumentRoot "/var/www/html/"User nobody Group nobody\<IfModule prefork.c\>MaxClients 150StartServers 5MinSpareServers 5MaxSpareServers 15\</IfModule\>\<IfModule worker.c\>StartServers 2MaxClients 150MinSpareThreads 25MaxSpareThreads 75ThreadsPerChild 25MaxRequestsPerChild 0\</IfModule\>MaxRequestsPerChild 0ErrorLog logs/error\_log\<Directory /\> Options FollowSymLinks AllowOverride None\</Directory\>

3つのセクション

httpd.confの設定項目(ディレクティブ)は、その影響範囲によって主に下記の3つに分類されます。

| Section1 | GlobalEnvironment | Apache全体に影響を及ぼします | | Section2 | MainServerConfiguration | メインのサーバに影響を及ぼします。VirtualHost設定時のデフォルト値にもなります | | Section3 | VirtualHosts | 指定したドメイン/ホストに影響を与えます。MainServerConfigurationを上書きします |

セクション1: GlobalEnvironment
# SampleServerRoot "/usr/local/apache2"Listen 80KeepAlive On KeepAliveTimeout 15MaxKeepAliveRequests 100Timeout 300

| ServerRoot | Apacheをインストールした場所のパス。以降のディレクトリ指定で相対パスを利用する場合等に利用 | | Listen | 特定のIPアドレスやポート番号だけを受け付ける指定。VirtualHostではここの設定のポート範囲内のみ使用できる | | KeepAlive | クライアントからの接続要求時にHTTPセッションを即座に閉じず一定時間保っておく設定。パフォーマンス向上に繋がる。ブラウザ側の対応に依存する | | KeepAliveTimeout | HTTPセッションを保っておく秒数。値を大きくすると転送完了後もクライアントとの接続を維持したままになり他のクライアントへの応答が遅れる。1ページ当たりの平均的な転送時間+αが参考値。サーバのリソース消費を嫌うなら2程度の極端な値に設定するなど | | MaxKeepAliveRequests | KeepAlive有効時に接続要求を受け付ける数の最大許容値。高い値に設定しておくことが推奨されている。大きな値を設定すると一度のリクエスト処理数が増える代わりに他の接続が割り込むタイミングが遅れる。1ページあたりの平均ファイル数+αが参考値 | | Timeout | クライアントから接続要求を受け取ってタイムアウトするまでの秒数。これを過ぎてもパケットが送信されない場合ブラウザにエラーを返す |

セクション2: MainServerConfiguration
# SampleUser apache Group apache ServerName example.com ServerAdmin [email protected] DocumentRoot "/var/www/html"\<Directory /\> ... \</Directory\>DirectoryIndex index.html index.php TypesConfig conf/mime.types DefaultType text/plain ServerTokens Prod ServerSignature Off Alias /icons/ "/usr/local/apache2/icons/"

| User / Group | サーバーを実行する為のユーザとグループの指定。apache用に特定のユーザとグループを作成しておくことが推奨されている | | ServerName | サーバ自身が使用するサーバ名とポート番号の指定。BINDで自動取得出来る場合があるが起動時の問題を避けるため指定しておくことが推奨されている | | ServerAdmin | エラーメッセージ等に表示される管理者メールアドレス | | DocumentRoot | ドキュメントルートの指定。基本的にここより上位階層にはアクセス出来ないがSymbolicLinkやAliasを使用すれば実現可能。Aliasはmod_aliasで提供されている機能 | | ... | 個々のディレクトリに対する設定。サーバールート(/)に対しての設定は必須 | | DirectoryIndex | スラッシュ「/」で終わるURLを指定した際にデフォルトで表示するファイルを指定。指定したファイルが存在しない場合は、404または403エラーコードを返す | | TypesConfig | ファイル拡張子とMIMEタイプのマッピングファイルの指定。.htaccessでもAddType application/x-smaf mmfなどで追加できる | | DefaultType | MIMEタイプファイルに記述が無かった場合の扱いを指定 | | ServerTokens | エラーメッセージ出力時等のサーバ情報を制限。情報が多い順に Full, OS, Min, Minor, Major, Prod | | ServerSignature | エラーメッセージ等をクライアントに返す際のフッターラインの表示を指定。On, Off, EMail(mailto:...が付く)が指定可能 | | Alias | 第1引数へのアクセスを第2引数へ繋ぐ。/icons/のように後ろにスラッシュが入った場合は/iconsというURL自体はエイリアスされないので注意 |

セクション3: VirtualHosts
# SampleNameVirtualHost \*:80\<VirtualHost \*:80\> ServerName arumakan.org DocumentRoot /var/www/lokka/public \<Directory /var/www/lokka/public\> Allow from all \</Directory\>\</VirtualHost\>\<VirtualHost \*:80\> ServerName gakuweb.com DocumentRoot /var/www/eden/public \<Directory /var/www/html\> Allow from all \</Directory\>\</VirtualHost\>\<VirtualHost \*:80\> ServerName 19950117.jp DocumentRoot /var/www/shinsaiNow/public \<Directory /var/www/html\> Allow from all \</Directory\>\</VirtualHost\>

上記の例の場合、全てのIPアドレスの80番ポートへのアクセスはNameVirtualHostが全て扱い、ServerNameに設定しているドメイン名別に違うディレクトリへアクセスするようにしています。ここに記載されていないがIPアドレス自体はこのサーバを向いているというドメインにアクセスした場合は、最も上に記述しているServername arumakan.orgの設定が適用されます。

上記の例では名前ベースのVirtualHost(NameVirtualHost)を利用しています。
VirtualHostの設定には以下の2種類の方法があります(混合も可能)。

| 名前ベース | アクセスされる名前(ホスト/ドメイン)によって挙動を変える | | IPアドレスベース | アクセスされるIPアドレスによって挙動を変える |

前者は1つのサーバに対して複数の名前が与えられているとき、後者は1つのサーバに対して複数のIPアドレスが与えられている時に有効な設定です。個人でサービス開発を行っている場合には前者のケースの方が多いかと思います。例えば私の場合であれば、さくらVPSで借りているCentOSのサーバにIPアドレスを1つ頂いていますが、そのIPアドレスに対して19950117.jpgakuweb.comという名前をドメイン取得元のDNS設定で与えています。これらは別のサービスなので、名前ベースのVirtualHostの設定を行い、ドメインによってそれぞれアクセスされるディレクトリを変えています。

名前ベースのVirtualHostを期待通りに動作させるには、アクセスがどのような流れで解決されるのかを知っておく必要があります。example.comに対してアクセスがあった時の大まかな流れを以下に示します。

  1. http://example.com に対してアクセスが行われた
  2. listen *:80 を設定しているのでApacheはこれを処理することを決めた
  3. NameVirtualHost *:80 を設定しているので主サーバー自体はこれを扱わずVirtualHostに委譲
  4. VirtualHost の中でexample.comに一致する条件を設定しているものを探す
  5. VirtualHost *:80 を設定しているものが2つあった
  6. 2つの中でServerName example.comのものを選ぶ。 無ければ1番上に記述しているものを選ぶ
  7. ServerName example.com の設定をしているVirtualHostが1つあった
  8. その中のDocumentRootを見に行く
  9. URLでファイル名が指定されていないのでindex.htmlなどを見に行く

モジュールの追加

Apacheの基本的な機能と設定の説明は以上ですが、Apacheはモジュールを追加することで機能を拡張することが出来ます。Apacheに組み込めるモジュールの種類は大きく分けて以下の2つに分類されます。

  1. コンパイル時に組み込まれるモジュール
  2. 実行時に組み込まれるモジュール

httpdに-lオプションを渡して実行すればコンパイル時に追加されているモジュールを確認できます。またApache2.0以降ではDSO(DynamicSharedObject)という機能で実行時にもモジュールを取り込めます。実行時にモジュールを組み込むにはhttpd.conf等に以下のように設定します。標準でもかなり多くのモジュールが設定されていますが、パフォーマンスに影響を与えるので、理解可能であれば必要最低限のモジュールのみ読み込むように設定した方が良いです。

X / \_ / X \< /usr/sbin/httpd -lCompiled in modules: core.c prefork.c http\_core.c mod\_so.c X / \_ / X \< cat /etc/httpd/conf/httpd.conf -n | grep LoadModule 146# LoadModule foo\_module modules/mod\_foo.so147 LoadModule auth\_basic\_module modules/mod\_auth\_basic.so 148 LoadModule auth\_digest\_module modules/mod\_auth\_digest.so 149 LoadModule authn\_file\_module modules/mod\_authn\_file.so 150 LoadModule authn\_alias\_module modules/mod\_authn\_alias.so 151 LoadModule authn\_anon\_module modules/mod\_authn\_anon.so ...

外部設定ファイルの読込み

Fedora Core / SUSE / Turbo 等のOSではconf.d/*.confという外部ファイルに設定を分け、それらを起動時に読み込む設定をhttpd.confに書くが常套手段となっています。ここのパスはServerRootで指定されたディレクトリからの相対パスなので注意してください。この設定により、ServerRoot/conf.d/ 以下の拡張子.confのファイルが全て設定ファイルとして読み込まれます。例として、http://example.com/blog へのアクセスに対してアクセスされるディレクトリをwordpressに設定するため、conf.d/wordpress.confにAliasの設定を書くなどの利用方法が挙げられます。

X / \_ / X \< cat /etc/httpd/conf/httpd.conf -n | grep \*.conf 210 Include conf.d/\*.conf X / \_ / X \< tree /etc/httpd /etc/httpd |-- conf | |-- httpd.conf | `-- magic|-- conf.d| |-- README| |-- php.conf| |-- phpmyadmin.conf| |-- proxy\_ajp.conf| |-- welcome.conf\_old| `-- wordpress.conf |-- logs -\> ../../var/log/httpd |-- modules -\> ../../usr/lib64/httpd/modules`-- run -\> ../../var/runX / \_ / X \< cat /etc/httpd/conf.d/wordpress.conf Alias /blog /var/www/wordpress

サーバリソースの監視方法

本題とは少し内容が逸れますが、設定のために必要になったのでサーバリソースの監視方法についても少し調べました。Apacheでは使用するプロセス数を設定出来ますが、これにはApacheのプロセスがサーバのリソースにどれだけ影響を与えるかを見極める必要があります。1プロセスあたりのメモリ使用量はpsコマンドやtopコマンドで調べられます。psはシステムで実行中のプロセスを表示するコマンドです。$ ps aux | grep [a]pache のように使用します。[a]と角括弧で括っているのは出力結果にgrepのプロセス自体を含めないためのハックです。真面目に書きたい人は$ ps aux | grep apache | grep -v grepとして「grepが含まれない行だけ出力する」としても良いですね。しかしgrepではpsコマンド1行目の部分が表示されず残念な感じなので、psコマンドに-u apache(USERを指定するオプション)か-C httpd(COMMANDを指定するオプション)を付けます。

# Usageps [-] [acefhjlmnrsuvwxS] [txx] [O[+|-]k1[[+|-]k2...]] [pids]# Sample - COMMANDにhttpdを含むプロセスをユーザ名と開始時刻とツリー付きで表示X / \_ / X \< ps uf -C httpd USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 18796 0.0 0.5 2350123020 ? Ss Feb21 0:00 /usr/sbin/httpd apache 18813 0.0 0.4 2351482552 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 18814 0.0 0.5 2351522608 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 18815 0.0 0.4 2351482548 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 18817 0.0 0.4 2351482540 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 18818 0.0 0.5 2351522612 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 18819 0.0 0.4 2351482544 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 18820 0.0 0.5 2351482588 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 18821 0.0 0.5 2351482556 ? S Feb21 0:01 \\_ /usr/sbin/httpd apache 17850 0.0 0.5 2351482708 ? S Feb22 0:00 \\_ /usr/sbin/httpd apache 20876 0.0 0.5 2351482804 ? S Feb22 0:00 \\_ /usr/sbin/httpd apache 19144 0.0 0.5 2351482788 ? S Feb23 0:00 \\_ /usr/sbin/httpd# Sample - uid18796のプロセス(rootが動かしているhttpd)の遷移状態をツリー表示X / \_ / X \< pstree 18796 -u -Ahttpd-+-PassengerWatchd-+-PassengerHelper-+-ruby---2\*[{ruby}] | | `-14\*[{PassengerHelper}] | |-PassengerLoggin(nobody)---{PassengerLoggin} | `-3\*[{PassengerWatchd}]`-11\*[httpd(apache)]

apacheのプロセスは、まずrootで1本起動させてから内部でUser/Groupに指定したユーザで子プロセスを複数生成します。勉強会中に友人に教えてもらったのですが、pstreeコマンドを利用すると実行中のプロセスの親子関係がツリー構造で表示されて分かりやすいです。上記の例では、rootのhttpdプロセスがapacheのhttpdプロセスを11本生成していることが分かります。またPassengerというRubyOnRailsのアプリをapacheで動かしてくれるモジュールを入れているので、その関係のプロセスも生成されています。プロセス数はapacheがよしなに調整してくれますが、これは『最小限のhttpd.conf』で記述したprefork.c内のStartServers 5(起動時)、MinSpareServers 5(最小数)、MaxSpareServers 15(最大数)の設定に基づいて管理されています。今回はこれらの設定値を最適化するためにメモリ使用量を調べた、という顛末でした。
最後に、psコマンドで利用するオプションと表示される要素について説明しておきます。

オプション

| a | 自分以外のユーザーのプロセスも表示する | | c | task_structに格納されているコマンド名を表示する | | e | 「実行命令 + 」に環境変数を付加する | | f | ツリー形式で表示する | | h | ヘッダーを表示しない | | j | pgidとsidを表示する | | l | 標準のPID,TTY,TIME,CMDに加え,F,S,UID,PPID,C,PRI,NI,ADDR,SZ,VSZ,RSS,WCHAN,STATも表示する | | m | スレッドも表示する | | n | USERとWCHANを数字で表示する | | r | 実行中のプロセスだけ表示する | | s | シグナル形式で表示する | | u | ユーザー名と開始時刻を表示する | | v | vm 形式で表示する | | w | 1行追加して表示を拡大する。wを増やすことによって行数をさらに増やせる | | x | 制御端末のないプロセスの情報も表示する | | S | 子プロセスのCPU消費時間とページ・フォルトを合計する | | txx | tty xxのプロセスのみ表示する | | pids | 表示するプロセスIDを指定する |

表示される要素の意味

| F | プロセスの状態を示すフラグ。16進数で表されている。それぞれ,00:プロセスが終了している,01:システム・プロセス(常にメモリー上に存在する), 02:親プロセスからトレースされている,04:親プロセスからトレースされ,停止している,08:プロセスがシグナルで起動できない,10:プロセスがメモリー上にあり,イベント終了までロックされている,20:プロセスがスワップできない,ことを意味している。 | | USER | プロセスの所有ユーザ | | UID | ユーザーID | | PID | プロセスID | | &CPU | CPUの占有率 | | &MEM | 実メモリでの占有率 | | SIZE | 仮想分も含めた使用サイズ[kB] | | VSZ | 仮想メモリの全サイズ | | RSS | 使用中の物理メモリー量 | | TTY | 制御端末の種類および番号 | | STAT/S | プロセスのステータス。Rは実行可能,Sは停止,Dは割り込み不可の停止,Tは停止またはトレース中,Zはゾンビ・プロセス,Wはスワップ・アウトしたプロセス,Nはナイス値が正であることを表す | | PPID | 親プロセスID | | PRI | 優先度 | | NI | ナイス値 | | WCHAN | プロセスが休眠状態の時のカーネル関数名 | | START | プロセスの開始時刻 | | TIME | プロセスの総実行時間 | | COMMAND/CMD | プロセスのコマンド名 |

参考