Next.js 應用程式透過Apache 當作反向代理伺服器

好的,這是一個很常見的網站架構。你想用 Apache 當作 反向代理伺服器 (Reverse Proxy),把外面連進來的請求導向你內部跑在 Port 3000 上的 Next.js 應用程式。

我會用繁體中文,用像心情筆記一樣的口語風格來跟你說明詳細步驟,高中生應該也能理解。

設定 Apache 反向代理

這個整合的重點,就是去改 Apache 的設定檔。

步驟一:確認 Apache 模組已經啟用

首先,我們要確定 Apache 已經打開了幾個重要的功能模組。這些模組就像是 Apache 的外掛,反向代理需要它們才能運作。

你需要確認以下三個模組是啟用的:

  • mod_proxy:這是代理功能的基礎。
  • mod_proxy_http:這是處理 HTTP 請求的代理模組。
  • mod_headers:這個會讓我們可以修改傳輸的標頭,確保 Next.js 伺服器能拿到正確的連線資訊。

在大部分 Linux 系統上,你可以用這個指令來啟用它們(如果還沒啟用的話):

sudo a2enmod proxy proxy_http headers

啟用後,要記得重新啟動 Apache 讓設定生效:

sudo systemctl restart apache2

步驟二:編輯 Apache 設定檔

接下來,我們要告訴 Apache 哪個網址要導向 Port 3000。我們通常會在一個特定的設定檔中做這件事,例如在 /etc/apache2/sites-available/ 目錄下的網站設定檔(例如 000-default.conf 或是你專屬的設定檔)。

請你用編輯器打開這個檔案。假設你的網站要使用 80 Port (標準 HTTP) 連線,設定會寫在 <VirtualHost *:80> 裡面。

你需要加入以下這幾行設定:

<VirtualHost *:80>
    ServerName 你的網域名稱 # 例如:www.yourwebsite.com

    # 這一行很重要,它會把所有連到這個網域的請求,
    # 偷偷轉發給內部 Port 3000 的 Next.js 伺服器。
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    # 這些是為了確保 Next.js 拿到的連線資訊是正確的,
    # 例如:用戶真實的 IP 位址。
    RequestHeader set X-Forwarded-Proto "http"
    RequestHeader set Host "你的網域名稱"
</VirtualHost>

如果你也想處理 HTTPS (443 Port) 的連線,那就要在另一個 <VirtualHost *:443> 區塊裡,再寫一次 ProxyPassProxyPassReverse。當然,前提是你已經設定好了 SSL 憑證。

步驟三:測試並重新載入設定

設定檔改好之後,我們需要檢查一下有沒有語法錯誤。

  • 測試指令:
    sudo apachectl configtest
  • 如果它回覆 Syntax OK,表示語法正確,我們就可以重新啟動 Apache 了。
  • 重新啟動指令:
    sudo systemctl restart apache2

步驟四:確認 Next.js 伺服器運作中

在做完上面的 Apache 設定後,你要確保你的 Next.js 應用程式正在 VPS 上用 Node.js 跑起來,而且確實是監聽著 Port 3000

  • 例如,你可能需要執行:node server.js 或是用 PM2 這樣的工具來管理你的 Node.js 應用程式。
  • 重點:請確認你的 Next.js 伺服器不是直接開放給外面連線的,它應該只監聽 localhost:3000 或是 127.0.0.1:3000,這樣才能確保只有 Apache 這個代理可以連到它,更安全一些。

最後的結果

現在,當用戶在瀏覽器輸入你的網域名稱 (例如 http://www.yourwebsite.com),Apache 會接收到這個請求,然後:

  1. Apache (在 80 Port) 接收到請求。
  2. Apache 偷偷把請求轉發給 http://localhost:3000
  3. Next.js 伺服器處理請求,生成 HTML。
  4. Next.js 把結果傳回給 Apache。
  5. Apache 把結果回傳給用戶的瀏覽器。

對用戶來說,他們只會看到你的網站,完全不知道背後是 Apache 在幫 Next.js 擋駕和轉發。


你想知道 Apache 到底有沒有正確讀取和使用你為 nextjs-hello.yourwebsite.com 設定的虛擬主機區塊,這是確認反向代理為什麼沒生效的關鍵一步。

驗證 Apache 虛擬主機載入的步驟

我們主要使用 Apache 內建的工具指令來檢查。

步驟一:檢查哪些設定檔被啟用

首先,要確認你建立的設定檔是否有被 Apache 啟用。在 Debian/Ubuntu 系統上,通常是這樣操作:

  1. 確認你的設定檔已經在 /etc/apache2/sites-available/ 這個目錄下。
  2. 確認你已經執行了啟用指令,它會在 /etc/apache2/sites-enabled/ 建立一個符號連結:
    • 啟用指令:sudo a2ensite 你的設定檔名稱
  3. 檢查符號連結是否存在:
    • 檢查指令:ls -l /etc/apache2/sites-enabled/
    • 你應該會看到一個箭頭指向 /etc/apache2/sites-available/ 的檔案。

步驟二:使用 apache2ctl -S 檢查設定檔解析狀態

這是最直接、最準確的方法,它會告訴你 Apache 實際讀取到的虛擬主機清單。

  • 執行指令sudo apache2ctl -S

執行這個指令後,你會看到類似這樣的輸出:

VirtualHost configuration:
*:80                   is a NameVirtualHost
         default server your-default-domain.com (/etc/apache2/sites-enabled/000-default.conf:1)
         port 80 namevhost your-default-domain.com (/etc/apache2/sites-enabled/000-default.conf:1)
         port 80 namevhost nextjs-hello.dropboxlike.com (/etc/apache2/sites-enabled/nextjs-hello.conf:5)
*:443                  is a NameVirtualHost
         default server ... (略)
         port 443 namevhost nextjs-hello.dropboxlike.com (/etc/apache2/sites-enabled/nextjs-hello-ssl.conf:10)
ServerRoot: "/etc/apache2"
...

如何解讀這個輸出:

  1. *:80 is a NameVirtualHost:這表示 Apache 在 80 Port 上啟用了名稱虛擬主機,它會根據用戶連線的網域名稱來區分不同的網站。
  2. default server ...:這是 Apache 找不到匹配網域名稱時,會使用的預設主機
  3. port 80 namevhost nextjs-hello.yourwebsite.com
    • 如果你看到這行,而且檔案路徑指向你設定 Next.js 反向代理的那個設定檔,那就表示 Apache 已經成功讀取你的設定了

步驟三:確認 NameVirtualHost 指令

在某些舊版的 Apache 或特定組態中,你可能需要手動在主要設定檔中加上 NameVirtualHost *:80。不過,在多數新版的 Ubuntu/Debian 系統上,這個指令已經被預設啟用,不用再手動設定。

只要 apache2ctl -S 的輸出中,nextjs-hello.yourwebsite.com 有出現,就表示設定檔已被載入。如果還連到預設網站,那問題可能就是:

  • 網域名稱解析問題:你的電腦或 DNS 是否正確將 nextjs-hello.yourwebsite.com 指向你的伺服器 IP。
  • 其他 VHost 衝突:是不是有另一個設定檔更早被 Apache 判斷為匹配,搶先處理了這個網域的請求。但這在名稱虛擬主機中比較少見。

你現在試試看執行 sudo apache2ctl -S,然後告訴我關於 nextjs-hello.yourwebsite.com 的輸出結果吧。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *