0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

.htaccessの差分が招くリダイレクトループを防ぐ:デプロイ前チェックリスト実践ガイド

0
Posted at

環境情報

  • Webサーバ: Apache 2.4.x (本番/テスト共通)
  • ドメイン構成: サブドメイン + パスベースのリダイレクト
  • デプロイ方式: FTP / rsync / CIパイプライン
  • 管理対象ファイル: .htaccess, index.php, wp-config.php

はじめに:見落としがちな「.htaccessの環境差分」

筆者は先日、本番環境へのデプロイ後に突如として発生したリダイレクトループに悩まされた。原因は、テスト環境と本番環境で.htaccessの設定が異なっていたことだ。テストでは正常に動作していたリダイレクトルールが、本番サーバのディレクトリ構造やモジュール有効状態によって無限ループを引き起こした。

このようなトラブルは、.htaccessに限らず、php.ininginx.confなど環境依存の設定ファイル全般で起こりうる。本記事では、具体的な事例をもとに、デプロイ前に必ず確認すべき「差分チェックリスト」の作成手順と、自動化による予防策を紹介する。

事例:本番環境で発生したリダイレクトループの詳細

発生した状況

  • テスト環境: http://test.example.com/sub/https://test.example.com/sub/ にリダイレクト(末尾スラッシュ付き)
  • 本番環境: http://example.com/subhttps://example.com/sub/ にリダイレクト(末尾スラッシュ追加+HTTPS)

テスト環境の.htaccess:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

本番環境の.htaccess(間違った状態):

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !^/sub/
RewriteRule ^sub$ /sub/ [R=301,L]

一見問題なさそうだが、本番環境ではsubディレクトリ配下にindex.phpが存在し、かつDirectoryIndexの設定が異なっていた。その結果、/sub/へのリダイレクトが再度/subに書き換えられ、ループが発生した。

ハマりポイント

  • テスト環境ではDirectoryIndexの設定がindex.htmlのみだったため、リダイレクトが正しく終了した。
  • 本番環境ではDirectoryIndex index.phpが優先され、/sub/へのアクセスが内部的に/sub/index.phpにマッピングされ、さらに別のRewriteRuleが発動してループ。
  • このようなモジュールやディレクティブの有効状態の違いは、.htaccess単体では検出が難しい。

なぜ差分が生まれるのか:環境間の設定差異の原因

  • 開発環境(ローカル)とステージング環境、本番環境でApacheのバージョンやモジュール構成が異なる
  • .htaccessがリポジトリ管理外(.gitignoreなど)で、手動で配置されるケース
  • デプロイスクリプトが.htaccessを上書きしない設定になっている
  • 複数人開発で.htaccessの変更履歴が追跡できていない

デプロイ前差分チェックリストの作り方(ステップバイステップ)

Step 1: チェック対象ファイルの列挙

まず、環境依存が発生しうる設定ファイルをリストアップする。例:

  • .htaccess(ルートおよびサブディレクトリ)
  • wp-config.php(WordPressの場合)
  • .env(環境変数ファイル)
  • composer.json / package.json(依存関係)
  • php.ini(カスタム設定がある場合)

Step 2: 環境ごとの設定値を比較するためのテンプレート作成

各ファイルについて、テスト環境と本番環境で共通の「基準値」を定義する。例えば:

設定項目 テスト環境の値 本番環境の値(想定) 差分チェック
RewriteBase /test/ / 要確認
HTTPS強制 OFF→ON 常にON 要確認
ベースURL http://test.example.com https://example.com 要確認
DirectoryIndex index.html index.php 要確認

Step 3: 自動比較スクリプトの作成

シェルスクリプトで、デプロイ前に2つの環境のファイルをダウンロードしてdiffを取る。

#!/bin/bash
# diff_check.sh - テスト環境と本番環境の.htaccess差分チェック

TEST_URL="https://test.example.com/.htaccess"
PROD_URL="https://example.com/.htaccess"
TEMP_DIR=$(mktemp -d)

