大多數 htaccess 轉換到 nginx 的失敗,並非因為任何單一指令無法翻譯,而是因為日積月累的小假設——關於旗標等效性、條件處理、檔案範疇、URI 比對與重新載入安全性——這些都沒有人會逐行稽核。從 Apache 的「每目錄設定模型」轉變為 Nginx 的集中式伺服器與 location 區塊,改變了每一條規則的解讀方式、它可以存在的位置,以及讓規則合理運作所需的周邊脈絡。通用型線上轉換器還會讓問題惡化,因為它們會為那些語意無法驗證的規則產出看起來合理的指令,包括 RewriteCond 相依性、未知的旗標、Alias 對應,以及無替代的破折號目標。一個較安全的起點是一個刻意範圍很窄的轉換器,它只處理可稽核的子集,列出每一行被忽略的規則及其原始行號,並把所有條件式、不熟悉或範疇模糊的內容留待人工依官方 Apache 與 Nginx 文件審查。

htaccess 轉換到 nginx 實際上會出錯的地方
每當請求進入其目錄時,Apache 都會讀取 .htaccess 檔案,重新解析它,並在由 AllowOverride 界定的「每請求設定空間」內套用它。Nginx 完全不理解這種模型。設定是集中式的:Nginx 在啟動或重新載入時一次性解析 include 檔案,建立其伺服器與 location 樹,並在任何 rewrite 處理執行之前,根據該樹解析請求。任何遷移中的第一個錯誤,就是把 .htaccess 檔案視為可直接放入的規則資料夾,而它實際上只是 Apache 分散式、請求階段行為的一個切片。
接著會產生兩個實際的後果。文件根目錄下 .htaccess 中的模式,通常會在移除目錄前綴之後才比對路徑,因此它們常以插入符開頭但沒有前置斜線。Nginx 的 rewrite 模式所看到的是以斜線開頭的 URI。任何轉換器都必須明確地彌補這個落差,而且只能針對根目錄脈絡的片段——巢狀的 .htaccess 檔案、Alias 對應,以及針對特定 location 的 Nginx 區塊,則遵循不同的規則。一個直接搜尋取代、卻忽略了前置斜線假設的轉換,會靜默地改寫錯誤的路徑。關於 Apache 如何組合這些模式的正典解釋,請參閱 Apache mod_rewrite 介紹。
第二個後果是 rewrite 處理順序不同。Apache 在 location 選取之後才執行其 rewrite 引擎,讓條件可以檢查檔案、目錄、查詢字串與標頭。Nginx 在請求生命週期的更早階段——在內容處理常式之前——就執行 rewrite,而像是 $uri 與 $request_uri 這一小組變數,雖然語意有所重疊,但在各種情況下並不完全等同於 Apache 的 %{REQUEST_URI}。即使是相同的正規表達式,兩種引擎的行為也可能不同,因為被比對的字串、跳脫方式、查詢處理與迴圈行為都不一樣。
會默默改變行為的 RewriteRule 旗標錯誤
旗標是遷移錯誤的第二大常見來源,因為它們在兩種引擎中看起來一模一樣,解析後卻對應到不同的東西。Apache 的 RewriteRule 支援一長串以方括號包起的旗標,包括 QSA(附加查詢字串)、END(停止 rewrite 引擎)、F(禁止)、G(消失)、B(反向參照跳脫)、NC(不區分大小寫)以及數個重新導向碼。Nginx 的 rewrite 支援的旗標集合明顯較小且語意不同:last、break、redirect、permanent,以及少數內部標記。安全的轉換器不能默默地把 QSA、END、F、G、B 或 NC 對應過去,因為它們的行為是引擎專屬的,若當作等價來翻譯,會改變規則實際的作用。
htaccess 轉 Nginx 轉換器刻意將自動處理的旗標集限制在 L、R、R=301 與 R=302。永久的 Apache 重新導向會變成 Nginx 的 permanent 旗標,暫時的重新導向會變成 redirect,內部的 last 規則會變成 last。當某條規則使用了該集合以外的任何旗標,工具會停止轉換該規則並回報原始行號,讓工程師能閱讀兩份手冊並手動撰寫對等的 Nginx 寫法。
有兩個相關的錯誤值得另外提出警告。首先,以單一破折號表示的 Apache「無替代目標」也會被保留。它常與會改變存取或處理方式、卻不變更 URI 的旗標並用,因此純粹的破折號並不是安全的替代——輸出這種破折號會破壞規則,甚至更糟的是,把它丟給一個完全不知所措的 location 區塊。其次,輸入內容可能已包含前置斜線的模式;根目錄脈絡的斜線插入只適用於文件記載的模式形式,其他變體必須手動移到正確的 Nginx 脈絡中。
為何 RewriteCond 行永遠不會自動翻譯
最常見的遷移錯誤,是在轉換一條 RewriteRule 時沒有同時轉換其前方的 RewriteCond。Apache 的條件可以檢查 HTTPS 狀態、主機名稱、檔案、目錄、查詢字串、標頭與擷取群組,且其在引擎中的評估順序很重要。一條本身看起來無害的規則——RewriteRule ^old/(.*)$ /new/$1 [L,R=301]——依其前方的條件不同,可能代表完全不同的意思。若將其在 Nginx 中強制轉成無條件的重新導向,可能會改變流量、造成重新導向迴圈、洩漏 Apache 版本未曾開放的路由,或漏掉原本有處理的情境。
基於這個理由,htaccess 轉 Nginx 轉換器會回報每一行 RewriteCond 及其原始行號而不進行翻譯;當某條 RewriteRule 的前方有條件時,工具也會一併抑制該規則。輸出中不會帶有任何猜測的語意;工程師應閱讀兩份文件,使用 if、map,或在適合的位置使用 server 或 location 分支,在 Nginx 中重現條件式邏輯,並在重新載入前驗證結果。一個會默默寫出看起來合理但實際不等價設定的轉換器,比一個明確把工作留給人的轉換器更危險。關於轉換器刻意不處理內容的完整目錄,請參閱 自動化 htaccess 轉 nginx 轉換的限制這篇指南。
驗證、授權、防盜連、代理邏輯、CMS front-controller 規則與複雜條件,是遷移屬於工程工作、而非批次文字取代的最明確訊號。請把任何其 Apache 行為依賴執行階段變數的規則,當作需要獨立 Nginx 區塊、獨立測試計畫,且在驗證期間盡可能使用暫時而非永久(註:原文為 permanent)重新導向的工作來處理,這樣即使行為錯誤,也能在不清除瀏覽器快取的情況下還原。
轉換器會對應的非 rewrite 指令
在轉換合約中包含三個非 rewrite 的對應,因為其 Apache 與 Nginx 的對應指令皆已文件化且穩定。下表整理了它們、雙方的行為,以及轉換器輸出的那一行。
| Apache 指令 | Apache 效果 | 轉換器輸出 |
|---|---|---|
| Options -Indexes | 停用當前目錄樹的目錄列表 | autoindex off; |
| ErrorDocument 404 /custom-404.html | 為找不到的資源提供本機 404 文件 | error_page 404 /custom-404.html; |
| Header set X-Robots-Tag "noindex, nofollow" | 為回應加入 X-Robots-Tag 標頭 | add_header X-Robots-Tag "noindex, nofollow"; |
除了這三項之外,轉換器不會自行發明 Nginx 的對應寫法。其他狀態碼、外部錯誤文件、條件式標頭、環境變數,以及像是 <If> 或 <Directory> 之類的指令容器,都需要手動遷移;而任何其 Nginx 對應指令依賴已安裝模組的項目(例如 headers 模組在許多發行版中是動態模組),則需要在 nginx -t 時額外檢查。本機 404 路徑的對應請參考 Nginx 核心 error_page 指令文件;本機路徑會原樣保留。
會讓 htaccess 轉 nginx 遷移變成停機的重新載入錯誤
即使輸出經過完善的審查,若缺乏整體紀律,仍可能在重新載入時失敗。最常導致公開站台損毀的步驟,是跳過 nginx -t、跳過備份當前設定,或以無法立即回復的方式部署。轉換器不會執行 nginx -t、不會檢查已安裝的模組、不會探查 include 的順序,也無法存取伺服器。一行設定可能在語法上正確,但對其所處的脈絡而言是錯的,而真正需要驗證的是組合後的整份設定檔。
正確的紀律順序是:備份當前設定、保持一個開啟中的回復工作階段、用 nginx -t 驗證整份組合後的檔案,並在重新載入前對一個運行中的實例進行具代表性的請求測試。重新載入失敗或重新導向迴圈都可能讓公開的公共站台無法使用,問題的代價通常不是測試本身,而是當變更出錯時,線上設定處於未歸檔的狀態。
永久(註:原文為 permanent)重新導向需要特別留意,因為瀏覽器與中介層可能會積極快取 301 回應。盡可能在受控環境中先以暫時的重新導向開始,經過測試後再切換為永久的重新導向,測試內容包含舊路徑、新路徑、查詢字串、替代主機與 HTTPS 行為。請確認回應的 Location 標頭,而不是只依賴瀏覽器網址列——共用網路裝置中快取的重新導向可能會與瀏覽器顯示的不同,唯有原始回應能反映事實。
如何使用 htaccess to nginx 工具轉換一段聚焦的 .htaccess 摘錄
- 將一小段位於 document-root 的 .htaccess 摘錄貼到 htaccess to Nginx Converter,內容不要超過您能一次坐下來檢視的目錄與規則集範圍。解析器一次處理一段有界限的行,會忽略 RewriteEngine On,並在掃描時保留註解。
- 檢視每一行輸出的內容,並依據 Apache 與 Nginx 官方文件讀懂每一行編號的警告。像是 QSA、END、F、G、B 或 NC 等未知旗標、RewriteCond 條件、不進行替代的破折號目標,以及任何超出支援對應範圍的指令,都會以警告的形式呈現,而不會被自動推測為輸出。
- 根據官方 Nginx 指令文件與實際應用程式架構,將產生的片段合併到正確的 Nginx 上下文中——全域重新導向與標頭規則使用 server 區塊,路徑範圍內的 rewrite 樣式則使用 location 區塊。此輸出並非一份完整的 nginx.conf;它並未定義 TLS、root、upstream 或 log。
- 備份目前正在使用的設定檔,執行 nginx -t 來檢查組裝後的檔案是否正確,並在重新載入正式環境前,先對一個預備好的實例測試具代表性的請求。實務上請從暫時性重新導向開始,這樣任何錯誤的行為都還可以回復。
- 如果來源包含驗證、授權、防盜連、代理邏輯、CMS front-controller 規則或複雜條件,請將此次遷移視為一項工程工作,而非單純的批次文字取代——把這個轉換器當作盤點助理,而不是一鍵完成遷移的工具。
若想進一步了解,請參閱使用 HTML 頁面權重分析器時的常見錯誤。