Apache

Apacheのディレクティブとコンテキストとは|Directory・Location・.htaccessの違い

Apache 2.4のディレクティブとコンテキストを初心者向けに解説します。server config、VirtualHost、directory、.htaccessの違い、Directory・Files・Location・Ifの対象、Context・Overrideの読み方、sectionのmerge順序とエラー診断まで確認できます。

この記事の目次
  1. Apacheのディレクティブとは
  2. コンテキストとは
  3. server configコンテキスト
  4. virtual hostコンテキスト
  5. directoryコンテキスト
  6. .htaccessコンテキスト
  7. ContextとOverrideの違い
  8. Apache公式ディレクティブページの読み方
  9. クイックリファレンスの記号を読む
  10. Directoryはfilesystemを対象にする
  11. DirectoryMatchで正規表現を使う
  12. Filesはファイル名を対象にする
  13. LocationはURL webspaceを対象にする
  14. Proxyは転送先resourceを対象にする
  15. IfとIfModuleは評価タイミングが違う
  16. sectionのmerge順序
  17. Directoryは短いpathから長いpathへ
  18. 「後勝ち」と決めつけない
  19. sectionのnested可否
  20. 同じdirectiveを別contextへ書いた例
  21. RewriteRuleはcontextで動作が変わる
  22. context errorの診断
  23. Directive is not allowed here
  24. Invalid command
  25. .htaccessで500になる
  26. 設定が反映されない
  27. 設定を検証するcommand
  28. Context確認チェックリスト
  29. まとめ

Apache HTTP Serverの「ディレクティブ」は設定項目、「コンテキスト」はそのディレクティブを記述できる場所です。

たとえばListenは待ち受けportを決めるdirectiveで、server configにだけ書けます。DirectoryIndexはserver config、VirtualHost、directory section、.htaccessで使えます。

Listen 80
DirectoryIndex index.php index.html

Apache 2.4公式docsのContext・Overrideを読めるようになると、「このディレクティブはここでは使えません」「.htaccessに書くと500になる」といったerrorを自分で診断できます。

この記事では、4つのcontext、Directory・Files・Locationの違い、sectionのmerge順序まで順番に解説します。

Apacheのディレクティブとは

directiveはApacheの動作を設定する命令です。基本構文はdirective名の後ろへ空白区切りでargumentを渡します。

ServerName example.com
DocumentRoot "/var/www/example/public"
DirectoryIndex index.php index.html

この例ではServerName、DocumentRoot、DirectoryIndexがdirectiveです。example.comやpath、file名がargumentです。

directiveごとに次が異なります。

  • 必要なargumentとsyntax
  • 省略時のdefault
  • 記述できるcontext
  • .htaccessで必要なoverride class
  • directiveを提供するmodule
  • 利用できるApache version・platform

コンテキストとは

contextは、directiveが合法に使えるconfiguration上の場所です。Apache 2.4公式docsでは主に次の4種類で示されます。

context 意味
server config main設定fileのtop level httpd.conf、apache2.conf、include file
virtual host <VirtualHost> host・IP・portごとの設定
directory requestへmatchするsection内 Directory、Files、Location、If、Proxyなど
.htaccess directoryごとの分散設定file /var/www/example/public/.htaccess

「server config」は設定file内ならどこでもよいという意味ではありません。VirtualHostやDirectoryなどsection containerの外側にあるglobal contextを表します。

server configコンテキスト

server configはhttpd.confやapache2.confなどのtop levelです。Includeで読み込まれたfileも、Includeが置かれた位置のcontextとして扱われます。

# server config
Listen 80
PidFile "logs/httpd.pid"
IncludeOptional "conf.d/*.conf"

Apache 2.4のconfigurationは複数fileへ分割されることが一般的です。古い構成名を暗記するのではなく、実際のmain fileとIncludeを確認します。

httpd.confの場所、HTTPD_ROOT、Include、構文確認はApache httpd.confの設定方法で詳しく解説しています。

virtual hostコンテキスト

virtual host contextは<VirtualHost>内です。1つのApache processで、hostname・IP address・portごとに異なるsite設定を持たせます。

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot "/var/www/example/public"
</VirtualHost>

<VirtualHost *:80>
    ServerName api.example.com
    DocumentRoot "/var/www/api/public"
</VirtualHost>

VirtualHostは「仮想software」ではなく、選択されたhost・address・portへ適用するconfiguration containerです。

同じdirectiveがglobalとVirtualHostの両方にある場合、VirtualHost側のsectionは対応するglobal sectionの後に適用されます。ただし最終値のmerge方法はdirectiveを提供するmoduleによって異なります。

directoryコンテキスト

Apache公式docsでcontextがdirectoryとなっているdirectiveは、一般に次のsection内で使用できます。

  • <Directory> / <DirectoryMatch>
  • <Files> / <FilesMatch>
  • <Location> / <LocationMatch>
  • <If>
  • <Proxy> / <ProxyMatch>

ただし、すべてのdirectory-context directiveがすべてのsectionで同じように使えるわけではありません。

代表的な例外です。

  • AllowOverrideはDirectory sectionだけ
  • Options FollowSymLinks系はDirectoryまたは.htaccess
  • OptionsはFiles / FilesMatchでは使えない

個別directiveのContextとsection固有の制約を両方確認します。

.htaccessコンテキスト

Contextに.htaccessが含まれるdirectiveは分散設定fileへ書けます。ただし、server側でAllowOverrideまたはAllowOverrideListによる許可も必要です。

# server config側
<Directory "/var/www/example/public">
    AllowOverride FileInfo Indexes
    Require all granted
</Directory>
# /var/www/example/public/.htaccess
DirectoryIndex index.php index.html
RewriteEngine On

Contextに.htaccessと書かれていても、Override欄のclassがserver側で許可されていなければ処理されません。

AllowOverride・AllowOverrideList・RewriteRuleの基本はApache .htaccessの書き方で実践的に解説しています。

ContextとOverrideの違い

Contextは「どの種類の場所に書けるか」、Overrideは「.htaccessで使うために必要な許可class」です。

たとえばDirectoryIndexのdocsには、次のような情報があります。

Context server config, virtual host, directory, .htaccess
Override Indexes
Module mod_dir

main config、VirtualHost、Directory sectionならContextを満たせば使えます。.htaccessではさらにAllowOverride IndexesまたはAllowOverrideListによるDirectoryIndexの許可が必要です。

Apache公式ディレクティブページの読み方

directive pageの項目を上から確認します。

項目 確認内容
Description directiveの目的
Syntax argument、optional値、繰り返し
Default directiveを省略した場合の値
Context 書けるconfiguration場所
Override .htaccessで必要なclass
Status / Module core・base・extensionと提供module
Compatibility 対応version・platform・追加時期

Default欄はApache本体がdirective省略時に使う値です。distributionが配布するdefault configに実際に書かれた値と同じとは限りません。

クイックリファレンスの記号を読む

Apache公式Directive Quick Referenceではcontextを短い記号で示します。

記号 context
s server config
v virtual host
d directory
h .htaccess
p proxy section

たとえばsvdhなら4contextで使用可能、sだけならserver config top levelだけです。

quick referenceは一覧確認に便利ですが、細かな制約・security warning・version差は個別directive pageも開いて確認します。

Directoryはfilesystemを対象にする

Directory sectionはfilesystem pathと、そのsubdirectory・fileを対象にします。

<Directory "/var/www/example/public">
    Options -Indexes
    AllowOverride None
    Require all granted
</Directory>

/var/www/example/publicはURLではなくserver上のabsolute file pathです。file access、Options、AllowOverrideなどfilesystemに関する設定はDirectoryを基本にします。

Directory sectionはserver configまたはVirtualHost内へ記述します。.htaccessの中へDirectory containerは書けません。

