把 Apache 的 .htaccess 檔案批次轉換成 Nginx 設定,指的是把一段範圍明確的網站根目錄摘錄,轉換成可供審查的 Nginx 設定行,並把每一個條件式規則、不熟悉的旗標,或目標不明確的規則,都標示成帶行號的警告,而不是默默猜一個結果出來。htaccess to Nginx Converter 正是根據這個原則運作:它一次只處理一行、範圍受限的內容,忽略 RewriteEngine On,保留註解,只對映一個範圍很窄的 RewriteRule 旗標集合(L、R、R=301 與 R=302)以及三個簡單的非改寫指令,其餘的一切都會連同它在 Apache 檔案裡的原始行號一起回報出來。這不是一鍵就能從 Apache 搬到 Nginx 的遷移工具,因為這兩種伺服器的請求處理模型,本質上就不一樣。Apache 是透過目錄逐層尋找 .htaccess 檔案,而且可能被 AllowOverride 停用;Nginx 則是讀取集中式設定,在進行改寫處理之前,就先選定要用哪個 server 與 location 區塊。把批次轉換當成一份有文件記錄的第一遍草稿——貼上一段範圍明確的摘錄、審查每一行輸出、對照官方手冊解決每一則警告,再把結果組裝進正確的 Nginx 情境裡——這才是讓遷移保持誠實、且可以回頭的做法。

htaccess to nginx bulk
htaccess to nginx bulk

「htaccess to nginx bulk」實際上代表什麼

搜尋「htaccess to nginx bulk」的人,幾乎都出自三種情況之一:伺服器正要從 Apache 搬到 Nginx;一台既有的 Nginx 伺服器,繼承了別人寫的 .htaccess;或者是一位開發者,想知道一份只有五行規則的檔案,能不能一次就搬過去。在這三種情況下,「批次」這個詞都帶有誤導性。.htaccess 檔案並不是一份可以一對一對映的 Nginx 指令平面清單。它是一種逐目錄疊加的設定,Apache 會針對經過該路徑的每一個請求重新讀取它,而 Nginx 則是在啟動時一次性評估設定,再透過一層層 server 與 location 區塊的階層來路由請求。把這個轉換器當成一個批次文字取代工具來用,正是這個工具明確拒絕的失敗模式。

htaccess to Nginx Converter則反過來,把「批次」理解成有邊界的範圍:貼上一段範圍明確的網站根目錄摘錄,拿回工具有把握轉換的那些行,並閱讀每一則關於條件式、不熟悉或語法含糊內容的警告。處理過程發生在瀏覽器裡,輸入內容不會被送到 Lizely。輸入內容全程留在操作者自己的掌控之下,而工具則會產生一份稽核紀錄,說明它動了什麼、又刻意不去動什麼。這份稽核紀錄才是真正的產出,而不是一堆看起來煞有其事的 Nginx 設定行。

轉換器對映的這一小組指令

在這個有邊界的範圍內,轉換器只認得一組刻意設計得很小的 Apache 指令,並把每一個各自對映成一行 Nginx 設定。它涵蓋三個非改寫指令,而 RewriteRule 則被限制在四種旗標組合內。這套對映關係是有文件記錄、可重現,也經得起審查的,這正是這個工具的重點所在。

下表整理了受支援的指令子集、轉換器輸出的 Nginx 設定行,以及每一列背後有文件記載的範圍假設。

Apache .htaccess 輸入輸出的 Nginx 設定行範圍說明
RewriteRule ^pattern substitution [L]rewrite ^/pattern substitution last;樣式以插入符號開頭、且沒有斜線;轉換器會自動補上開頭的斜線
RewriteRule ^pattern substitution [R=301]rewrite ^/pattern substitution permanent;永久轉址,會被瀏覽器與中介節點快取
RewriteRule ^pattern substitution [R]rewrite ^/pattern substitution redirect;暫時轉址
Options -Indexesautoindex off;停用該目錄的檔案列表
ErrorDocument 404 /local/patherror_page 404 /local/path;僅限本機路徑,不涵蓋外部網址
Header set X-Robots-Tag \"value\"add_header X-Robots-Tag \"value\";限於加引號的固定值,不涵蓋條件式標頭

有兩個細節特別值得注意。第一,一條位於網站根目錄 .htaccess 裡的 Apache RewriteRule 樣式,通常比對的是目錄前綴已經被移除之後的路徑,所以它常常以插入符號開頭、且不帶開頭斜線。而 Nginx 的 rewrite 樣式,看到的則是一個以斜線開頭的 URI。因此轉換器會為受支援的根層級樣式,自動加上這個開頭斜線;這是一項有文件記錄的範圍假設,並不是適用於巢狀 .htaccess 檔案、Alias 對映,或特定 location 區塊的通用轉換方式。第二,自動處理的旗標集合刻意限制在 L、R、R=301 與 R=302。Apache 的永久轉址會變成 Nginx 的 permanent 旗標,暫時轉址會變成 redirect,內部的最終規則則會變成 last。像 QSA、END、F、G、B 或 NC 這類不認識的旗標,會讓那條規則的轉換停下來,因為它們的細節沒辦法被安全地抹去。

