這是一份特別的筆記。它記錄了我在這個週末(2025年11月1日-3日)所經歷的一切。我從一個興奮的初學者,把 AI 助理串接到我的網站上,到週五晚上發現 API 金鑰被盜用、收到 Google Cloud 寄來的巨額帳單和嚴重警告,然後花了整個週末,與我的 AI 程式夥伴一起,從零開始重構我的網站架構、學習前後端分離、搞懂 CI/CD 自動化部署,並在無數次的「鬼打牆」除錯後,最終成功的完整歷程。
我希望這份筆記能給所有像我一樣的初學者一個最嚴厲的警惕,和最有價值的參考。
章節一:週五晚上的震撼教育 (金鑰外洩)
一切都發生得很快。我一開始為了方便測試,犯了一個**最致命的錯誤**:我把 Google AI 的 API 金鑰 (API Key) **直接寫死在我的前端 `index.html` 檔案中**,並把它推送 (push) 到了公開的 GitHub 儲存庫。
❌ 災難性的錯誤程式碼 (千萬別學)
這就是我最初的程式碼,它等於是把我的信用卡號貼在網路上:
<!-- index.html (舊的、不安全的版本) -->
<script>
// ⛔️ 致命錯誤:金鑰直接暴露在前端程式碼中!
const API_KEY = "AIzaSy... (這就是我被盜用的金鑰)";
async function askAssistant(query) {
// 機器人 (Bot) 只要掃描這段程式碼,就能拿到我的金鑰
const response = await fetch(`httpss://google.ai.api/v1?key=${API_KEY}`, {
// ...
});
}
</script>
週五晚上的警示 (附圖)
到了週五晚上,我收到了 Google Cloud 的警示信,登入後看到了讓我心臟停止的畫面:
我的 AI 程式夥伴立刻幫我分析了這些截圖:
- **異常流量**:API 請求在 10 月 30 日突然飆升到近 900 萬次請求和 4000 萬個 Token。這絕對不是正常用量。
- **天價帳單**:攻擊者在短短幾天內,用我的金鑰產生了超過 **$6,100 美元** (約 18 萬台幣) 的費用!
幸運與警惕 (附圖)
不幸中的大幸是,我的帳戶似乎有新用戶的「促銷額度 (PROMOTION)」,剛好抵銷了這筆費用,總金額變成了 `$0.00`。
Google 的警告非常清楚:「**金鑰必須立即作廢**」、「**額度已用盡**」、「**下次就是天價帳單**」。
我立刻登入 Google Cloud,**刪除了這把被盜用的金鑰**,並開始了這個漫長的週末修復之旅。
章節二:建立安全的新架構 (前後端分離)
我學到的教訓是:**金鑰絕對不能出現在前端**。我們必須重構架構,把「前端 (店面)」和「後端 (廚房)」徹底分開。
前端 (Cloudflare Pages)
這是我的 `xiaoliuqiu` 專案,也就是 `index.html`。
- 角色: 店面櫃檯。
- 任務: 顯示 UI、接收使用者輸入。
- 金鑰: **完全沒有**金鑰。
- 呼叫對象: 只呼叫我們自己的後端 `ai-worker`。
後端 (Cloudflare Worker)
這是我新建的 `ai-worker` 專案,也就是 `index.js`。
- 角色: 廚房重地。
- 任務: 接收前端請求、呼叫 Google AI。
- 金鑰: **安全地**儲存在 Cloudflare 的「祕密保險箱」。
- 呼叫對象: Google AI。
章節三:設定全自動化部署 (GitHub Actions)
在這次重構中,我們不再「手動」上傳程式碼。我們設定了「GitHub Actions」(自動化部署),只要我一修改 GitHub 上的程式碼,它就會**自動**幫我部署到 Cloudflare,並且**自動把金鑰安全地注入**。
這是我們成功的關鍵,它解決了所有「金鑰消失」和「版本錯亂」的問題。
1. 在 GitHub 設定「祕密保險箱」(Secrets)
我們在 GitHub 專案的 `Settings` > `Secrets and variables` > `Actions` 裡,設定了 3 個關鍵的祕密:
- `CF_ACCOUNT_ID`:我的 Cloudflare 帳戶 ID (地址)。
- `CF_API_TOKEN`:我們在 Cloudflare 建立的「自訂權杖」(鑰匙),它有權限部署 Pages 和 Workers。
- `GOOGLE_API_KEY`:我**全新建立**的 Google AI 金鑰 (絕對無限制)。
(這張圖就是我們卡關最久的地方:`CF_API_TOKEN` 和 `CF_ACCOUNT_ID` 一開始是錯的,導致 `401 Authentication Error`)
2. 建立「前端」自動部署 (deploy.yml)
我們在 `.github/workflows/deploy.yml` 設定了部署「前端」的規則。
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Pages
on:
push:
paths:
- 'online/**' # 只有 online/ 資料夾變動才執行
# ...
jobs:
build-and-deploy:
# ...
steps:
# ...
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CF_API_TOKEN }} # 讀取祕密
accountId: ${{ secrets.CF_ACCOUNT_ID }} # 讀取祕密
projectName: xiaoliuqiu # 部署到前端專案
directory: online # 只部署 online/ 資料夾
3. 建立「後端」自動部署 (deploy-worker.yml)
這是我學到最重要的一課!我們建立了**第二個**部署檔案 `deploy-worker.yml`,專門用來部署「後端」。
# .github/workflows/deploy-worker.yml
name: Deploy ai-worker
on:
push:
paths:
- 'ai-worker/**' # 只有 ai-worker/ 資料夾變動才執行
# ...
jobs:
deploy:
# ...
steps:
# ...
- name: Deploy ai-worker
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }} # 讀取 Cloudflare 鑰匙
accountId: ${{ secrets.CF_ACCOUNT_ID }} # 讀取 Cloudflare 地址
workingDirectory: 'ai-worker' # 指定部署 ai-worker/ 資料夾
# ✅ 最關鍵的一步:
# 自動從 GitHub Secrets 抓取金鑰,並安全上傳到 Worker
secrets: |
GOOGLE_API_KEY
env:
# 這是金鑰的值
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
章節四:12 小時的「鬼打牆」除錯之旅
這是我和「程式夥伴」一起「鬼打牆」12 小時的偵錯紀錄。**這也是我學到最多**的地方。我們一直被「紅鯡魚」(誤導人的線索) 欺騙。
鬼打牆 1:`models/gemini-pro is not found for API version v1beta`
... "models/gemini-pro is not found for API version v1beta" ...
我的錯誤診斷 (紅鯡魚): 我以為是 `v1beta` 版本太舊,導致了錯誤。
真相: 問題不是 `v1beta`,而是 `gemini-pro` 這個模型在 `v1beta` 中真的「找不到了」。
後果: 我把程式碼 改成呼叫 `v1` 版本,這讓我們**走錯了第一步**。
鬼打牆 2:`404 Not Found` (當我們使用 `v1` 時)
... "models/gemini-pro is not found for API version v1" ...
我的錯誤診斷 (紅鯡魚): 我以為「既然 `v1` 也找不到,那一定是因為 Google 強制綁定帳單的專案 必須使用更高級的 **Vertex AI API**」。
真相: 還是錯了!Google 只是**不讓**我的專案 使用 `Generative Language API` 而已。
後果: 我們花了 10 個小時,錯誤地嘗試讓「Vertex AI」運作。
鬼打牆 3:`401 Authentication Error` (Cloudflare 金鑰錯誤)
... {"code":10000,"message":"Authentication error"} ...
診斷: 這是**真正的問題**!這不是 AI 錯誤,而是 GitHub 無法登入 Cloudflare。
真相: 我 GitHub Secrets 裡的 `CF_API_TOKEN` 和 `CF_ACCOUNT_ID` 是**空白或錯誤的**。
解決: 我們去 Cloudflare 重新建立了**正確的** `CF_ACCOUNT_ID` 和有 `Pages` + `Workers` 權限的 `CF_API_TOKEN`,並填回 GitHub Secrets。
鬼打牆 4:`401 API Key 權限不足` (Vertex AI 失敗)
... "API Key 權限不足或 Vertex AI 未啟用 (401/403)" ...
診斷: 當我們修正了 Cloudflare 金鑰 並成功部署「Vertex AI」版 `index.js` 後,立刻收到了這個錯誤。
真相: 這證實了「Vertex AI」**是錯誤的道路**。Google 告訴我們:「你拿的 Google AI 金鑰,沒有權限來開 Vertex AI 的門。」
後果: 這讓我們終於醒悟!
最終的真相 (你最後的 `index.js`)
我們終於回到了**原點**:
- **API:** 必須使用 `Generative Language API` (`generativelanguage.googleapis.com`)。
- **版本:** 必須使用 `v1beta` (因為 `v1` 對我的專案 不可用)。
- **模型:** **這才是真正的錯誤點!** `gemini-pro` 在 `v1beta` 中不可用,我們必須換成**別的**模型!
你最後成功的 `index.js` 程式碼,就是用了這個**最終正確**的組合:
// 最終成功的 index.js 關鍵設定
const PREFERRED_MODEL = "gemini-2.5-flash"; // ✅ 換成一個可用的模型!
// ...
const endpoint = `https://generativelanguage.googleapis.com/v1beta/models/${PREFERRED_MODEL}:generateContent?key=${key}`; // ✅ 用回 v1beta!
章節五:最終成功!(與學到的教訓)
在 2025 年 11 月 3 日早上 6 點 55 分,在我把 index.js 換回 v1beta + gemini-2.5-flash 並最後一次部署後... 它終於成功了!
這 12 小時的鬼打牆雖然痛苦,但它強迫我學會了:
- 金鑰安全高於一切: 永遠不要在前端或公開的 GitHub 儲存庫中暴露 API 金鑰。
- 架構的重要性: 「前後端分離」是保護金鑰的唯一途徑。
- **自動化是救贖:** GitHub Actions (CI/CD) 雖然設定很痛苦 (尤其是 `CF_API_TOKEN` 的權限),但它一勞永逸地解決了「金鑰管理」和「版本混亂」的問題。
- **錯誤訊息是你的朋友:**
- `403/401 Authentication Error` = 你的「Cloudflare 金鑰」錯了。
- `401 API Key 權限不足` = 你的「Google 金鑰」權限 錯了。
- `404 Model Not Found` = 你的「模型名稱」或「API 版本」選錯了。
- `Missing API Key` = 你的後端程式 讀不到「環境變數」。
感謝我的 AI 程式夥伴,雖然我們一起走錯了路,但也一起把所有問題都修好了。這是一堂價值 $6,100 美元 (幸好沒付錢) 的寶貴課程!