DirectoryMatchで正規表現を使う

regular expressionでfilesystem pathをmatchする場合はDirectoryMatchを使うと意図が明確です。

<DirectoryMatch "^/var/www/[^/]+/public$">
    Options -Indexes
</DirectoryMatch>

regexはApacheが利用するPCRE系syntaxとして、version・escaping・path separatorを確認します。単一pathなら通常のDirectoryを優先します。

Filesはファイル名を対象にする

Files sectionはdirectoryに関係なくfile名へmatchします。

<Files "private.html">
    Require all denied
</Files>

特定extensionなどregular expressionが必要ならFilesMatchを使います。

<FilesMatch "\.(bak|sql)$">
    Require all denied
</FilesMatch>

特定filesystem directory内のfileだけに絞る場合は、Directoryの内側へFilesをnestedできます。

<Directory "/var/www/example/private">
    <Files "report.html">
        Require all denied
    </Files>
</Directory>

LocationはURL webspaceを対象にする

Location sectionはclientから見えるURL pathを対象にします。filesystemへ存在しないhandler、server-status、proxy endpointなどにも適用できます。

<Location "/internal-status">
    Require ip 192.0.2.0/24
</Location>

/internal-statusはURL pathです。/var/www/...のfilesystem pathではありません。

filesystem fileのaccess制御はDirectory / Filesを基本にします。Locationはmerge順でDirectory・Filesより後に評価され、重なるauthorization設定を上書きして意図せずaccessを許可する危険があります。

Proxyは転送先resourceを対象にする

Proxy / ProxyMatch sectionはreverse proxy先など、proxied resourceへ設定を適用します。

<Proxy "http://backend.example.internal/*">
    Require all granted
</Proxy>

外部・内部backendへのaccess policy、authenticationなどをURL webspaceのLocationと混同せず管理します。proxy directiveが使えるcontextは個別docsで確認します。

IfとIfModuleは評価タイミングが違う

<If>はrequest時のexpressionで設定を適用します。

<If "%{REQUEST_URI} =~ m#^/admin/#">
    Require ip 192.0.2.0/24
</If>

一方、IfModule・IfDefine・IfVersionはstartup・restart時にconditionを評価します。

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
</IfModule>

IfModuleはoptionalなmodule差を吸収するときに使います。必須directiveを囲むと、moduleがない場合に有用なstartup errorが出ず、設定が黙って無視される点に注意します。

sectionのmerge順序

1requestへ複数sectionがmatchすると、Apacheは決められた順序でmoduleごとのconfigurationをmergeします。

基本順序は次のとおりです。

  1. 通常のDirectoryと、許可された.htaccess
  2. DirectoryMatchと<Directory "~">
  3. FilesとFilesMatch
  4. LocationとLocationMatch
  5. If

VirtualHost内のsectionは、対応するglobal sectionの後に適用されます。Proxy requestではProxy sectionがDirectoryの役割を置き換える場合があります。

Directoryは短いpathから長いpathへ

通常のDirectory sectionはconfiguration fileの記述順だけではなく、短いdirectory componentから長いものへ処理されます。

<Directory "/var/www">
    Require all denied
</Directory>

<Directory "/var/www/example/public">
    Require all granted
</Directory>

同じpathへ複数Directoryがmatchする場合や、別種類のsectionが重なる場合はさらにmerge ruleが関係します。

「後勝ち」と決めつけない

mergeは単純なtext上書きではありません。各moduleがdirectiveの値をどうcombineするか決めます。

たとえばOptionsの相対指定、authorizationのAuthMerging、rewrite rule inheritanceなどは固有のruleがあります。最終結果が不明な場合は、個別module docsと実際のrequest・logで確認します。

sectionのnested可否

一部sectionはnestedできます。

  • FilesはDirectory内へ置ける
  • IfはDirectory・Location・Files内へ置ける
  • Ifを別のIfへ直接nestedする構成には制約がある
  • VirtualHostはserver config top levelで定義する

「HTML tagのように見えるから自由に入れ子にできる」と考えず、section directive自身のContextとApache Configuration Sections docsを確認します。

同じdirectiveを別contextへ書いた例

DirectoryIndexは複数contextで使えます。

# server全体のdefault
DirectoryIndex index.html
# 特定VirtualHost
<VirtualHost *:80>
    ServerName app.example.com
    DirectoryIndex index.php index.html
</VirtualHost>
# 特定filesystem directory
<Directory "/var/www/docs">
    DirectoryIndex home.html
</Directory>
# .htaccess。AllowOverride Indexesが必要
DirectoryIndex landing.html

同じdirectiveでも、どのrequestへ適用したいかでcontextを選びます。

RewriteRuleはcontextで動作が変わる

RewriteRuleはserver / VirtualHost contextと、Directory / .htaccessのper-directory contextでpatternの対象が異なります。

.htaccessでは配置directoryのprefixと先頭slashが除かれます。

# /shop/.htaccess で /shop/products/42 にmatch
RewriteRule "^products/([0-9]+)$" "product.php?id=$1" [END,QSA]

同じ文字列を別contextへ移動するだけでは同じ動作にならない代表例です。pattern・substitution・flagの詳細はApache RewriteRuleの基本を参照してください。

context errorの診断

Directive is not allowed here

directiveを許可されないcontextへ書いています。公式directive pageのContextを確認し、server top level、VirtualHost、Directory、.htaccessの正しい場所へ移します。

Invalid command

directive名のtypo、提供moduleがloadされていない、Apache versionに存在しないdirectiveの可能性があります。

apachectl -M
apachectl -V

loaded moduleとversionを確認します。

.htaccessで500になる

Contextに.htaccessが含まれるか、Override classがAllowOverrideで許可されているか、AllowOverrideListにdirective名があるかを確認します。

.htaccessはrequest時にparseされるため、main configのsyntax checkが成功しても、実際に対象URLへrequestして初めてerrorが分かる場合があります。

設定が反映されない

別VirtualHostが選ばれている、filesystem pathとURL pathを混同している、より後のLocation / Ifで値がmergeされた、別.htaccessやinclude fileがある可能性を確認します。

設定を検証するcommand

main server configはreload前にsyntaxを検証します。

apachectl -t
apachectl -S
apachectl -M
-t 設定fileのsyntax
-S VirtualHostのparse結果
-M loaded module

.htaccessは対象URLへrequestし、HTTP statusとerror logを確認します。startup error・request error・module別logの調べ方はApacheログの場所と確認方法で解説しています。

Context確認チェックリスト

  • directiveの個別docsでSyntax・Context・Overrideを確認した
  • quick referenceのs / v / d / h / pを読める
  • server configはsection外のglobal contextだと理解した
  • VirtualHostはhost・address・port単位のconfiguration containerとして使った
  • filesystemはDirectory / Files、URLはLocationで分けた
  • .htaccessではAllowOverride・AllowOverrideListも確認した
  • IfとIfModuleの評価timingを分けた
  • Directory→DirectoryMatch→Files→Location→Ifのmerge順を確認した
  • 単純な後勝ちと決めつけず、module固有のmerge ruleを確認した
  • main configはsyntax・vhost・module、.htaccessは実requestとlogで検証した

まとめ

Apacheのdirectiveは設定項目、contextはそのdirectiveを合法に記述できる場所です。公式docsではserver config、virtual host、directory、.htaccessを確認し、.htaccessの場合はOverrideとAllowOverrideも照合します。

Directoryはfilesystem、Filesはfile名、LocationはURL webspace、Proxyはproxied resourceを対象にします。複数sectionがmatchすると、Directory・DirectoryMatch・Files・Location・Ifの順でmoduleごとにmergeされます。

設定例をコピーする前にContext・Module・Compatibilityを確認し、main configはapachectl、.htaccessは実際のHTTP requestとerror logで検証してください。