批次轉換一段範圍明確的 .htaccess 摘錄

  1. 在瀏覽器分頁裡開啟這個轉換器,並從你的 Apache 設定裡,切出一段範圍明確的網站根目錄摘錄。驗證、代理邏輯、CMS 前端控制器規則,以及複雜的條件鏈,都應該放到另一次獨立的審查裡處理;這個工具不是為它們設計的。
  2. 把摘錄貼進輸入區。工具一次只處理一行、範圍受限的內容,忽略 RewriteEngine On,保留註解,也只針對落在它狹窄轉換契約內的指令輸出設定行。輸入內容全程留在你的瀏覽器裡,不會被送到 Lizely。
  3. 依序閱讀輸出的 Nginx 設定行,並記下每一則帶行號的警告。每一則警告都會回指到 Apache 檔案裡的特定行號,方便你在對伺服器做任何變更之前,先對照Apache mod_rewrite 簡介Nginx 核心 error_page 文件逐一確認。
  4. 手動解決每一則警告。RewriteCond 那些行、帶有未知旗標的 RewriteRule 行,以及目標僅為單一破折號的規則,都是刻意被保留不轉換的;不要自己發明一個替代寫法。把解決之後的設定行,加進你 Nginx 設定裡正確的 server 或 location 區塊。
  5. 把組裝好的片段存進版本控制,然後在重新載入 Nginx 之前,先完成下面的驗證步驟。如果你還在草擬這次批次轉換,就回到轉換器,貼上另一段範圍明確的摘錄,延伸這份稽核紀錄。

為什麼帶行號的警告,比默默猜測更重要

這些警告不是一個需要繞過去的限制。它們正是讓這次遷移安全可靠的稽核紀錄。有三類輸入,永遠只會被回報,而不會被直接輸出成設定。

第一,RewriteCond 那些行絕對不會被自動轉換。Apache 的條件式可以檢查 HTTPS 狀態、主機名稱、檔案、目錄、查詢字串、標頭與擷取到的群組,而且它們的判斷順序很重要。當一條 RewriteRule 緊跟在某個條件式後面時,轉換器同樣會抑制那條規則,而不是輸出一個無條件的轉址,因為那可能會改變流量走向、造成迴圈,或暴露出某條路由。如果讀者想更深入了解這項取捨,可以對照轉換器的行為,和不靠猜測把 Apache .htaccess 轉成 Nginx 規則一文所提出的更廣泛討論。

第二,未知的旗標會讓那條規則的轉換停下來。受支援的 RewriteRule 旗標集合是 L、R、R=301 與 R=302。像 QSA、END、F、G、B 或 NC 這類旗標,會改變一些轉換器無法安全抹除的語意。舉例來說,[F] 會禁止該請求,[G] 會強制回傳「已消失」的回應,[B] 會對替換內容中的反向參照做逸出處理,[NC] 則會讓樣式比對不分大小寫。把這些旗標中的任何一個直接對映成 last、redirect 或 permanent,都會在你不知情的狀況下改變流量走向。警告本身就是處理的結果,而不是缺少的功能。

第三,以單一破折號表示的 Apache「不替換」目標,會被保留不轉換。它常常和一些會改變存取或處理方式、卻不改變 URI 的旗標搭配使用,而一個字面上的破折號,並不是 Nginx 裡安全的替代寫法。一個會默默寫出看似合理、實際上卻不等價設定的轉換器,比一個明確留下待辦事項的轉換器更危險,而這則警告,正是輸出結果的一部分。

組裝這個片段,並在重新載入之前先驗證

轉換器輸出的是一個片段,不是一份完整的 nginx.conf。它不會建立 http、server 或 location 區塊,不會選擇監聽埠、設定 server_name、設定 TLS、找出網站根目錄、保留 PHP 路由、轉發代理,或定義記錄檔。每一行審查過的內容,都必須依照官方的 Nginx 指令文件,以及實際的應用程式架構,放進正確的情境裡。一行設定即使語法正確,放錯情境依然是錯的。

在重新載入之前,請先備份目前生效的設定,並保留一個可用的復原連線。執行 nginx -t 驗證組裝好的設定,接著針對新的 server 或 location 區塊,測試幾個具代表性的請求,確認回應的 Location 標頭、狀態碼與各項標頭都正確。永久轉址需要格外小心,因為瀏覽器與中介節點可能會把它快取下來。比較安全的順序,是先在受控環境裡使用暫時轉址,確認舊路徑、新路徑、查詢字串、替代主機名稱與 HTTPS 行為都沒問題,之後才切換成永久轉址。如何在不中斷服務的情況下換上一份已審查過的設定,這方面的技術細節,說明在如何在不中斷服務的情況下讓 Nginx 重新載入設定裡;重點在於,只有當組裝好的檔案通過 nginx -t、預先測試的結果符合預期,且目前生效的設定已經安全備份好之後,這次批次轉換才算真正完成。

如果來源內容裡包含驗證、授權、防盜連保護、代理邏輯、CMS 前端控制器規則,或複雜的條件式,請把這次遷移當成一項工程工作來對待,而不是單純的批次文字取代。這個轉換器最擅長的角色,是作為一個盤點小幫手:貼上一段範圍明確的摘錄、檢視轉換的行數、解決每一則警告、把結果組裝進一份受版本控制的 Nginx 檔案裡,再到暫存環境上驗證它。