Homepage¶
Overview¶
Homepage 係一套開源、現代化嘅自建服務儀表板,主要用嚟將分散喺唔同主機、容器同 SaaS 嘅服務整合到同一個入口。喺 wiki.benhoweb.com 嘅架構入面,Homepage 部署喺 oracle-cloud 嘅虛擬機,並以 docker 容器方式運行,對外網址係 homepage.benhoweb.com。佢唔單止係一個靜態書籤頁,仲支援即時 widget、服務狀態、系統資源、Docker 容器狀態、書籤分類同自訂主題。管理員可以透過 YAML 設定檔定義服務卡片,例如 litellm、Uptime Kuma、Portainer 等,令日常運維唔需要記住大量 IP 同埠。由於 Homepage 只喺內部 cf_network 同 cloudflare-tunnel 溝通,所以主機唔需要將 3000 埠暴露到公網,安全性同可維護性都較高。
Architecture¶
Homepage 嘅架構可以分為四層:
- 邊緣層:Cloudflare DNS 將
homepage.benhoweb.com指向 Cloudflare Tunnel,唔需要喺 Oracle Cloud 開放入站 80/443 或 3000。 - 隧道層:cloudflare-tunnel 容器同 Homepage 容器一齊接入外部 Docker 網絡
cf_network。Tunnel 將公網請求轉去http://172.21.0.26:3000。 - 應用層:Homepage 容器監聽內部 3000 埠,讀取
/app/config入面嘅 YAML 設定,並產生儀表板。 - 資料層:設定檔持久化喺主機
/home/opc/homepage/config,容器重啟或升級都唔會遺失。
呢種設計嘅關鍵係 cf_network 係 external: true,即係由外部預先建立,通常同其他反向代理或 Tunnel 服務共用。Homepage 獲派固定 IP 172.21.0.26,好處係 Tunnel 設定可以寫死目標,唔怕容器重啟後 IP 改變。由於 ports 已被註解,Host 主機嘅防火牆同 Oracle Cloud Security List 都唔需要開放 3000,減少攻擊面。若果冇 HOMEPAGE_ALLOWED_HOSTS,Homepage 會因為 Host Header 唔匹配而回傳 403,所以呢個環境變數係對外網址能否正常運作嘅核心。
Deployment¶
部署前要準備:Oracle Cloud 實例、已安裝 docker 同 docker-compose、以及一個有 subnet 嘅 cf_network。如果 cf_network 未存在,可以用以下指令建立;若果已經由 Tunnel 建立,就唔好重複建立,並確認 subnet 包含 172.21.0.26。
docker network create --driver bridge --subnet 172.21.0.0/16 cf_network
mkdir -p /home/opc/homepage/config
跟住喺合適目錄建立 docker-compose.yml,內容如下:
version: '3'
networks:
cf_network:
external: true
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
environment:
- TZ=Asia/Hong_Kong
# ⚠️ 終極關鍵:補上呢行,放行你嘅新網址!
- HOMEPAGE_ALLOWED_HOSTS=homepage.benhoweb.com
volumes:
- /usr/share/zoneinfo:/usr/share/zoneinfo:ro
- /home/opc/homepage/config:/app/config # 掛載剛剛建立的資料夾
# ports:
# - "3000:3000" # 走 Tunnel 內部網路,甚至可以不需要把 3000 埠暴露給公網
restart: unless-stopped
networks:
cf_network:
ipv4_address: 172.21.0.26
之後執行 docker compose up -d,再用 docker ps 確認 homepage 狀態。最後喺 Cloudflare Tunnel 嘅 Public Hostname 設定,將 homepage.benhoweb.com 指向 http://172.21.0.26:3000。如果 Tunnel 同 Homepage 唔喺同一個 cf_network,就會連唔到;如果 static IP 同網絡 subnet 唔一致,Compose 亦會報錯。
Configuration¶
Homepage 嘅主要設定檔通常包括 settings.yaml、services.yaml、widgets.yaml、bookmarks.yaml、docker.yaml 等,全部放喺 /home/opc/homepage/config。settings.yaml 控制標題、主題、語言、佈局;services.yaml 定義服務群組同卡片;widgets.yaml 放系統資源、天氣、搜尋等 widget;bookmarks.yaml 管理常用連結。
環境變數方面,TZ=Asia/Hong_Kong 確保日誌同 widget 時間正確;HOMEPAGE_ALLOWED_HOSTS 必須填寫實際對外域名,多個域名用逗號分隔。若果經 proxy 或其他反向代理,亦要將該 Host 加入允許清單。
例如要加入 litellm 服務卡,可以喺 services.yaml 寫:
- LLM:
- LiteLLM:
icon: litellm.png
href: https://litellm.benhoweb.com
description: LLM Gateway
敏感資訊建議用 HOMEPAGE_VAR_ 開頭嘅環境變數或 .env 檔,唔好直接寫入 YAML。/usr/share/zoneinfo 以唯讀方式掛載,係為咗令容器內時區資料同主機一致,避免 Asia/Hong_Kong 解析出錯。改完設定後,重新整理頁面或 docker compose restart homepage 令新設定生效。
Operations¶
日常運維包括更新、備份、監控同故障排查。更新映像檔可用:
docker compose pull
docker compose up -d
因為使用 latest,建議先睇 release note,必要時 pin 版本。備份就係將 /home/opc/homepage/config 同 docker-compose.yml 打包;還原時放返原位再 up -d 即可。排查問題先用 docker logs -f homepage,再檢查 cf_network、Tunnel 狀態同 DNS。健康檢查可以用 docker exec homepage wget -qO- http://localhost:3000。
安全方面,唔好開放 3000 到公網,SSH 只限管理 IP,Cloudflare 可加 Access 政策。若果要加 Watchtower 自動更新,要小心 latest 可能帶嚟兼容問題。資源方面,Homepage 本身佔用唔高,但要留意 widget 查詢頻率同外部 API 限額。
FAQ¶
點解瀏覽器顯示 403 Invalid Host Header?
通常係 HOMEPAGE_ALLOWED_HOSTS 未設定,或者域名串錯。要填 homepage.benhoweb.com,唔要加 https:// 或尾斜線。
點解唔使 ports: 3000:3000?
因為 cloudflare-tunnel 同 Homepage 都喺 cf_network,Tunnel 可以直接用 172.21.0.26:3000 連入,唔需要經主機公網埠。
點解要指定 ipv4_address?
固定 IP 令 Tunnel 設定穩定,唔會因容器重建而改變目標。但前提係 cf_network 有正確 subnet。
可唔可以用 Nginx 代替 Tunnel?
可以,但要自行處理 TLS、反向代理標頭同 HOMEPAGE_ALLOWED_HOSTS,亦可能要開放 443。
設定檔放喺邊?
主機路徑係 /home/opc/homepage/config,容器路徑係 /app/config。
點加新服務?
改 services.yaml,加 href、icon、description,需要 widget 就補 widget 區塊,然後重新載入。
點解要掛載 zoneinfo?
確保容器內時區資料完整,配合 TZ=Asia/Hong_Kong 顯示香港時間。
點備份?
備份 config 資料夾同 compose 檔已經足夠;資料庫類服務要另外備份。
Related Links¶
- docker
- docker-compose
- oracle-cloud
- oracle-linux-9-安裝-codex-cli
- cloudflare-tunnel
- cloudflare
- litellm
- Uptime Kuma
- Portainer
- Watchtower
- proxy
- homepage
- docker
Source¶
Coverage auto (container scan)