前言:最後一塊拼圖

你好!終於來到這個長篇系列的最後一篇。在前四篇中,我們從自動部署系統的理論開始,實現了 FastAPI Webhook 伺服器的核心邏輯,並建立了穩定的 Systemd 服務運行環境。

這個系列的前幾篇文章可以通過下面的鏈接查看:

① 為什麼要自己實現?

② 整體架構及流程設計

③ 測試伺服器環境設定及 FastAPI Webhook 伺服器基礎構建

④ 部署處理程序詳細及 Systemd 服務註冊

但還有一個步驟需要完成。目前,我們的 FastAPI Webhook 伺服器僅在 8000 端口上運行,並且沒有使用 HTTPS,這使得系統在安全上有漏洞。此外,GitHub 強烈建議使用公共域名和 HTTPS 連接。

在這一篇中,我們將拼湊最後的拼圖,完成系統。 將 Nginx 設置為反向代理 以安全地將 FastAPI 伺服器暴露給外部,並 通過 Let's Encrypt 應用免費 HTTPS,最後 將 GitHub Webhook 整合以完成自動部署系統

等等,為什麼選擇 Nginx 而不是 Apache2 呢? Apache2 和 Nginx 是網路伺服器市場的兩大佼佼者。 但像 FastAPI 這樣的 非同步網路框架 和 Nginx 相得益彰。 Nginx 設計為非同步事件驅動,可以在高並發環境下充分發揮 FastAPI 的非同步性能。 因此,FastAPI 社區強烈推薦將 Nginx 作為生產環境的網路伺服器,這篇文章也將圍繞 Nginx 進行說明。

Nginx 安裝及反向代理設定

為什麼要使用 Nginx?

  1. 反向代理:像 FastAPI 這樣的應用伺服器並不是用來直接接收外部流量的。Nginx 作為反向代理,接收 webhook 請求並安全地將其傳遞給 FastAPI 伺服器。

  2. 安全性:Nginx 提供各種安全設定和 DDoS 攻擊防禦功能。

  3. 應用 HTTPS:HTTPS 證書的管理和應用由 Nginx 等網路伺服器負責。

Nginx 安裝及設定

透過 SSH 連接到測試伺服器以安裝 Nginx。我假設閱讀這篇文章的讀者已經對 Nginx 有一定的經驗和知識,因此不會詳細解釋 Nginx 的安裝方法、文件結構或工作原理。

sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx # 在重啟時自動啟動
sudo systemctl start nginx # 啟動 nginx
sudo systemctl status nginx # 確認活動狀態

現在我們需要寫 Nginx 設定檔來將請求轉發到我們的 FastAPI Webhook 伺服器。假設我們使用的域名為 deployer.example.com。以下是設定的範例。

#/etc/nginx/sites-available/deployer.example.com

# 將 HTTP 請求重定向到 HTTPS
server {
    listen 80;
    server_name deployer.example.com;
    return 308 https://$host$request_uri;
}

# 處理 HTTPS 請求
server {
    listen 443 ssl;
    server_name deployer.example.com;

    # 設定 SSL 證書路徑
    ssl_certificate /etc/letsencrypt/live/deployer.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/deployer.example.com/privkey.pem;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 5m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
    }
}

  • HTTP 80 端口設定server_namedeployer.example.comlisten 80 區塊會通過命令return 308 https://$host$request_uri; 永久重定向所有進來的 HTTP 請求到 HTTPS。

  • HTTPS 443 端口設定listen 443 ssl; 區塊用於處理 HTTPS 請求。

  • ssl_certificate & ssl_certificate_key:假設已通過 Let's Encrypt 申請過證書。這個區塊指定已發放的 SSL 證書和金鑰檔案的路徑。這些路徑是 certbot 在發放證書時自動生成的。

  • location / 區塊:設置反向代理將經過 HTTPS 轉換的請求轉發到我們的 FastAPI 伺服器(http://127.0.0.1:8000)。

重啟 Nginx 使用這個設定檔後,現在所有的 Webhook 請求將安全地通過 HTTPS 處理。

# 將設定檔符號鏈接到 sites-enabled 目錄
sudo ln -s /etc/nginx/sites-available/deployer.example.com /etc/nginx/sites-enabled/

# 檢查 Nginx 設定檔語法錯誤。
sudo nginx -t

# 重啟 Nginx 以應用變更。
sudo systemctl restart nginx

應用 HTTPS(Let's Encrypt + Certbot)

由於安全原因,GitHub Webhook 強烈建議使用 HTTPS 通信。Let's Encrypt 是一個免費的非營利認證機構,任何人都可以獲得 SSL/TLS 證書,而 Certbot 是一個出色的工具,自動化證書的發放和續期。這裡不會詳細說明安裝方法。

成功完成後,請在瀏覽器中訪問 https://deployer.example.com,查看 FastAPI 的 API 文檔(.../docs)或 / 端點。如果能看到 Webhook server is running! 訊息,則表示 Nginx 和 HTTPS 設定已成功完成。

GitHub Webhook 最終整合與測試

現在一切準備就緒。讓我們把我們構建的自動部署系統連接到 GitHub 存儲庫。

  1. 訪問 GitHub 存儲庫:轉到要應用自動部署的項目的 GitHub 存儲庫。

  2. 設定 Webhooks:在頂部菜單中,點擊Settings -> 在左側菜單中點擊Webhooks

  3. 添加 Webhook:點擊Add webhook 按鈕,並輸入以下信息。

    • Payload URL:輸入應用 Nginx 和 HTTPS 的 Webhook 伺服器地址。(例如:https://deployer.example.com/webhook

    • Content type:選擇 application/json

    • Secret:準確複製並粘貼在第三篇文章中設置的 ~/projects/webhook_server/.env 文件中的 GITHUB_WEBHOOK_SECRET 值。

    • 哪種事件會觸發這個 webhook?:選擇 Just the push event

    • Active:確保勾選框已啟用。

  4. 保存:點擊 Add webhook 按鈕保存 Webhook。

GitHub Webhook 設定截圖

如果 Webhook 正常註冊,則在 Recent Deliveries 部分將出現綠色勾選標記,您可以確認測試請求已成功發送。

現在讓我們進行最終測試。

  1. 在本地更改代碼:稍微修改項目的代碼,進行 Git 提交並推送。

  2. 檢查狀態

    • 在 GitHub Webhook 設定頁的 Recent Deliveries 中確認剛發送的推送的 Webhook 是否成功(綠色勾選)。

    • 通過 SSH 連接到測試伺服器,使用 sudo journalctl -u github-webhook-deployer.service -f 命令實時查看日誌。如果能看見 Git pull successfulDeployment task finished 等訊息,則表示成功。

    • 檢查已部署的 Docker 容器狀態以驗證最新代碼是否已應用。

最後:完成自動部署系統!

恭喜你!成功建立了從本地開發環境到 GitHub,再到自建的測試伺服器的完整 CI/CD 管道。

通過這個系列,我們完成了以下所有事項。

  • 理解了為什麼要自己構建基於 Webhook 的自動部署系統。

  • 設計和實現了使用 FastAPI 的 Webhook 伺服器架構。

  • 學會了如何使用 Systemd 穩定運行服務。

  • 通過 Nginx 和 HTTPS 設定增加了安全性。

  • 最終與 GitHub 整合,自動化了所有流程。

現在每當你推送代碼時,系統將自動將最新代碼應用到伺服器,無需你進行任何操作。基於這個系統,你可以添加更複雜的部署邏輯,或集成通知功能等,按自己的方式進行延伸。

感謝您與我一起走過這段漫長旅程!