curl -s "$TEST_URL" > "$TEMP_DIR/test_htaccess"
curl -s "$PROD_URL" > "$TEMP_DIR/prod_htaccess"

if diff "$TEMP_DIR/test_htaccess" "$TEMP_DIR/prod_htaccess" > /dev/null; then
    echo "OK: 差分なし"
else
    echo "NG: 以下に差分があります"
    diff "$TEMP_DIR/test_htaccess" "$TEMP_DIR/prod_htaccess"
fi

rm -rf "$TEMP_DIR"

注意:curlで.htaccessを取得するにはサーバ設定でAllowOverrideが適切に設定されている必要がある。実際には、リポジトリから直接比較するほうが安全。

Step 4: 重要な箇所だけを抜き出す正規表現チェック

全ての行を比較するのではなく、環境依存の項目(絶対パス、ドメイン名、ディレクトリ名)を抽出して比較する。

grep -E 'RewriteCond %{HTTP_HOST}|RewriteRule \^|RewriteBase' .htaccess

この結果を環境ごとに集約し、一致するか確認する。

よくある誤設定とその対策(FAQ形式)

Q1: RewriteBaseの設定が環境で異なる場合の対処法は?
A: RewriteBaseは相対パスに依存するため、環境ごとに動的に切り替える。可能ならRewriteBaseを使わず、フルパスRewriteRuleに統一する。

Q2: HTTPSリダイレクトでループが発生したが、なぜ?
A: リダイレクト先が再度リダイレクト条件を満たしてしまうケース。対策として、以下のように%{ENV:REDIRECT_STATUS}をチェックする。

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Q3: 本番だけ特定のRewriteRuleが効かない
A: モジュールmod_rewriteの有効状態、AllowOverrideの設定、.htaccessの配置場所(サブディレクトリに置かれているか)を確認。

チェックリストの実装例:CI/CDへの組み込み

GitHub ActionsなどのCIでプルリクエスト作成時に自動チェックする例。

# .github/workflows/htaccess-check.yml
name: Check .htaccess consistency

on: [pull_request]

jobs:
  diff-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Compare with production template
        run: |
          if diff <(grep -v '^\s*#' .htaccess) <(curl -s ${{ secrets.PROD_BASE_URL }}/.htaccess) > /dev/null; then
            echo "一致"
          else
            echo "差分があります"
            exit 1
          fi

ただし、本番サーバの.htaccessをcurlで取得するのはセキュリティ上問題があるため、実際はリポジトリ内に「本番用テンプレート」を別途管理する方法が推奨される。

総合的ベストプラクティス

  1. .htaccessは必ずGit等でバージョン管理し、環境ごとの差分は環境変数やif文で吸収する。
  2. デプロイ前に「設定ファイル差分チェックリスト」を手順書として保持し、リリース担当者が確認する。
  3. CIに組み込めるチェックは自動化し、人の目はロジックの妥当性確認に集中する。
  4. ステージング環境は本番と可能な限り同一構成にする(Apacheのバージョン、PHPモジュール、拡張子の関連付けまで)。
  5. リダイレクトルールをデバッグするときは、RewriteLog(またはLogLevel alert rewrite:trace6)を有効にし、実際の処理フローを追跡する。

まとめ

デプロイ前の一瞬の確認不足が、本番環境でのリダイレクトループという重大なインシデントにつながる。本記事で紹介したチェックリストの作成と自動化は、たった数分の手間で大きなトラブルを未然に防ぐ。特に.htaccessは「見えない設定」であるがゆえに、差分を見落としやすい。ぜひ今日から、デプロイフローに「設定ファイル差分チェック」のステップを追加してほしい。


この記事を書いた人

BENTEN Web Works — 業務自動化・システム開発のフリーランスエンジニアです。

GAS / Python / RPA を使った業務自動化や、Web制作・システム開発のご相談を承っています。
「こんなこと自動化できる?」というご質問だけでもお気軽にどうぞ。

👉 情シス代行サービス — 詳細・お問い合わせはこちら
🐦 X(旧Twitter) — 日々の知見を発信中

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?