Apache

Apache .htaccessの書き方と使い方|AllowOverride・RewriteRuleを解説

Apache 2.4の.htaccessの書き方と使い方を初心者向けに解説します。配置場所、AllowOverride・AllowOverrideList、Options、DirectoryIndex、Redirect、RewriteRule、反映されない・500エラーの原因、安全な運用まで確認できます。

この記事の目次
  1. .htaccessとは
  2. .htaccessを使うべき場面
  3. AllowOverrideで.htaccessを有効にする
  4. AllowOverrideは.htaccess自身に書けない
  5. AllowOverride Allは必須ではない
  6. AllowOverrideListでdirective単位に許可する
  7. .htaccessファイルを作成する
  8. コメントと基本構文
  9. DirectoryIndexを設定する
  10. Options -Indexesでfile一覧を防ぐ
  11. Requireでaccessを制御する
  12. Redirectで単純な転送を設定する
  13. RewriteRuleでfront controllerへ送る
  14. .htaccessのpatternは先頭slashなし
  15. RewriteBaseが必要な場合
  16. 上位・下位.htaccessの適用を理解する
  17. .htaccess変更にApache再起動は必要か
  18. .htaccessが反映されないときの確認方法
  19. 500 Internal Server Error
  20. Options not allowed here
  21. RewriteRuleが動かない
  22. 403 Forbidden
  23. 安全に編集する手順
  24. .htaccessのperformanceとsecurity
  25. .htaccess運用チェックリスト
  26. まとめ

.htaccessは、Apache HTTP Serverの設定をdirectory単位で追加・上書きするための分散設定fileです。shared hostingのようにhttpd.confを編集できない環境で、redirect、URL rewrite、directory index、access制御などを設定できます。

ただし、main server configを編集できる場合、Apache公式は同じdirectiveを<Directory>へ書く方法を推奨しています。.htaccessはrequestごとに探索・読み込みされ、利用者へserver設定を変更する権限も渡すためです。

最初に要点を整理します。

  • .htaccessは配置したdirectoryと、その配下のrequestへ適用される
  • 利用可否はhttpd.conf側のAllowOverrideAllowOverrideListで決まる
  • AllowOverride Allは必須ではなく、必要な権限だけ許可する
  • 変更は次のrequestから読まれるため、通常Apacheのreloadは不要
  • syntax errorや許可されないdirectiveはHTTP 500の原因になる

この記事ではApache 2.4を前提に、作成方法、権限設定、基本例、RewriteRule、error診断まで解説します。

.htaccessとは

.htaccessは「distributed configuration file」と呼ばれます。通常のfile名は.htaccessですが、server管理者はAccessFileNameで変更できます。

# main server configでfile名を変更する例
AccessFileName ".config"

一般的な環境ではfile名を変えず、DocumentRootまたは設定したいsubdirectoryへ配置します。

/var/www/example/public/
├── .htaccess
├── index.php
├── assets/
└── admin/
    └── .htaccess

rootの.htaccessはpublic directory以下へ影響します。admin directoryにも.htaccessがあれば、両方のconfigがdirectiveごとのmerge ruleに従って評価されます。

.htaccessを使うべき場面

次のようにmain server configを編集できない場合が主な用途です。

  • shared hostingでhttpd.confやVirtualHostへaccessできない
  • directory単位の設定をsite運営者へ委任する必要がある
  • WordPressなどapplicationがrewrite ruleを管理する運用になっている

server・containerを自分で管理できるなら、同じ設定をVirtualHost内のDirectory sectionへ置くほうが明確です。

<Directory "/var/www/example/public">
    Options -Indexes
    DirectoryIndex index.php index.html
</Directory>

server側の設定場所、VirtualHost、Directoryの作り方はApache httpd.confの場所と設定方法で解説しています。

AllowOverrideで.htaccessを有効にする

.htaccessを置くだけでは、すべてのdirectiveが使えるわけではありません。server管理者がhttpd.conf、apache2.conf、VirtualHostなどのDirectory sectionで許可します。

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

この例はFileInfoとIndexes classのdirectiveを.htaccessで使えるようにします。Require all grantedはApache 2.4のauthorizationです。

AllowOverrideは.htaccess自身に書けない

次の設定を.htaccessへ追加しても、自分自身の権限を広げることはできません。

# .htaccessへ書いて有効化することはできない
AllowOverride All

AllowOverrideはserver config・VirtualHost・Directory contextで管理者が設定します。shared hostingではhosting providerが定めた許可範囲を確認します。

AllowOverride Allは必須ではない

すべてのclassを許可する必要はありません。必要な用途に絞ります。

class 主な用途 directive例
AuthConfig authentication AuthType、AuthUserFile
FileInfo URL mapping・header・content type RewriteRule、Redirect、Header
Indexes directory index DirectoryIndex
Limit host・request access制御 Require
Options directory feature Options

各directiveのApache公式docsにはContextとOverrideが記載されています。.htaccessがContextに含まれ、serverのAllowOverrideに必要なclassがあるか確認します。詳しい読み方はApacheのcontextとdirectiveを参照してください。

AllowOverrideListでdirective単位に許可する

