▶
概覽 — 技術架構
整體流程時間估計
約 10 分鐘
建立網站 HTML + 支援檔案
約 5 分鐘
Firebase Hosting 建立 Site + 部署
約 5 分鐘
Cloudflare DNS 設定
10~30 分鐘
Firebase 驗證 + SSL 憑證簽發
約 5 分鐘
Search Console + AdSense + Sitemap
1~3 天
Google AdSense 審核(等待)
固定資源(所有網站共用)
| 項目 | 值 |
|---|---|
| Firebase Project | ouwinner |
| AdSense ID | ca-pub-8677311122302504 |
| 瀏覽計數器 | counter.ouwinner.com/{sitename} |
| Firebase Auth Domain | ouwinner.firebaseapp.com |
| Cloudflare Zone | ouwinner.com |
1
準備網站檔案
指令 建立目錄
mkdir -p /workspace/{sitename}
檔案 firebase.json
{
"hosting": {
"site": "{sitename}-ouwinner",
"public": ".",
"ignore": ["firebase.json", "**/.*"],
"headers": [{
"source": "**",
"headers": [
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" },
{ "key": "X-Content-Type-Options", "value": "nosniff" }
]
}]
}
}
檔案 .firebaserc
{ "projects": { "default": "ouwinner" } }
檔案 ads.txt(固定內容)
google.com, pub-8677311122302504, DIRECT, f08c47fec0942fa0
檔案 index.html 必要 meta 標籤
<meta name="google-site-verification" content="RL8J2GxnNh31EI7Izbpd5Si8VNJ4an_5ARc40VKM5x8"> <meta name="google-adsense-account" content="ca-pub-8677311122302504"> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8677311122302504" crossorigin="anonymous"></script>
檔案 Firebase 留言板設定(每站修改 SITE)
const firebaseConfig = {
apiKey: "AIzaSyDvysuZtZxNyVJ9jLS-Mii6ArzjxCZjWtY",
authDomain: "ouwinner.firebaseapp.com",
projectId: "ouwinner",
storageBucket: "ouwinner.firebasestorage.app",
messagingSenderId: "349909798111",
appId: "1:349909798111:web:91849b1e308c2816276d6a"
};
const SITE = '{sitename}'; // ← 每個網站改這裡
2
Firebase Hosting 部署
指令 Firebase 登入
在本機終端機執行,會開啟瀏覽器 Google 登入
firebase login
⚠️ 非互動環境登入方式(Claude Code / 遠端伺服器)
1. 執行 firebase login 後,瀏覽器開啟 Google 登入
2. 登入後瀏覽器重定向到 http://localhost:9005/?state=...&code=...
3. 若頁面無法載入,複製整個 URL 並執行:
2. 登入後瀏覽器重定向到 http://localhost:9005/?state=...&code=...
3. 若頁面無法載入,複製整個 URL 並執行:
curl "http://localhost:9005/?state=...&code=..."
指令 建立 Firebase Hosting Site
firebase hosting:sites:create {sitename}-ouwinner --project ouwinner
指令 部署
cd /workspace/{sitename}
firebase deploy --only hosting --project ouwinner
✅ 部署後確認:
curl -sI https://{sitename}-ouwinner.web.app 應回傳 HTTP 200
3
Cloudflare DNS 設定
操作 新增 DNS 記錄
前往 Cloudflare Dashboard → ouwinner.com → DNS → Records → Add record
| 類型 | 名稱 | 值 | Proxy |
|---|---|---|---|
| CNAME | {sitename} |
{sitename}-ouwinner.web.app |
灰色(DNS only) |
| TXT | _acme-challenge.{sitename} |
Firebase 提供的 token | 灰色(DNS only) |
⚠️ 重要注意事項
• 必須用 CNAME,不可用 A 記錄(Firebase v1 API 要求)
• Proxy 必須關閉(灰色雲朵),否則 SSL 憑證無法簽發
• 若有舊的 Cloudflare Tunnel CNAME,必須先刪除再加新記錄
• 同名不能同時存在 CNAME 和 A 記錄
• Proxy 必須關閉(灰色雲朵),否則 SSL 憑證無法簽發
• 若有舊的 Cloudflare Tunnel CNAME,必須先刪除再加新記錄
• 同名不能同時存在 CNAME 和 A 記錄
指令 取得 Firebase 需要的 DNS 記錄
TOKEN=$(cat ~/.config/configstore/firebase-tools.json | \
python3 -c "import sys,json; d=json.load(sys.stdin); \
print(d.get('tokens',{}).get('access_token',''))")
curl -s "https://firebasehosting.googleapis.com/v1beta1/projects/ouwinner/sites/{sitename}-ouwinner/customDomains/{sitename}.ouwinner.com" \
-H "Authorization: Bearer $TOKEN" | python3 -m json.tool
指令 監控驗證狀態
等到出現 OWNERSHIP_ACTIVE 即可
TOKEN=$(cat ~/.config/configstore/firebase-tools.json | \
python3 -c "import sys,json; d=json.load(sys.stdin); \
print(d.get('tokens',{}).get('access_token',''))")
until STATUS=$(curl -s \
"https://firebasehosting.googleapis.com/v1beta1/projects/ouwinner/sites/{sitename}-ouwinner/customDomains/{sitename}.ouwinner.com" \
-H "Authorization: Bearer $TOKEN" | python3 -c \
"import sys,json; d=json.load(sys.stdin); \
print(d.get('ownershipState',''), d.get('hostState',''), \
d.get('cert',{}).get('state',''))"); \
echo "$(date +%H:%M:%S) $STATUS"; \
echo "$STATUS" | grep -q "OWNERSHIP_ACTIVE"; do sleep 20; done
| 狀態 | 說明 |
|---|---|
OWNERSHIP_MISSING | 等待 Firebase 驗證 DNS |
OWNERSHIP_ACTIVE | ✅ 驗證完成 |
CERT_PENDING | SSL 申請中 |
CERT_PROPAGATING | SSL 擴散中(即將完成) |
DNS_MATCH | ✅ DNS 正確 |
指令 完成後重新部署
cd /workspace/{sitename} && firebase deploy --only hosting --project ouwinner
✅ 確認上線:
curl -sI https://{sitename}.ouwinner.com 應回傳 HTTP 200
4
更新各站 Sitemap
說明 需要更新的檔案
| 網站 | 路徑 | 更新方式 |
|---|---|---|
| worldcup | /workspace/worldcup/sitemap_index.xml | 直接修改即生效 |
| aibuildwebsite | /workspace/aibuildwebsite/sitemap_index.xml | 直接修改即生效 |
| nasssh | /workspace/nasssh/sitemap_index.xml | 修改後需 firebase deploy |
| aiwebsop | /workspace/aiwebsop/sitemap_index.xml | 修改後需 firebase deploy |
| {新站} | /workspace/{sitename}/sitemap_index.xml | 依部署方式而定 |
✅ worldcup / aibuildwebsite 透過 NAS + Cloudflare Tunnel 服務,直接修改 /workspace 下的檔案即立即生效
範本 sitemap_index.xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://{sitename}.ouwinner.com/sitemap.xml</loc>
<lastmod>YYYY-MM-DD</lastmod>
</sitemap>
<sitemap>
<loc>https://worldcup.ouwinner.com/sitemap.xml</loc>
<lastmod>YYYY-MM-DD</lastmod>
</sitemap>
<sitemap>
<loc>https://nasssh.ouwinner.com/sitemap.xml</loc>
<lastmod>YYYY-MM-DD</lastmod>
</sitemap>
<sitemap>
<loc>https://aibuildwebsite.ouwinner.com/sitemap.xml</loc>
<lastmod>YYYY-MM-DD</lastmod>
</sitemap>
<sitemap>
<loc>https://aiwebsop.ouwinner.com/sitemap.xml</loc>
<lastmod>YYYY-MM-DD</lastmod>
</sitemap>
</sitemapindex>
5
Google Search Console
操作 新增屬性
前往 https://search.google.com/search-console → 左上角新增資源
- 輸入
https://{sitename}.ouwinner.com - 若顯示「你是已驗證擁有者」→ 根網域已驗證,直接跳下一步
- 左側點「Sitemap」→ 提交
sitemap.xml - 再提交一次
sitemap_index.xml - 首頁網址輸入到搜尋列 → 點「要求建立索引」
⚠️ 若 Sitemap 顯示「無法擷取」
刪除該筆記錄後重新提交一次,通常是剛建立時抓取時機問題。
6
Google AdSense
操作 新增網站
- 前往 https://adsense.google.com → 左側「網站」
- 點「新增網站」→ 輸入
{sitename}.ouwinner.com - 若顯示「已加入過」或看到 ouwinner.com 正在審查 → 正常,子網域自動涵蓋
| 狀態 | 說明 |
|---|---|
| 正在接受審查 | Google 人工審核中,1~3 天 |
| 就緒 | ✅ 廣告已啟用 |
| 需要注意 | ⚠️ 點進去查看問題 |
⚠
常見問題與注意事項
坑 Firebase login 在非互動環境失敗
Claude Code / 遠端伺服器無法開啟瀏覽器,需手動完成 OAuth 流程
# 瀏覽器登入後,複製 localhost:9005 的 URL 執行: curl "http://localhost:9005/?state=...&code=..."
坑 Cloudflare Tunnel CNAME 衝突
若之前設過 Cloudflare Tunnel,同名 CNAME 和 A 記錄無法共存,必須先刪舊記錄
刪除指向 cfargotunnel.com 的 CNAME → 再加 Firebase CNAME
坑 Firebase Token 過期
Access token 有效期短,下次部署若出現 401 錯誤需重新 firebase login
坑 A 記錄 vs CNAME
Firebase Hosting 新版(v1)需要 CNAME 指向 {site}.web.app,舊版 API 給的 A 記錄 IP 會造成 OWNERSHIP_MISSING
提醒 每站必須修改的變數
| 位置 | 變數 | 說明 |
|---|---|---|
| firebase.json | site | {sitename}-ouwinner |
| index.html JS | const SITE | 留言板分類用 |
| index.html JS | counter endpoint | counter.ouwinner.com/{sitename} |
| sitemap.xml | <loc> | 網站正確網址 |
📋
現有網站清單
| 網站 | 網址 | 部署方式 | 狀態 |
|---|---|---|---|
| worldcup | worldcup.ouwinner.com | NAS + Cloudflare Tunnel | ✅ 上線 |
| aibuildwebsite | aibuildwebsite.ouwinner.com | NAS + Cloudflare Tunnel | ✅ 上線 |
| nasssh | nasssh.ouwinner.com | Firebase Hosting | ✅ 上線 |
| aiwebsop | aiwebsop.ouwinner.com | Firebase Hosting | ✅ 上線 |
💬 留言板 — 有問題或補充歡迎留言
登入 Google 帳號即可留言