摘要:
比照 badminton-scoreboard 的做法,加一個 nginx 容器負責 SSL,
反向代理到原本的 Node 應用;Node 端維持純 HTTP,不碰憑證。
根本原因:
播放器原本只提供 HTTP。專案內原先想直接 symlink www/certificate 進來,
但那份憑證是 2026-04-16 從 DSM 複製出來的靜態副本,已於 2026-07-01 過期,
且 DSM 續期後不會自動更新副本。共用目錄 /volume1/docker/certs 才是
其他專案在用、且持續被續期的來源(目前效期至 2026-09-04)。
影響:
- 外網連線全程明文
- 若沿用 www/certificate,瀏覽器會直接因憑證過期而擋下連線
修法:
- 新增 docker/nginx/(Dockerfile + entrypoint.sh):啟動時把 cert.pem 與
chain.pem 正規化並串成 fullchain,依環境變數產生 nginx 設定,
再用 inotifywait 監看憑證目錄,續期後自動 reload,不需重啟容器
- docker-compose.yml 拆成 360-player(app)與 360-player-web(nginx)兩個服務,
憑證以唯讀掛載 ${SSL_CERT_DIR:-/volume1/docker/certs}
- 保留 app 的 HTTP 埠:憑證綁網域,區網用 IP 連 HTTPS 必定跳警告,
維持 區網走 http / 外網走 https 兩條路
- .env.example 補上 SSL_* 與 HTTPS_PORT 設定項
針對本專案調整(與 badminton-scoreboard 不同之處):
- proxy_buffering off + proxy_max_temp_file_size 0:影片走 HTTP Range 串流,
開著緩衝 nginx 會把整段回應先寫成暫存檔,數 GB 來源會塞爆容器磁碟
- proxy_read_timeout/send_timeout 24h:/api/events 是 SSE,轉檔動輒數小時,
預設 60 秒會被切斷導致進度停止更新
- 移除 websocket 的 Upgrade 標頭:本專案用 SSE,沒有 websocket
驗證:
以 entrypoint 相同的 awk 邏輯在本機組出 fullchain,openssl 解析得到完整三層
憑證鏈(jianmiau.tk → Let's Encrypt YR2 → ISRG Root YR),且 cert 與 privkey
的 modulus 相符。docker compose config 展開後的路徑與埠號皆正確。
註:無 docker daemon 權限,未實際 build 與啟動容器。
順帶修正 README:videoDir 範例改為 NAS 路徑、VAAPI 一節更新為已實機驗證。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
53 lines
1.9 KiB
YAML
53 lines
1.9 KiB
YAML
services:
|
||
360-player:
|
||
container_name: 360-player
|
||
build:
|
||
context: .
|
||
dockerfile: Dockerfile
|
||
image: 360-player:latest
|
||
restart: unless-stopped
|
||
ports:
|
||
# 區網用 IP 直連的 HTTP(憑證是網域名,IP 連一定會跳警告,所以留一條明文)。
|
||
# 想只走 HTTPS 的話把這兩行刪掉,改用下面的 expose 就好。
|
||
- "${PORT:-8360}:8360"
|
||
expose:
|
||
- "8360"
|
||
volumes:
|
||
# 影片資料夾(NAS 上的實際路徑)→ 容器內 /videos,唯讀
|
||
- "${VIDEO_DIR:-/volume1/photo/Badminton}:/videos:ro"
|
||
# 轉檔輸出 + probe 快取 → 容器內 /cache(需要可寫)
|
||
- "${CACHE_DIR:-./cache}:/cache"
|
||
environment:
|
||
TZ: ${TZ:-Asia/Taipei}
|
||
# CPU 轉檔時 libx264 的 preset;NAS CPU 弱可改 superfast / ultrafast(檔案會稍大)
|
||
X264_PRESET: ${X264_PRESET:-veryfast}
|
||
# 本機為 Intel J4025(UHD 600),已啟用 VAAPI 硬體轉檔;
|
||
# 換到沒有 /dev/dri 的機器時要把下面兩行註解掉,否則容器起不來。
|
||
devices:
|
||
- /dev/dri:/dev/dri
|
||
|
||
360-player-web:
|
||
container_name: 360-player-web
|
||
build:
|
||
context: .
|
||
dockerfile: docker/nginx/Dockerfile
|
||
image: 360-player-web:latest
|
||
restart: unless-stopped
|
||
depends_on:
|
||
- 360-player
|
||
ports:
|
||
- "${HTTPS_PORT:-8443}:8443"
|
||
environment:
|
||
TZ: ${TZ:-Asia/Taipei}
|
||
NGINX_PORT: 8443
|
||
NGINX_SERVER_NAME: ${NGINX_SERVER_NAME:-_}
|
||
SSL_CERT_DIR: /etc/nginx/certs
|
||
SSL_CERT_FILE_NAME: ${SSL_CERT_FILE_NAME:-cert.pem}
|
||
SSL_CHAIN_FILE_NAME: ${SSL_CHAIN_FILE_NAME:-chain.pem}
|
||
SSL_KEY_FILE_NAME: ${SSL_KEY_FILE_NAME:-privkey.pem}
|
||
UPSTREAM_HOST: 360-player
|
||
UPSTREAM_PORT: 8360
|
||
volumes:
|
||
# 憑證來源與 badminton-scoreboard 共用;DSM 續期後 entrypoint 會自動 reload
|
||
- "${SSL_CERT_DIR:-/volume1/docker/certs}:/etc/nginx/certs:ro"
|