Apache 2.4では、AllowOverrideListで許可するdirective名を個別指定できます。

<Directory "/var/www/example/public">
    AllowOverride None
    AllowOverrideList RewriteEngine RewriteCond RewriteRule
    Require all granted
</Directory>

この例ではrewriteに必要な3directiveだけを許可します。指定されていないdirectiveを.htaccessへ書くとserver errorになります。

category単位のAllowOverrideより細かく制限できるため、applicationが必要とするdirectiveを把握できる環境では有効です。

.htaccessファイルを作成する

file名は先頭がdotの.htaccessです。macOS・Linuxやfile managerではhidden fileとして表示されない場合があります。

作成時は次を確認します。

  • .htaccess.txtになっていない
  • plain textで保存している
  • Apache processがfileとparent directoryを読み取れる
  • Web application processから不用意に書き換えられないpermissionにする
  • 変更前のfileをbackupしてすぐ戻せる

最小の動作確認にはcommentだけでも構いません。

# Site-specific Apache settings

コメントと基本構文

#から行末まではcommentです。directive名とargumentを空白で区切ります。

# index.phpを先に探し、なければindex.htmlを探す
DirectoryIndex index.php index.html

# directory listingを無効化する
Options -Indexes

pathなどに空白がある場合はquoteします。main configと基本構文は同じですが、すべてのdirectiveを.htaccessへ書けるわけではありません。

DirectoryIndexを設定する

directory URLへaccessしたときに探すfileを指定します。

DirectoryIndex index.php index.html

https://example.com/docs/へのrequestなら、docs directory内のindex.php、次にindex.htmlを探します。

DirectoryIndexを.htaccessで使うには、通常AllowOverrideのIndexes classまたはAllowOverrideListでの明示許可が必要です。

Options -Indexesでfile一覧を防ぐ

DirectoryIndexに該当するfileがなく、Indexesが有効だとdirectory内のfile一覧が表示される場合があります。

Options -Indexes

-は既存OptionsからIndexesだけを無効化する意味です。Options Allのように不要なfeatureまで広く有効化せず、差分を明示します。

Options directiveにはAllowOverride OptionsまたはAllowOverrideListの許可が必要です。許可されていない環境で書くと500 errorになります。

Requireでaccessを制御する

Apache 2.4ではRequireでauthorizationを設定します。

# すべてのrequestを拒否
Require all denied

特定IP addressだけ許可する例です。

Require ip 192.0.2.10 198.51.100.0/24

複数条件を組み合わせる場合はRequireAll・RequireAnyなどのauthorization containerを使います。古いApache 2.2向けのOrderAllow fromDeny fromとApache 2.4のRequireを安易に混在させません。

Requireを.htaccessで使うにはLimitまたはAuthConfigなど、使うproviderに対応したoverride権限を確認します。hosting環境のaccess制御機能が別にある場合は、その運用との競合も確認してください。

Redirectで単純な転送を設定する

単純な旧URLから新URLへの転送はmod_aliasのRedirectで書けます。

Redirect 302 "/old-page" "/new-page"

最初は302 temporary redirectでLocationと転送先を確認し、恒久移転だと確定してから301へ変更します。

Redirect 301 "/old-page" "/new-page"

browserやsearch engineは301を長くcacheすることがあります。誤った301は修正後も古い転送が見えるため、private windowやcurl -Iでも確認します。

複数条件・query string・file存在判定が必要ならRewriteRuleを使います。redirect loopを含む詳しい設計は.htaccessでredirectする方法で分離して解説しています。

RewriteRuleでfront controllerへ送る

存在しないfile・directoryへのrequestをindex.phpへ送る基本例です。

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [END]
  • !-f: 実在fileでない場合
  • !-d: 実在directoryでない場合
  • RewriteRule ^: 残りのURL pathへmatch
  • [END]: 現在のper-directory rewrite処理を終了

mod_rewriteがloadされ、AllowOverride FileInfoまたは必要なAllowOverrideListが設定されている必要があります。

.htaccessのpatternは先頭slashなし

.htaccessのRewriteRuleは、配置directoryのprefixを除いたpathへmatchします。patternを^/productsで始めるとmatchしません。

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

この例でRewriteRuleが見るのはproducts/42です。/shop/も先頭slashも含みません。

RewriteRuleのpattern・substitution・flagはApache RewriteRuleの基本で詳しく扱っています。

RewriteBaseが必要な場合

多くの一般的な構成ではRewriteBaseを明示する必要はありません。AliasやsymlinkでURL pathとfilesystem pathが異なる、subdirectory applicationでrelative substitutionが意図しない場所へ解決される場合に確認します。

RewriteEngine On
RewriteBase "/shop/"
RewriteRule "^products$" "index.php?page=products" [END,QSA]

意味を確認せずにすべてのsampleへRewriteBaseを追加しないようにします。

上位・下位.htaccessの適用を理解する

上位directoryと下位directoryの.htaccessが両方存在する場合、「下位が必ず上位をすべて上書きする」とは限りません。directiveごとにmerge方法が異なります。

