初學者指南:設定 Apache 反向代理 Django 服務(含 SSL)
更新日期: 2025 年 3 月 13 日
本文為 HTTPS 連線 基本介紹,第 1 篇:
- 什麼是代管網域(Domain Hosting)?初學者完整指南
- 網站託管(Web Hosting)入門指南:讓你的網站輕鬆上線
- Cloudflare 介紹:讓網站更安全、更快速的關鍵服務
- 反向代理是什麼?初學者必看詳解
- Apache HTTP Server 是什麼:初學者指南
- Django 初學者指南:ALLOWED_HOSTS 設定與安全性考量
- 如何為初學者配置 HTTPS 和 SSL:Cloudflare、Let’s Encrypt 和 Apache 完整指南
- Let’s Encrypt 初學者完全指南
- 虛擬主機(Virtual Host)入門指南:讓你的網站輕鬆上線
- 初學者指南:設定 Apache 反向代理 Django 服務(含 SSL) 👈進度
- Cloudflare 設定指南:如何正確配置 SSL/TLS 加密模式
- Cloudflare Edge Certificates 入門指南
- 解決 Cloudflare 301 重定向循環問題:初學者指南
在使用 Django 開發網站時,通常會需要將其部署到伺服器,並透過 Apache 作為反向代理(Reverse Proxy)來轉發請求。
同時,為了確保網站的安全性,我們也會使用 SSL(HTTPS)。
本指南將詳細說明如何設定 Apache,使其能夠正確轉發 Django 服務的請求,並啟用 SSL 憑證。
本指南適合初學者,將逐步解析 Apache 設定檔案的內容,並教你如何獲取 DocumentRoot
目錄,以確保設定的正確性。
Apache 設定 Django 反向代理與 SSL
在 Apache 伺服器上,我們可以使用 VirtualHost
來設定網站的網域名稱、文件目錄、反向代理等功能。
以下是一個完整的 Apache 設定範例,讓我們逐步解析它的內容。
Apache 設定範例
以下是 VirtualHost
設定的範例檔案:
<VirtualHost *:443>
ServerName musicevent.realnewbie.com
DocumentRoot /path/to/your/django/project
# 啟用 SSL
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/musicevent.realnewbie.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/musicevent.realnewbie.com/privkey.pem
# 反向代理到 Django 服務
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
<Directory /path/to/your/django/project>
Require all granted
AllowOverride All
</Directory>
</VirtualHost>
接下來,我們將依序解釋這些設定的作用。
Apache 設定檔詳細解析
在 Apache 的 VirtualHost
設定檔中,每個指令都有其特定的作用。以下是對每個設定項目的詳細說明,幫助你理解其功能及如何應用。
監聽 HTTPS 連線
<VirtualHost *:443>
VirtualHost
用於定義一個虛擬主機,Apache 會根據這個設定來處理對應的請求。*
代表此設定適用於 伺服器上的所有 IP 地址,不限定特定的 IP。443
是 HTTPS 預設使用的埠號,這表示該VirtualHost
會監聽 HTTPS 連線。
如果你的網站要同時支援 HTTP 和 HTTPS,你還需要一個監聽 80 埠的 VirtualHost
,並將 HTTP 的請求自動轉向 HTTPS:
<VirtualHost *:80>
ServerName musicevent.realnewbie.com
Redirect permanent / https://musicevent.realnewbie.com/
</VirtualHost>
這樣,所有 HTTP 請求都會被轉向 HTTPS,確保網站的安全性。
指定網站的網域名稱
ServerName musicevent.realnewbie.com
ServerName
用來 指定此 VirtualHost 負責的網域名稱。- 當用戶瀏覽
https://musicevent.realnewbie.com
,Apache 會比對ServerName
,並根據這個VirtualHost
的設定來處理請求。
如果想讓 www.musicevent.realnewbie.com
也適用這個設定,你可以加上 ServerAlias
:
ServerAlias www.musicevent.realnewbie.com
這樣 www.musicevent.realnewbie.com
也會使用相同的 VirtualHost
設定。
指定網站的根目錄
DocumentRoot /path/to/your/django/project
DocumentRoot
用來 指定網站的根目錄,Apache 會從這個目錄提供靜態檔案。- 例如,如果
DocumentRoot
設定為:
DocumentRoot /var/www/musicevent
- 那麼當使用者請求
https://musicevent.realnewbie.com/index.html
,Apache 會去/var/www/musicevent/index.html
找該檔案。
Django 注意事項
在 Apache 伺服器中,
DocumentRoot
代表網站的根目錄,通常 Apache 會從這個目錄中讀取並提供靜態檔案(如 HTML、CSS、JavaScript、圖片等)。為什麼 Django 不直接使用
DocumentRoot
來提供靜態檔案?在傳統的 靜態網站 或 PHP 網站 中,Apache 會將
DocumentRoot
設定為網站的根目錄,例如:DocumentRoot /var/www/html
這表示:
- 所有網頁與靜態資源(HTML、CSS、JavaScript、圖片等)都直接存放在
DocumentRoot
目錄內。- 當使用者請求
https://example.com/index.html
,Apache 會從/var/www/html/index.html
提供該檔案。- 當使用者請求
https://example.com/css/style.css
,Apache 會從/var/www/html/css/style.css
提供 CSS 檔案。在這樣的架構下,Apache 會直接從
DocumentRoot
目錄讀取並提供所有靜態資源,而 後端程式(如 PHP)則與靜態檔案混合在同一個目錄內。Django 的靜態檔案管理方式不同
Django 是一個 後端框架,它的主要職責是處理動態請求,例如:
- 資料庫存取
- 使用者驗證
- 伺服器端邏輯處理
Django 不會 將所有靜態檔案直接存放在
DocumentRoot
,而是使用STATIC_URL
來管理靜態資源的路徑。例如,在settings.py
裡的靜態檔案設定:STATIC_URL = '/static/' STATIC_ROOT = '/path/to/your/django/project/staticfiles/'
這代表:
- Django 會將所有靜態檔案(CSS、JS、圖片)統一存放到
STATIC_ROOT
目錄,而不會與後端程式混合在一起。- 在網頁中,Django 會使用
STATIC_URL
來定義靜態檔案的網址前綴,例如/static/
。- 當使用者訪問
https://example.com/static/css/style.css
時,Django 預期伺服器應該將這個請求轉向STATIC_ROOT
內的對應檔案。- Django 本身不會提供
STATIC_ROOT
內的檔案,而是讓 Apache 或 Nginx 負責這個工作。比較 Django 和 Apache 提供靜態檔案的方式
方式 Apache(傳統靜態網站或 PHP) Django 靜態檔案存放目錄 直接存放在 DocumentRoot 內,例如 /var/www/html/css/style.css 存放在 STATIC_ROOT 內,例如 /path/to/your/django/project/staticfiles/css/style.css 伺服器如何提供靜態檔案 Apache 直接從 DocumentRoot 提供 Django 依賴 STATIC_URL 設定,並讓 Apache 使用 Alias 來提供檔案 需要手動收集靜態檔案嗎? 不需要,直接放在 DocumentRoot 即可 需要執行 python manage.py collectstatic,將所有靜態檔案集中到 STATIC_ROOT 如何讓 Apache 提供 Django 的靜態檔案?
因為 Django 不會自動處理靜態檔案的請求,所以我們必須讓 Apache 知道
STATIC_ROOT
目錄的位置,並手動設定 Apache 來提供靜態資源,例如:Alias /static/ /path/to/your/django/project/staticfiles/ <Directory /path/to/your/django/project/staticfiles/> Require all granted </Directory>
這段設定的作用:
- 當 Apache 收到
/static/
開頭的請求時,它會轉向/path/to/your/django/project/staticfiles/
目錄,並提供對應的靜態檔案。Require all granted
允許所有使用者存取這些靜態資源,確保 CSS、JS 和圖片可以正確載入。這樣,Django 只需要管理動態內容,而 Apache 會負責提供靜態檔案,確保網站運行更高效、更穩定。
總結
- 傳統網站(PHP、靜態 HTML)會將靜態檔案存放在
DocumentRoot
,Apache 直接提供它們。- Django 不會透過
DocumentRoot
來提供靜態檔案,而是使用STATIC_URL
來管理它們的路徑。- Django 會將所有靜態檔案存放到
STATIC_ROOT
,並需要手動讓 Apache 或 Nginx 來提供這些靜態檔案。- Apache 需要透過
Alias /static/
來對應 Django 的STATIC_ROOT
,才能正確提供靜態資源。這種架構可以提高效能,減少 Django 本身的負擔,讓靜態檔案的管理更靈活。
啟用 SSL 加密
Apache 預設不會處理 HTTPS 的請求,只有當你 啟用了 SSLEngine on
,並正確設定 SSL 憑證後,Apache 才能處理 HTTPS 連線。
為什麼 Apache 預設不支援 HTTPS?
- HTTP 和 HTTPS 使用不同的協議與埠號
- 預設情況下,Apache 只會監聽 80 埠(HTTP)。
- HTTPS(443 埠)需要 SSL/TLS 加密,但 Apache 不會自動啟用 SSL,因為這需要額外的加密處理與憑證設定。
- SSL 需要 OpenSSL 和
mod_ssl
- HTTPS 需要 SSL/TLS 加密,這是透過 OpenSSL 來處理的。
- Apache 必須載入
mod_ssl
模組,才能處理 HTTPS 連線,否則即使你啟用了SSLEngine on
,Apache 仍然無法正確運行 HTTPS。
- 需要有效的 SSL 憑證
- HTTPS 連線需要 憑證(Certificate) 和 私鑰(Private Key),這些資訊不會預設存在於 Apache,因此需要手動設定。
如何讓 Apache 支援 HTTPS?
如果你希望 Apache 能夠處理 HTTPS,你需要做 三件事:
- 啟用
SSLEngine on
- 安裝並啟用
mod_ssl
模組 - 提供有效的 SSL 憑證
完整的 Apache HTTPS 設定範例如下:
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/example
# 啟用 SSL
SSLEngine on
# 指定 SSL 憑證與私鑰
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>
這樣,Apache 就能夠正確處理 HTTPS 連線,並透過 443 埠 提供加密的網站服務。
如何確認 Apache 是否已啟用 HTTPS?
1. 確認 Apache 是否已啟動 mod_ssl
使用以下指令檢查:
apachectl -M | grep ssl
如果回傳:
ssl_module (shared)
表示 mod_ssl
已啟用,Apache 具備處理 HTTPS 的能力。
如果沒有回傳結果,則需要手動啟用:
Ubuntu / Debian
sudo apt install -y apache2 ssl-cert
sudo a2enmod ssl
sudo systemctl restart apache2
CentOS / RHEL
sudo yum install -y mod_ssl
sudo systemctl restart httpd
確保 Apache 監聽 HTTPS(443 埠)
查看 Apache 目前監聽的埠號:
sudo netstat -tulnp | grep apache
如果你看到 :443
,表示 Apache 正在監聽 HTTPS,輸出示例:
tcp6 0 0 :::443 :::* LISTEN 1234/apache2
如果沒有 :443
,則需要在 Apache 設定中明確指定:
Listen 443
並重新啟動 Apache:
sudo systemctl restart apache2 # Ubuntu / Debian
sudo systemctl restart httpd # CentOS / RHEL
指定 SSL 憑證與私鑰
SSLCertificateFile /etc/letsencrypt/live/musicevent.realnewbie.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/musicevent.realnewbie.com/privkey.pem
SSLCertificateFile
指定 網站的 SSL 憑證(certificate),用來加密與使用者之間的通訊。SSLCertificateKeyFile
指定 私鑰(private key),用來解密 HTTPS 連線。- 憑證通常由 Let’s Encrypt 提供,可透過以下指令申請:
sudo certbot --apache -d musicevent.realnewbie.com
- 成功後,Certbot 會自動產生這些檔案在
/etc/letsencrypt/live/musicevent.realnewbie.com/
。
6. 設定反向代理(Reverse Proxy)
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
ProxyPass
將所有請求轉發 到本機的 Django 服務(localhost:8000
)。ProxyPassReverse
確保 Django 產生的重導向 URL 正確,避免用戶端出現錯誤的網址。
舉例:
sequenceDiagram participant User as 使用者 participant Apache as Apache 伺服器<br>(musicevent.realnewbie.com) participant Django as Django 應用<br>(localhost:8000) %% 正常請求流程 User->>Apache: 請求 https://musicevent.realnewbie.com/dashboard Note over Apache: ProxyPass 設定<br>ProxyPass / http://localhost:8000/ Apache->>Django: 轉發請求到 http://localhost:8000/dashboard Django->>Apache: 回應處理結果 Apache->>User: 傳送回應給使用者 %% 重定向流程 User->>Apache: 請求未授權資源<br>https://musicevent.realnewbie.com/admin Apache->>Django: 轉發請求到 http://localhost:8000/admin Note over Django: 發現未登入,需要重定向 Django->>Apache: 回應 302 重定向到<br>http://localhost:8000/login Note over Apache: ProxyPassReverse 設定<br>ProxyPassReverse / http://localhost:8000/ Apache->>User: 修正重定向 URL 為<br>https://musicevent.realnewbie.com/login %% 使用者跟隨重定向 User->>Apache: 請求 https://musicevent.realnewbie.com/login Apache->>Django: 轉發請求到 http://localhost:8000/login Django->>Apache: 回應登入頁面 Apache->>User: 傳送登入頁面給使用者 %% 說明標籤 Note right of User: 使用者始終只看到<br>musicevent.realnewbie.com Note left of Django: Django 不知道外部網址<br>使用內部網址 localhost:8000 %% 配置說明 rect rgb(240, 240, 240) Note over Apache: Apache 反向代理配置:<br>ProxyPass / http://localhost:8000/<br>ProxyPassReverse / http://localhost:8000/ end
- 基本請求處理流程:
- 使用者訪問
https://musicevent.realnewbie.com/dashboard
- Apache 伺服器透過
ProxyPass
將請求轉發至http://localhost:8000/dashboard
- Django 處理請求後返回結果給 Apache
- Apache 將結果傳回給使用者
- 使用者訪問
- 重定向處理流程:
- 使用者嘗試存取未授權的資源(例如管理頁面)
- Django 發現使用者未登入,產生重定向到
http://localhost:8000/login
- 這時
ProxyPassReverse
的重要性顯現:它將 Django 回傳的 URL 中的localhost:8000
轉換為使用者實際看到的網域musicevent.realnewbie.com
- 使用者看到的重定向網址為
https://musicevent.realnewbie.com/login
,而非 Django 內部使用的地址
Apache 配置關鍵點:
- ProxyPass:
- 將進入 Apache 的請求轉發到內部應用(Django)
ProxyPass / http://localhost:8000/
意味著所有網址路徑都會被轉發
- ProxyPassReverse:
- 處理重定向與引用路徑,確保使用者看到的網址一致
- 修改 HTTP 回應標頭中的 URL(如 Location, Content-Location 等)
- 對使用者隱藏後端架構,提供無縫的使用體驗
這種設置使 Django 應用可以在內部運行,同時讓使用者通過加密的網域名稱進行訪問,實現了安全性與便利性的結合。
確保 Apache 支援反向代理 反向代理功能需要 Apache 啟用 mod_proxy
和 mod_proxy_http
,可以用以下指令啟用:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl restart apache2
設定 Django 專案目錄的存取權限
<Directory /path/to/your/django/project>
Require all granted
AllowOverride All
</Directory>
<Directory>
區塊用來設定 Apache 如何處理特定目錄 的存取權限。Require all granted
允許 所有使用者存取該目錄。AllowOverride All
允許 .htaccess 覆寫 Apache 設定。
.htaccess 的作用
如果 AllowOverride
設定為 All
,則 Django 專案目錄下的 .htaccess
檔案可以自訂 Apache 設定。例如:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
這段 .htaccess
會強制所有 HTTP 請求轉向 HTTPS。
結論
這份 Apache 設定檔的作用是:
- 監聽 HTTPS(443)埠,確保網站使用 SSL 加密連線。
- 設定 ServerName,讓 Apache 知道如何處理特定網域的請求。
- 指定網站根目錄(DocumentRoot),確保靜態資源的正確存取。
- 啟用 SSL 憑證,使用 Let’s Encrypt 簽發的免費憑證來加密 HTTP 通訊。
- 透過 ProxyPass 進行反向代理,將請求轉發至 Django 應用程式。
- 設定 Django 目錄的存取權限,允許 Apache 正確讀取專案內容並執行
.htaccess
。
這些設定確保 Django 服務能夠穩定、安全地運行於 Apache 伺服器上,並透過 HTTPS 提供加密連線。🚀
設定項目 | 說明 |
---|---|
<VirtualHost *:443> | 這表示此設定適用於所有 IP,並監聽 HTTPS(443)埠。 |
ServerName musicevent.realnewbie.com | 指定此網站的網域名稱,所有該網域的請求將由此 VirtualHost 處理。 |
DocumentRoot /path/to/your/django/project | 指定網站的根目錄(實際路徑需替換)。 |
SSLEngine on | 啟用 SSL(HTTPS)。 |
SSLCertificateFile & SSLCertificateKeyFile | 指定 SSL 憑證與私鑰的路徑(通常透過 Let’s Encrypt 簽發)。 |
ProxyPass / http://localhost:8000/ | 設定反向代理,將所有請求轉發至本機的 Django 服務(運行於 localhost:8000)。 |
ProxyPassReverse / http://localhost:8000/ | 讓 Apache 正確回應 Django 服務的重導向請求。 |
<Directory /path/to/your/django/project> | 設定 Django 專案目錄的存取權限,Require all granted 允許所有請求,AllowOverride All 允許 .htaccess 覆寫設定。 |
二、如何獲取 DocumentRoot 目錄
在 VirtualHost
設定檔中,我們需要正確填入 DocumentRoot
,也就是 Django 專案所在的目錄。如果你的 Django 專案是透過 Docker 執行,則可以依照以下方法來獲取正確的目錄路徑。
2.1 在 Docker Compose 中確認 Volume
如果你的 Django 應用程式是透過 Docker 運行,請先檢查 docker-compose.yml
中的 volumes
設定。例如:
volumes:
- ./your-django-app:/app
這表示本機的 your-django-app
目錄對應到容器內的 /app
。
2.2 在本機獲取 Django 專案目錄
若要確認專案的實際路徑,可以在專案目錄下執行以下指令:
pwd
這將回傳當前目錄的完整路徑,例如:
/home/user/projects/your-django-app
這就是你需要填入 DocumentRoot
的值,例如:
DocumentRoot /home/user/projects/your-django-app
<Directory /home/user/projects/your-django-app>
三、總結
在本指南中,我們學到了:
- 如何設定 Apache 來反向代理 Django 服務,並啟用 SSL 憑證。
- 如何解析 Apache 設定檔,了解每個指令的作用。
- 如何獲取 Django 的 DocumentRoot 目錄,確保 Apache 能夠正確讀取專案。
透過這些步驟,你應該能夠成功設定 Apache,讓你的 Django 網站透過 HTTPS 運行,並透過反向代理來處理請求。如果在設定過程中遇到問題,可以檢查 Apache 日誌(通常位於 /var/log/apache2/error.log
)來進一步排除錯誤。
希望這篇指南對你有所幫助,祝你的 Django 部署順利!🚀