一個針對性的 htaccess 對 nginx.conf 轉換工具,只會將一小部分 Apache 指令翻譯成對應的 Nginx 設定行,並對每個條件式或不熟悉的規則附上原始的行號,而不是去猜測其行為。Apache 的每目錄 .htaccess 模式與 Nginx 集中式的 server-and-location 設定模式並不能互換,因此任何誠實的轉換工具都會把輸出的內容視為需要檢視並合併的片段,而不是可以直接套用的 nginx.conf 檔案。htaccess to Nginx Converter 遵循這項契約:它每次只解析一個有界定的行、忽略 RewriteEngine On、保留註解,並且只輸出其支援對應表有涵蓋的指令。任何落在支援子集之外的內容(RewriteCond 區塊、帶有 QSA、END、F、G、B 或 NC 等旗標的規則,或是帶有 Apache 不代入破折號目標的規則)都會被抑制,並列在帶有行號的警告中,讓操作員可以手動對照 Apache 與 Nginx 文件進行處理。本篇文章將說明為何這個保守的範圍才是安全的選擇、轉換工具實際辨識哪些內容、如何貼上片段並讀取產生的行,以及如何將這些行組合成正確的 Nginx 內容,並在重新載入之前驗證組合後的設定。
為何 htaccess 對 nginx.conf 屬於局部對應
Apache 與 Nginx 透過不同的架構來評估請求。Apache 會在每次請求抵達某個路徑時,透過目錄樹來尋找 .htaccess 檔案,並由 AllowOverride 所控管。Nginx 則是讀取像 nginx.conf 這類集中式的設定檔,透過監聽位址選擇 server 區塊,再透過 URI 前綴選擇 location 區塊,整個過程在任何 rewrite 引擎執行之前就已經完成。
即使兩個引擎接受相同的正規表示式,被比對的字串並不相同。在文件根目錄的 .htaccess 中,RewriteRule 樣式通常是比對移除目錄前綴之後的路徑,因此像 RewriteRule ^about$ /about-us [L] 這條規則,一般預期比對的是不帶前置斜線的 about。在 Nginx 內部,rewrite 引擎看到的 URI 開頭會帶有斜線,因此轉換工具在支援的根內容樣式中會自動補上那個前置斜線。這是一項有書面記載的假設,而非通用的轉換:巢狀的 .htaccess 檔、Alias 對應,以及特定 location 的 Nginx 區塊,都可能改變引擎實際看到的內容。
由此衍生出三項實際的後果。
- 一個會悄悄寫出看似合理但實際不等價設定的轉換工具,比留下一份明確待辦工作的轉換工具更危險。
- 條件式、不熟悉的旗標,以及會影響存取的指令,都值得手動處理,而不是交由自動工具做最佳猜測。
- 輸出內容是一段片段,您可以將其合併到正確的 Nginx 內容中,而不是一個可以逕行放入 /etc/nginx/ 的獨立 nginx.conf。
轉換工具辨識的內容
htaccess to Nginx Converter 在一個刻意界定的範圍內運作。它處理四種 Apache 結構,並為每一種輸出一行定義好的 Nginx 設定,其他內容則以警告的形式保留。
| Apache 指令 | 輸出的 Nginx 行 |
|---|---|
| RewriteRule PATTERN SUB [L] | rewrite ^/PATTERN SUB last; |
| RewriteRule PATTERN SUB [R=301] | rewrite ^/PATTERN SUB permanent; |
| RewriteRule PATTERN SUB [R=302] | rewrite ^/PATTERN SUB redirect; |
| RewriteRule PATTERN SUB [R] | rewrite ^/PATTERN SUB redirect; |
| Options -Indexes | autoindex off; |
| ErrorDocument 404 /local.html | error_page 404 /local.html; |
| Header set X-Robots-Tag "value" | add_header X-Robots-Tag "value"; |
受支援的 rewrite 方括號列表中,只包含 L、R、R=301 與 R=302 這幾個旗標。Apache 的永久 redirect 會轉為 Nginx 的 permanent 旗標,臨時 redirect 會轉為 redirect,而內部的 last 規則會轉為 last。RewriteEngine On 會刻意忽略,而輸入中的註解則原樣保留,使轉換稽核保持可讀。
另外也支援三項非 rewrite 的對應:透過 Options -Indexes 停用目錄列表、透過 ErrorDocument 404 指定本地 404 文件,以及透過 Header set 指定加上引號的 X-Robots-Tag 值。除了這些情況之外(其他狀態碼、外部錯誤文件、條件式標頭、環境變數,以及指令容器),轉換工具會回傳警告,而不是進行猜測。
逐步轉換一段 .htaccess 片段
將遷移作業分為三個受控階段執行。
- 將一段聚焦於文件根目錄的 .htaccess 片段貼到 htaccess to Nginx Converter。請保持片段精簡,並只包含轉換工具有書面記載支援的指令。這個工具在瀏覽器中執行,貼上的文字不會被送到 Lizely。
- 逐行檢視每行輸出的 Nginx 設定,並針對每一行帶有行號的警告,對照 Apache mod_rewrite 介紹 以及 Nginx 的 rewrite、error_page 與 add_header 參考頁面手動處理。若警告涉及旗標或條件式,請勿在其上方直接疊上自動產生的內容。
- 將已接受的行合併到正確的 Nginx 內容中,先備份目前使用中的設定,再執行 nginx -t 進行測試,並在預備環境或可還原的維護時段中,針對代表性的請求進行測試,最後再重新載入。
第 2 步是多數讀者最容易低估的工作環節。一行設定在語法上可能正確,但放在錯誤的內容中仍會出問題:rewrite 行必須放在 server 或 location 區塊內,error_page 404 可以放在 http、server 或 location 層級,而 autoindex off 通常是 http 或 location 層級的指令。請將每一行經過檢視的設定,準確地放到 Nginx 指令參考文件所指示的位置。
解讀帶有行號的警告
警告表是轉換工具的核心功能。它會告訴您哪些內容「並未」被翻譯,以及這些行在輸入中的位置。在實務上,幾乎所有警告都落在四個類別中。
| Apache 行的形式 | 被保留的原因 |
|---|---|
| RewriteCond 檢查標頭、主機、檔案、目錄、查詢字串或擷取內容 | 條件式可以讀取伺服器變數與擷取群組,且其評估順序可能讓規則在安全與危險之間翻轉 |
| RewriteRule 緊接在 RewriteCond 之後 | 工具會連同條件式一起抑制該規則,而不是輸出一條可能改變流量、造成迴圈或暴露路徑的無條件 redirect |
| RewriteRule 的方括號旗標列表中含有 QSA、END、F、G、B 或 NC | 未知旗標會產生轉換工具無法保證的效果,因此該規則的轉換會中止,而非錯誤地翻譯它 |
| RewriteRule 使用不代入的破折號目標 (SUBS-) | 該破折號會與存取及處理旗標產生交互作用;直接以字面破折號取代並非安全的 Nginx 對應方式,而會成為虛假的承諾 |
當解析器看到一條緊接在 RewriteCond 之後的 RewriteRule 時,會連同該規則一起抑制,而不僅僅抑制條件式。這樣可以避免產生一條無條件 redirect,卻失去了原本條件式所賦予的語意。警告文字會精確指出對應的行號,讓您能重新開啟來源 .htaccess 並以手動方式處理這些規則。若想更深入了解為何這樣的轉換理念拒絕猜測,請參考 一種會標記風險的 htaccess 對 Nginx 轉換替代方案。
轉換工具測試套件中的負向測試已證實這樣的行為:條件式、不熟悉的旗標,以及不代入的破折號,都會分別產生警告,且不會有猜測出來的輸出。若您貼上一段片段後看到零個警告,請將其視為「該片段確實落在支援子集內」的證據,而非「整份 .htaccess 檔案本身就這麼簡單」的證據。
將輸出合併到正確的 Nginx 內容
輸出是一段片段,而不是一份完整的 nginx.conf。轉換工具並不會建立 http、server 或 location 區塊、不會挑選 listen 連接埠、不會設定 server_name、不會設定 TLS、不會指定文件根目錄、不會保留 PHP 路由、不會設定代理轉發,也不會定義日誌。這些決定取決於您實際的網站架構,且不屬於任何轉換工具應處理的範疇。
這些行在 nginx.conf 中落在哪裡,取決於該指令的作用範圍。
- rewrite:在 server、location 與 if 內容中皆有效。請挑選與該規則要管轄的 URI 前綴最為吻合的 location,否則該規則可能永遠不會執行,或在請求處理順序的錯誤時機執行。
- autoindex off:通常位於 http 或 location。僅將其放在 server 區塊中,會讓子 location 透過繼承或覆寫決定其行為。
- error_page 404 /local.html:可接受 http、server、location 與 if 內容。請挑選應當提供 404 回應的內容,讓巢狀的 location 可透過繼承機制沿用該設定。
- add_header X-Robots-Tag:屬於 headers 模組的指令,在 http、server、location 與 if 內容中皆有效。標頭預設僅套用於成功的回應;若有針對錯誤回應的 Apache 設定意圖,請予以保留。
若您的 .htaccess 包含身分驗證、授權、熱連結保護、代理邏輯、CMS 前控制器規則,或複雜的 RewriteCond 堆疊,請將這次遷移視為工程工作,而非大量文字替換。對簡單的部分而言,範圍較窄的轉換工具是合適的第一關處理,而對其餘部分發出誠實的訊號則代表需要手動處理。
在重新載入之前驗證 nginx.conf
把已接受的行貼入 nginx.conf 只是遷移的起點,而不是終點。一次失敗的重新載入或重新導向迴圈,都可能讓公開的網站無法使用,因此驗證步驟必須刻意規劃。
在編輯之前,請保留一個開啟的復原工作階段,並備份目前使用中的設定。在將各行設定就定位之後,請執行 nginx -t,將組合後的設定檔作為整體進行驗證——這個測試能抓出單行檢視無法發現的語法錯誤與參照錯誤。在重新載入正式伺服器之前,請使用 nginx.conf 的預備複本,並對代表性的請求進行測試。
永久 redirect 值得格外留意。瀏覽器與中介節點都可能快取 301 回應,因此在預備環境重新載入時運作正常的測試,仍可能在下一位訪客身上出問題。在可行情況下,請先在受控環境中使用臨時 redirect,待測試過舊路徑、新路徑、查詢字串、備用主機與 HTTPS 行為後,再切換為永久 redirect。請確認回應中的 Location 標頭,而非僅仰賴瀏覽器網址列。
若您需要一份結構化的清單,盤點 Nginx http 區塊在您已遷移行前後所需的設定(root、index、try_files、PHP 路由、TLS),請將這個轉換工具與一個有書面記載的靜態網站產生器搭配使用,僅用於產生周邊的骨架。這兩種工具刻意保持分離,才能各自維持在範圍狹窄、可驗證的契約之內。
若想進一步了解,請參考 Windows 上的 Htaccess 產生器:桌面工作流程。