特にmod_rewriteのrule inheritanceには独自の扱いがあり、subdirectoryに別の.htaccessがあるとparentのrule setが想定どおり継承されない場合があります。必要ならRewriteOptionsのInherit系設定を公式docsで確認します。

まずは.htaccessを不用意に階層ごとへ増やさず、site rootへ集約できるか検討します。複数fileが必要なら、各fileの責務と適用directoryを記録します。

.htaccess変更にApache再起動は必要か

.htaccessはrequest時に探索・読み込みされるため、通常はApacheのrestart・reloadなしで次のrequestから反映されます。

これは同時に、間違った設定もすぐrequestへ影響するという意味です。syntax errorや許可されないdirectiveがあると、そのdirectoryへのrequestが500になることがあります。

main server config側でAllowOverrideやmoduleを変更した場合は、server configの構文checkとreloadが必要です。

.htaccessが反映されないときの確認方法

次の順番で切り分けます。

  1. file名が正確に.htaccessか確認する
  2. requestされるfilesystem directoryと配置場所が一致するか確認する
  3. 親Directory sectionのAllowOverride・AllowOverrideListを確認する
  4. directiveの公式docsでContextとOverrideを確認する
  5. 必要なmoduleがloadされているか確認する
  6. file・directory permissionを確認する
  7. Apache error logを確認する
  8. redirectはbrowser cacheを避けてstatusとLocationを確認する

500 Internal Server Error

最初に直前の変更を戻し、siteを復旧します。その後error logでfile・line・messageを確認します。

代表的な原因です。

  • directive名やargumentの誤り
  • そのdirectiveが.htaccess contextで使えない
  • AllowOverrideで必要なclassが許可されていない
  • moduleがloadされていない
  • quoteやregular expressionのsyntax error

Options not allowed here

Options overrideが許可されていない可能性があります。shared hostingでは勝手にAllowOverrideを変更できないため、providerの仕様を確認します。server管理者ならAllowOverride Optionsではなく、必要に応じてAllowOverrideListでOptionsだけを許可する方法も検討します。

RewriteRuleが動かない

RewriteEngine On、mod_rewrite、FileInfo権限、patternの先頭slash、配置directory、実在file / directoryのRewriteCondを確認します。

debug時はserver config側で一時的にrewrite log levelを上げられますが、productionでtrace levelを長時間有効にすると大量のlogとperformance低下につながります。

403 Forbidden

Requireによるdeny、filesystem permission、Directory側のaccess設定、Options、symlink policyを確認します。.htaccessだけでなく、main configとVirtualHostを含むmerge結果で判断します。

安全に編集する手順

  1. 現在の.htaccessを別名でbackupする
  2. 一度に1目的だけ変更する
  3. redirectは302でtestする
  4. 正常URL・存在しないURL・管理画面・static fileを確認する
  5. HTTP status、Location、response bodyを確認する
  6. error logに新しいwarning・errorがないか確認する
  7. 恒久移転を確認してから301へ変更する

command lineでheaderだけを確認できます。

curl -I https://example.com/old-page

WordPressやframeworkが.htaccessの一部を自動生成する場合は、管理範囲を示すcommentの内側を手作業で変更しないようにします。次回の設定保存で上書きされる可能性があります。

.htaccessのperformanceとsecurity

AllowOverrideが有効なdirectoryでは、Apacheはrequestされたfileまでのpathで.htaccessを探索します。fileが存在しなくても探索costが発生し、存在すればrequestごとに読み込み・parseされます。

また、.htaccessを編集できるuserへ、許可したdirectiveの範囲でserver behaviorを変える権限を渡します。

対策は次のとおりです。

  • main configを編集できるならDirectory sectionへ移す
  • 不要なdirectoryはAllowOverride Noneにする
  • Allではなく必要なoverride classだけ許可する
  • 可能ならAllowOverrideListでdirective名を限定する
  • .htaccessをapplicationから不用意に書き込み可能にしない
  • DocumentRootには公開してよいfileだけを置く

.htaccess運用チェックリスト

  • main server configへ書けない理由がある
  • 配置directoryと影響範囲を把握した
  • AllowOverride Allを無条件に使っていない
  • directiveのContextとOverrideを公式docsで確認した
  • AllowOverrideListで絞れるか検討した
  • Apache 2.4のRequireを使い、2.2記法を混在させていない
  • RewriteRule patternを先頭slashで始めていない
  • redirectは302で確認してから301へ変更した
  • backupと即時rollback手順がある
  • HTTP status・Location・error logを確認した

まとめ

.htaccessはdirectory単位でApache設定を変更できる便利なfileですが、使えるdirectiveはserver側のAllowOverride・AllowOverrideListで決まります。AllowOverride Allは必須ではなく、FileInfo、Indexes、Optionsなど必要なclass、またはdirective名だけを許可します。

基本的なDirectoryIndex、Options、Require、Redirect、RewriteRuleを目的別に使い、per-directory rewriteではpatternの先頭slashとdirectory prefixが除かれる点に注意します。

main server configを編集できる場合はDirectory sectionを優先し、.htaccessが必要な環境ではbackup、最小権限、302 test、HTTP・error log確認を一連の手順にしてください。