新增分拆文件、SOP 與 Caddy SSL 憑證更新紀錄

- 將 hospital_media_antmedia.md 分拆為 docs/ 下五份主題文件
  (host.md, caddy.md, antmedia.md, ssl.md, maintenance.md)
- 新增 README.md / QUICKSTART.md / SUMMARY.md 作為文件入口
- 新增 SOP:Caddy SSL 憑證更新流程 (docs/sop-update-caddy-ssl.md)
  含 2026-04-16 實戰踩坑紀錄(.cer 副檔名、私鑰不匹配、sudo、防火牆 TLS 終端)
- 更新各文件中 tel.tpech.gov.tw 憑證資訊:HiPKI → TWCA,到期 2026-10-30
- 新增 .gitignore 排除 ssl-staging/(含私鑰,不可進 git)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 10:54:47 +08:00
parent 7d6a7ef848
commit 97fd841a0c
10 changed files with 1013 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# SSL 暫存工作區:含私鑰、原始憑證 zip絕對不可進 git
ssl-staging/
# macOS
.DS_Store

118
QUICKSTART.md Normal file
View File

@@ -0,0 +1,118 @@
# Quickstart 常用操作速查
本文件整理日常維護 `106.105.181.40` 最常用的指令。各主題完整說明請見 [docs/](docs/)。
## 登入與巡檢
```bash
# SSH 登入
ssh hospital_media
# 查看所有容器狀態
docker ps
# 查看特定容器日誌
docker logs -f antmedia
docker logs -f caddy
```
## Caddy`/opt/caddy`
```bash
cd /opt/caddy
./run.sh # docker-compose up -d
./stop.sh # docker-compose down
./restart.sh # stop + run
./shell.sh # 進入容器 sh
./list-containers.sh # docker-compose ps
./view-output-from-containers.sh # docker-compose logs -f
```
完整路由與 SSL 配置見 [docs/caddy.md](docs/caddy.md)。
## Ant Media Server`/opt/antmediaserver`
```bash
cd /opt/antmediaserver
./run.sh # 停舊容器 → 啟動新容器(掛載 antmedia_volume
./stop.sh # docker stop antmedia
./shell.sh # 進入容器 bash
./build_antmedia_image.sh # 重新建構 Docker image
./backup_antmedia_data.sh # 備份 antmedia_volume 到當前目錄
./enable_ssl.sh <CERT_DIR> [DOMAIN] # 一鍵更新 SSL 憑證
```
完整部署細節見 [docs/antmedia.md](docs/antmedia.md)。
## SSL 憑證更新
### Caddy`tel.tpech.gov.tw`
```bash
# 1. 從本機把新憑證上傳
scp fullchain.pem privkey.pem hospital_media:/opt/caddy/
# 2. 重啟 Caddyvolume 會自動載入新憑證)
ssh hospital_media "cd /opt/caddy && ./restart.sh"
# 3. 驗證有效期
openssl s_client -connect tel.tpech.gov.tw:443 \
-servername tel.tpech.gov.tw </dev/null 2>/dev/null \
| openssl x509 -noout -dates
```
### Ant Media Server`tel-server.tpech.gov.tw`
把新憑證資料夾(含 `fullchain.pem``*.key`)放到 `/opt/antmediaserver/` 下後:
```bash
cd /opt/antmediaserver
./enable_ssl.sh ssl_tel_server_tpech_gov_tw_2026
# 若需指定網域:
./enable_ssl.sh ssl_tel_server_tpech_gov_tw_2026 tel-server.tpech.gov.tw
# 驗證
openssl s_client -connect tel-server.tpech.gov.tw:5443 \
-servername tel-server.tpech.gov.tw </dev/null 2>/dev/null \
| openssl x509 -noout -dates
```
DCV 驗證檔、手動操作、年度 checklist 詳見 [docs/ssl.md](docs/ssl.md)。
2026-10 這次 TWCA 換發的完整步驟見 [docs/sop-update-caddy-ssl.md](docs/sop-update-caddy-ssl.md)。
## 備份
```bash
# AMS 資料卷備份
cd /opt/antmediaserver && ./backup_antmedia_data.sh
# 產生 antmedia_backup_YYYYMMDD_HHMMSS.tar.gz 於當前目錄
```
更多備份資訊見 [docs/maintenance.md](docs/maintenance.md)。
## 緊急排查
| 現象 | 檢查步驟 |
|------|----------|
| 網站 502 | `docker ps``php` / `php-staging` 是否運行;`docker logs caddy` 看 upstream 錯誤 |
| AMS 無法串流 | `docker logs antmedia`;確認 port `1935/5443/50000-60000` 未被 firewall 擋 |
| HTTPS 憑證錯誤 | `openssl s_client` 檢查到期日;必要時重新 `./restart.sh``./enable_ssl.sh` |
| phpMyAdmin 進不去 | 確認 `10.200.251.40:1888` 可達Caddy 用內網 IP 轉發) |
## 對外 Port 速查
| Port | 服務 |
|------|------|
| 80 / 443 | CaddyHTTP/HTTPS |
| 1443 | Caddy → php-staging |
| 8081 | Caddy 健康檢查 |
| 5080 / 5443 | AMS HTTP / HTTPS |
| 1935 / 8443 | AMS RTMP / RTMPS |
| 3478 | CoturnTURN/STUN |
| 50000-60000 | AMS WebRTC UDP |
| 1888 | phpMyAdmin對外經 Caddy |
| 3306 | MySQL |
完整 Port 與容器對應見 [docs/host.md](docs/host.md)。

73
README.md Normal file
View File

@@ -0,0 +1,73 @@
# 106.105.181.40 伺服器運維文件
此儲存庫為伺服器 `106.105.181.40`SSH 別名 `hospital_media`)的運維筆記,記錄該主機上的 Docker 服務部署、SSL 憑證管理,以及 Ant Media Server 的操作流程。
## 主機概觀
| 項目 | 值 |
|------|-----|
| IP | `106.105.181.40` |
| SSH 別名 | `hospital_media` |
| 對外網域 | `tel.tpech.gov.tw``tel-server.tpech.gov.tw` |
| 運行容器 | Caddy、Ant Media Server、PHP正式/測試、phpMyAdmin、MySQL、Coturn |
## 服務架構
```
┌──────────────────────────────────────────────────────────┐
│ 106.105.181.40 (host) │
│ │
│ ┌─────────┐ ┌──────────┐ ┌─────┐ ┌─────────────┐ │
│ │ Caddy │ │ AntMedia │ │ PHP │ │ phpMyAdmin │ ... │
│ │ :443 │ │ :5443 │ │:8888│ │ :1888 │ │
│ └────┬────┘ └────┬─────┘ └──┬──┘ └──────┬──────┘ │
│ │ │ │ │ │
│ └────────────┴───────────┴────────────┘ │
host network / 各自 port
└──────────────────────────────────────────────────────────┘
```
- Caddy對外 HTTPS 終端與反向代理
- Ant Media Server直播LiveApp與 WebRTC 企業版WebRTCAppEE
- 所有容器皆設 `restart: always`
## 文件導覽
### 總覽層
| 文件 | 說明 |
|------|------|
| [README.md](README.md) | 本文件:專案總覽與文件索引 |
| [QUICKSTART.md](QUICKSTART.md) | 常用操作速查登入、啟停、SSL 更新、備份) |
| [SUMMARY.md](SUMMARY.md) | 伺服器整體架構摘要容器、路由、Port、憑證 |
### 主題層(`docs/`
| 文件 | 說明 |
|------|------|
| [docs/host.md](docs/host.md) | 主機資訊、全部容器一覽、對外 Port 總表 |
| [docs/caddy.md](docs/caddy.md) | Caddy 反向代理操作、路由、SSL、憑證備份 |
| [docs/antmedia.md](docs/antmedia.md) | Ant Media Server部署、腳本、Web 應用、連接埠 |
| [docs/ssl.md](docs/ssl.md) | SSL 憑證管理總覽、AMS 更新方法、年度 checklist |
| [docs/sop-update-caddy-ssl.md](docs/sop-update-caddy-ssl.md) | SOP更新 Caddy `tel.tpech.gov.tw` 憑證TWCA 版) |
| [docs/maintenance.md](docs/maintenance.md) | 系統維護、備份、注意事項 |
### 其他
| 文件 | 說明 |
|------|------|
| [CLAUDE.md](CLAUDE.md) | 給 Claude Code 使用的專案指引 |
## 快速連結
- 登入伺服器:`ssh hospital_media`
- Caddy 部署路徑:`/opt/caddy`
- Ant Media Server 部署路徑:`/opt/antmediaserver`
- SSL 憑證到期日:**2026-04-23**(每年需手動更新)
## 維護重點
1. **SSL 憑證需定期更新**`tel.tpech.gov.tw`Caddy已於 2026-04-16 換成 TWCA到期 **2026-10-30**(僅半年);`tel-server.tpech.gov.tw`AMS仍為中華電信 HiPKI到期 2026-04-23。詳見 [docs/ssl.md](docs/ssl.md)、[docs/sop-update-caddy-ssl.md](docs/sop-update-caddy-ssl.md)。
2. **AMS 資料卷** `antmedia_volume`:刪除 volume 會遺失資料。
3. **TURN/STUN 仍為預設帳密** `testuser` / `testpassword`,建議盡快更換。
4. **LiveApp 的 `remoteAllowedCIDR` 格式錯誤**`106.105.181.40.106.105.181.70` 中間句點應為逗號。

124
SUMMARY.md Normal file
View File

@@ -0,0 +1,124 @@
# 伺服器架構摘要
本文件彙整 `106.105.181.40` 的整體運維圖像。逐項細節請點入對應的主題文件。
## 1. 主機
| 項目 | 值 |
|------|-----|
| IP | `106.105.181.40` |
| SSH 別名 | `hospital_media` |
| 主要使用者 | `tpech_1duan``sftpuser``root` |
→ 詳見 [docs/host.md](docs/host.md)
## 2. 容器總覽
| 容器 | Image | 網路 | 用途 |
|------|-------|------|------|
| `caddy` | `caddy` | host | 反向代理、SSL 終端、靜態檔 |
| `antmedia` | `antmediaserver:2.13.2` | host、privileged | 直播串流 |
| `php` | `timmy/php_base:v1.0` | `8888→80` | 正式 PHP |
| `php-staging` | `timmy/php_base:v1.0` | `6666→80` | 測試 PHP |
| `coturn` | `coturn` | `3478` | TURN/STUN |
| `phpmyadmin` | `phpmyadmin` | `1888→80` | DB 管理介面 |
| `mysql-container` | `mysql:latest` | `3306` | MySQL |
> 全部容器 `restart: always`。
## 3. Caddy 路由
| 入口 | 後端 | 說明 |
|------|------|------|
| `tel.tpech.gov.tw:443` | `127.0.0.1:8888`php | 正式HTTPS |
| `tel.tpech.gov.tw:443/phpmyadmin/*` | `10.200.251.40:1888` | phpMyAdmin |
| `tel.tpech.gov.tw:80` | `127.0.0.1:8888` | 正式HTTP |
| `:1443` | `127.0.0.1:6666`php-staging | 測試 |
| `tel-server.tpech.gov.tw:80/443` | `/srv/tel-server` | PKI `.well-known` 靜態檔 |
| `:443` / `:80` | `127.0.0.1:8888` | 其他網域 fallback |
| `:8081` | — | 健康檢查 |
- `auto_https off`:手動管理憑證
- 部署於 `/opt/caddy`,以 `docker-compose.yaml` 管理
→ 詳見 [docs/caddy.md](docs/caddy.md)
## 4. Ant Media Server
| 項目 | 值 |
|------|-----|
| 部署路徑 | `/opt/antmediaserver` |
| Image | `antmediaserver:2.13.2`(基底 `ubuntu:22.04` |
| 網路 | `--network host` + `--privileged` |
| 時區 | `Asia/Taipei` |
| 資料 Volume | `antmedia_volume``/usr/local/antmedia/` |
### Web 應用
| 路徑 | 說明 |
|------|------|
| `/LiveApp` | 主要使用WebRTC 20fps、HLS 啟用 |
| `/WebRTCAppEE` | WebRTC 企業版30fps目前無串流 |
| `/` | AMS Angular 管理後台 |
- 轉碼720p (1.5 Mbps) + 480p (1 Mbps)
- TURN/STUN 指向 `106.105.181.40:3478`
→ 詳見 [docs/antmedia.md](docs/antmedia.md)
## 5. 對外 Port 總表
| 協定 | Port |
|------|------|
| HTTP | 80、5080 |
| HTTPS | 443、1443、5443、8443RTMPS |
| RTMP | 1935 |
| TURN/STUN | 3478 |
| WebRTC UDP | 50000-60000 |
| 健康檢查 | 8081 |
## 6. SSL 憑證
兩張憑證分屬不同 CA需各自手動更新。
| 網域 | CA | 到期日 | 使用於 | 憑證位置 |
|------|----|--------|--------|----------|
| `tel.tpech.gov.tw` | **TWCA** | **2026-10-30** | Caddy | 主機 `/opt/caddy/fullchain.pem``privkey.pem` |
| `tel-server.tpech.gov.tw` | 中華電信 HiPKI | 2026-04-23 | AMS | 容器內 `/usr/local/antmedia/conf/` |
> `tel.tpech.gov.tw` 2026-04-16 從 HiPKI 換成 TWCA且只有半年效期→ 10/30
- AMS Keystore 密碼 = 網域名稱 `tel-server.tpech.gov.tw`
- 歷年憑證備份:`/opt/caddy/hospital/``/opt/antmediaserver/ssl_*/`
- **注意**:醫院前端有防火牆/WAF 做 TLS 終端,更新 Caddy 後需另外通知網管同步更新
→ 詳見 [docs/ssl.md](docs/ssl.md)
## 7. 備份
| 項目 | 方式 |
|------|------|
| AMS 資料卷 | `/opt/antmediaserver/backup_antmedia_data.sh` 產生 tar.gz |
| AMS 歷史完整備份 | `/opt/antmedia_*.tar.gz`(最新 2025-05-123.4GB |
| 憑證備份 | `/opt/caddy/hospital/``/opt/antmediaserver/ssl_*/` |
→ 詳見 [docs/maintenance.md](docs/maintenance.md)
## 8. 已知問題 / 待辦
- **TURN/STUN** 仍為預設帳密 `testuser` / `testpassword`,建議更換。
- **LiveApp `remoteAllowedCIDR`** 格式錯誤:`106.105.181.40.106.105.181.70`,中間句點應為逗號。
- **AMS 以 `--privileged` 運行**,安全上需留意。
- **host 網路模式**`caddy``antmedia` 皆共用主機所有 port變更前需檢查衝突。
## 9. 年度 SSL 更新流程(總覽)
1. 向中華電信提交 CSR。
2. 拿到 DCV 驗證檔 → 放入 `/opt/caddy/tel-server/.well-known/pki-validation/`
3. CA 驗證通過 → 取得新憑證。
4. 更新 Caddy覆蓋 `/opt/caddy/fullchain.pem``privkey.pem``./restart.sh`
5. 更新 AMS`cd /opt/antmediaserver && ./enable_ssl.sh ssl_tel_server_tpech_gov_tw_<年份>`
6. 備份新憑證 → `hospital/``ssl_*/` 目錄。
7. 備份 AMS 資料 → `./backup_antmedia_data.sh`
→ 詳細步驟見 [docs/ssl.md](docs/ssl.md),常用指令見 [QUICKSTART.md](QUICKSTART.md#ssl-憑證更新)。

90
docs/antmedia.md Normal file
View File

@@ -0,0 +1,90 @@
# Ant Media Server
- 部署路徑:`/opt/antmediaserver`
## 服務狀態
| 項目 | 值 |
|------|-----|
| 容器名稱 | `antmedia` |
| Docker Image | `antmediaserver:2.13.2` |
| 安裝包 | `ant-media-server-enterprise-2.13.2-20250207_1708.zip` |
| 基礎映像 | `ubuntu:22.04` |
| 網路模式 | `--network host` |
| 時區 | `Asia/Taipei` |
| 重啟策略 | `--restart=always` |
| 資料 Volume | `antmedia_volume``/usr/local/antmedia/` |
## 操作腳本(`/opt/antmediaserver`
```bash
./build_antmedia_image.sh # 建構 Docker image
./run.sh # 停舊容器 → 啟動新容器(掛載 antmedia_volume
./stop.sh # docker stop antmedia
./shell.sh # docker exec -it antmedia bash
./enable_ssl.sh <CERT_DIR> [DOMAIN] # 一鍵更新 SSL 憑證
./backup_antmedia_data.sh # 備份 antmedia_volume 到當前目錄
```
### build_antmedia_image.sh
```bash
docker build --network=host -t antmediaserver \
--build-arg AntMediaServer=ant-media-server-enterprise-2.13.2-20250207_1708.zip .
```
### run.sh
```bash
docker stop antmedia && docker rm antmedia
docker run -d --network host --privileged \
--restart=always \
-e TZ=Asia/Taipei \
-v /etc/localtime:/etc/localtime:ro \
--mount source=antmedia_volume,target=/usr/local/antmedia/ \
--name antmedia antmediaserver:2.13.2
```
### backup_antmedia_data.sh
```bash
docker run --rm \
-v antmedia_volume:/data \
-v "$(pwd)":/backup \
busybox \
sh -c "cd /data && tar czf /backup/antmedia_backup_$(date +%Y%m%d_%H%M%S).tar.gz ."
```
## Web 應用
| 應用 | 路徑 | 說明 |
|------|------|------|
| LiveApp | `/LiveApp` | 直播應用主要使用WebRTC 20fpsHLS 啟用 |
| WebRTCAppEE | `/WebRTCAppEE` | WebRTC 企業版30fps目前無串流 |
| root | `/` | AMS 管理後台Angular SPA |
- 轉碼設定720p (1.5Mbps) + 480p (1Mbps)
- TURN/STUN 指向 `106.105.181.40:3478`(帳密為預設 `testuser`/`testpassword`,建議更換)
- LiveApp 的 `remoteAllowedCIDR` 有格式錯誤:`106.105.181.40.106.105.181.70`,中間句點應為逗號
## 連接埠
| 協定 | Port |
|------|------|
| HTTP | 5080 |
| HTTPS | 5443 |
| RTMP | 1935 |
| RTMPS | 8443 |
| TURN/STUN | 3478 |
| WebRTC UDP | 50000-60000 |
## 注意事項
- **AMS 使用 Docker volume**`antmedia_volume`):容器刪除後資料仍保留,但刪除 volume 則遺失。
- **AMS 特權模式**:容器以 `--privileged` 運行。
## 相關文件
- [SSL 憑證管理](ssl.md)(含 AMS 憑證更新方法一 / 方法二)
- [主機與容器總覽](host.md)
- [系統維護與備份](maintenance.md)

79
docs/caddy.md Normal file
View File

@@ -0,0 +1,79 @@
# Caddy 反向代理
- 部署路徑:`/opt/caddy`
- 使用 `docker-compose.yaml` 管理,`--network host` 模式
- Volume 掛載:`Caddyfile``caddy_data`、SSL 憑證、`tel-server` 靜態檔案
## 操作腳本
```bash
./run.sh # docker-compose up -d
./stop.sh # docker-compose down
./restart.sh # stop + run
./shell.sh # docker exec -it caddy sh
./list-containers.sh # docker-compose ps
./view-output-from-containers.sh # docker-compose logs -f
```
## 路由規則Caddyfile
| 入口 | 後端 | 說明 |
|------|------|------|
| `tel.tpech.gov.tw:443` | `127.0.0.1:8888`php 容器) | 正式環境HTTPS |
| `tel.tpech.gov.tw:443/phpmyadmin/*` | `10.200.251.40:1888` | phpMyAdminstrip prefix 後轉發) |
| `tel.tpech.gov.tw:80` | `127.0.0.1:8888` | 正式環境HTTP |
| `:1443` | `127.0.0.1:6666`php-staging 容器) | 測試環境ISO27001 |
| `tel-server.tpech.gov.tw:80/443` | `/srv/tel-server` | 靜態檔案服務(用於 PKI 驗證 `.well-known` |
| `:443` / `:80` | `127.0.0.1:8888` | 其他網域的 fallback |
| `:8081` | — | 健康檢查(回傳 "I am 8081" |
- `auto_https off`:不使用 Caddy 自動 HTTPS手動管理憑證
## Caddy SSL 憑證
| 項目 | 值 |
|------|-----|
| 網域 | `tel.tpech.gov.tw` |
| 簽發者 | TWCA Secure SSL Certification Authority2026-04-16 起) |
| 有效期 | 2026-04-15 ~ **2026-10-30**(僅半年) |
| 憑證路徑(主機) | `/opt/caddy/fullchain.pem``/opt/caddy/privkey.pem` |
| 憑證路徑(容器內) | `/etc/caddy/ssl/fullchain.pem``/etc/caddy/ssl/privkey.pem` |
> 前一張為中華電信 HiPKI2025-04-23 ~ 2026-04-23已備份至 `/opt/caddy/hospital/ssl_tel_tpech_gov_tw_pre_2026_10_backup/`。
## 更新 Caddy 憑證
完整 SOP 見 [sop-update-caddy-ssl.md](sop-update-caddy-ssl.md)。快速摘要:
```bash
# 1. 上傳新憑證到主機(經 /tmp 中轉避免權限問題)
scp fullchain.pem privkey.pem hospital_media:/tmp/
ssh hospital_media "sudo mv /tmp/fullchain.pem /tmp/privkey.pem /opt/caddy/ && \
sudo chmod 644 /opt/caddy/fullchain.pem && \
sudo chmod 600 /opt/caddy/privkey.pem"
# 2. 重啟 Caddy需要 sudo
ssh hospital_media "cd /opt/caddy && sudo ./restart.sh"
# 3. 驗證(本地連線最可靠,外部可能被防火牆/WAF 攔截)
ssh hospital_media "openssl s_client -connect 127.0.0.1:443 \
-servername tel.tpech.gov.tw </dev/null 2>/dev/null \
| openssl x509 -noout -issuer -dates"
```
> **注意**:醫院前端有防火牆做 TLS 終端,外部 `openssl s_client` 可能看到舊憑證。須另外通知網管更新。
## 憑證備份(`/opt/caddy/hospital/`
| 目錄 | 內容 |
|------|------|
| `hospital/ssl_tel_tpech_gov_tw_2026_10/` | `tel.tpech.gov.tw` 2026 TWCA 憑證cert.zip + fullchain + key |
| `hospital/ssl_tel_tpech_gov_tw_pre_2026_10_backup/` | 更新前的舊 HiPKI 憑證備份 |
| `hospital/ssl_tel_tpech_gov_tw_2025/` | `tel.tpech.gov.tw` 2025 年 HiPKI 憑證key + csr + fullchain |
| `hospital/ssl_tel_server_tpech_gov_tw_2025/` | `tel-server.tpech.gov.tw` 2025 年憑證key + csr + fullchain |
## 相關文件
- [SOP更新 Caddy SSL 憑證](sop-update-caddy-ssl.md)
- [SSL 憑證管理](ssl.md)
- [主機與容器總覽](host.md)

44
docs/host.md Normal file
View File

@@ -0,0 +1,44 @@
# 主機與容器總覽
## 主機資訊
| 項目 | 值 |
|------|-----|
| IP | `106.105.181.40` |
| SSH 別名 | `hospital_media` |
| 檔案擁有者 | `tpech_1duan` / `sftpuser` / `root` |
## 全部容器一覽
| 容器名稱 | Image | 網路 | 用途 |
|----------|-------|------|------|
| `caddy` | `caddy` | host | 反向代理、SSL 終端、靜態檔案 |
| `antmedia` | `antmediaserver:2.13.2` | host | Ant Media Server串流 |
| `php` | `timmy/php_base:v1.0` | port 8888→80 | 正式環境 PHP 應用 |
| `php-staging` | `timmy/php_base:v1.0` | port 6666→80 | 測試環境 PHP 應用ISO27001 驗證用) |
| `coturn` | `coturn` | port 3478 | TURN/STUN 伺服器 |
| `phpmyadmin` | `phpmyadmin` | port 1888→80 | 資料庫管理介面 |
| `mysql-container` | `mysql:latest` | port 3306 | MySQL 資料庫 |
所有容器皆設為 `restart: always`
## 對外 Port 總表
| Port | 協定 / 服務 |
|------|-------------|
| 80 / 443 | CaddyHTTP / HTTPS |
| 1443 | Caddy → `php-staging` |
| 8081 | Caddy 健康檢查 |
| 5080 / 5443 | Ant Media Server HTTP / HTTPS |
| 1935 / 8443 | Ant Media Server RTMP / RTMPS |
| 3478 | CoturnTURN/STUN |
| 50000-60000 | Ant Media Server WebRTC UDP |
| 1888 | phpMyAdmin對外經 Caddy |
| 3306 | MySQL |
## 相關文件
- [Caddy 反向代理](caddy.md)
- [Ant Media Server](antmedia.md)
- [SSL 憑證管理](ssl.md)
- [系統維護與備份](maintenance.md)

38
docs/maintenance.md Normal file
View File

@@ -0,0 +1,38 @@
# 系統維護與備份
## 備份
| 項目 | 方式 | 說明 |
|------|------|------|
| AMS 資料卷備份 | `/opt/antmediaserver/backup_antmedia_data.sh` | 從 `antmedia_volume` 備份到當前目錄 |
| AMS 歷史完整備份 | `/opt/antmedia_*.tar.gz` | 手動 tar 備份最新2025-05-123.4GB |
| 憑證備份 | `/opt/caddy/hospital/``/opt/antmediaserver/ssl_*/` | 各時期憑證 |
## 注意事項
- **AMS 使用 Docker volume**`antmedia_volume`):容器刪除後資料仍保留,但刪除 volume 則遺失。
- **AMS 特權模式**:容器以 `--privileged` 運行。
- **Caddy 使用 bind mount**Caddyfile 和憑證直接掛載主機檔案。
- **host 網路**`caddy``antmedia` 皆使用 host 網路模式,直接共用主機所有 port。
- **TURN/STUN 帳密為預設值** `testuser` / `testpassword`,建議更換。
- **LiveApp 的 `remoteAllowedCIDR` 有格式錯誤**`106.105.181.40.106.105.181.70`,中間句點應為逗號。
## SSL 憑證到期時間
兩張憑證分屬不同 CA需各自手動更新
| 網域 | CA | 到期日 | 使用於 |
|------|----|--------|--------|
| `tel.tpech.gov.tw` | **TWCA** | **2026-10-30** | Caddy 反向代理 |
| `tel-server.tpech.gov.tw` | 中華電信 HiPKI | 2026-04-23 | Ant Media Server |
> `tel.tpech.gov.tw` 只有半年效期2026-10 前需再次更新。
完整更新 SOP 請見 [sop-update-caddy-ssl.md](sop-update-caddy-ssl.md),年度 checklist 見 [ssl.md](ssl.md#年度-ssl-更新-checklist)。
## 相關文件
- [SSL 憑證管理](ssl.md)
- [Caddy 反向代理](caddy.md)
- [Ant Media Server](antmedia.md)
- [主機與容器總覽](host.md)

View File

@@ -0,0 +1,330 @@
# SOP更新 Caddy SSL 憑證(`tel.tpech.gov.tw`
本 SOP 用於把新申請到的 SSL 憑證部署到 `/opt/caddy/`,讓 `tel.tpech.gov.tw` 使用新憑證。
> 本 SOP 只處理 **Caddy** 的憑證(`tel.tpech.gov.tw`)。
> Ant Media Server 的 `tel-server.tpech.gov.tw` 是**另一張獨立憑證**,更新方式見 [ssl.md](ssl.md)。
---
## 實戰紀錄2026-04-16 首次執行)
以下是本 SOP 首次實際執行時踩到的坑,記錄下來避免日後重蹈覆轍。
### 坑 1TWCA cert.zip 裡的副檔名是 `.cer`,不是 `.crt`
TWCA 核發的壓縮檔解開是 `root.cer``uca.cer``server.cer`,都是 PEM 格式但副檔名為 `.cer`。指令中的 `*.crt` 要改成 `*.cer`,否則找不到檔案。
### 坑 2Private Key 不在主機上
主機 `/opt/caddy/privkey.pem` 裡面是舊的 HiPKI 那把 key。這次向 TWCA 申請時用的是**新產生的 CSR / key pair**,所以舊 key 和新憑證的 modulus 不匹配。
最後在本機 `~/Downloads/ssl/tel/tel.key`2026-03-26 產生)找到正確的 key。
**教訓**申請憑證時key 和 CSR 一定要放到固定位置並標註日期與用途。建議統一放到 `ssl-staging/<網域>-<年月>/` 並保留 `.key` + `.csr` 原始檔。
### 坑 3Docker 指令需要 sudo
`tpech_1duan` 使用者不在 docker group 裡,`./restart.sh` 必須加 `sudo`
### 坑 4醫院前端有防火牆 / WAF 做 TLS 終端
Caddy 重啟後,**主機本地** `127.0.0.1:443` 驗證是新的 TWCA 憑證,但**從外部**連 `106.105.181.40:443` 看到的還是舊的 HiPKI 憑證。
原因:醫院網路在伺服器前面有一層設備(防火牆 / WAF / load balancer在做 SSL 終端或 SSL inspection。外部 TLS 連線是跟那台設備交握,不是直接跟 Caddy 交握。
**需要額外通知網管單位**:把新憑證也更新到前端防火牆/WAF 上。憑證檔案可以從主機 `/opt/caddy/hospital/ssl_tel_tpech_gov_tw_2026_10/` 取得。
### 坑 5OCSP Stapling timeout
Caddy log 中出現 TWCA 的 OCSP 伺服器 `twcasslocsp.twca.com.tw` 連線 timeout。原因可能是主機對外存取被限制。這只是 warning不影響 TLS 正常運作,但客戶端可能需要自行查 OCSP。
---
## 憑證資訊
### 目前生效的憑證2026-04-16 部署)
| 項目 | 值 |
|------|-----|
| 網域 | `tel.tpech.gov.tw` |
| 簽發者 | TWCA Secure SSL Certification Authority |
| 憑證序號 | `95590185165637134231279949412783532535` |
| 生效日 | 2026-04-15 |
| 到期日 | **2026-10-30**(僅半年) |
| 憑證檔 | `cert.zip`(內含 `root.cer``uca.cer``server.cer` |
| 私鑰來源 | 本機 `~/Downloads/ssl/tel/tel.key`2026-03-26 產生) |
| 主機備份 | `/opt/caddy/hospital/ssl_tel_tpech_gov_tw_2026_10/` |
### 被替換的舊憑證
| 項目 | 值 |
|------|-----|
| 簽發者 | 中華電信 HiPKI OV TLS CA - G1 |
| 有效期 | 2025-04-23 ~ 2026-04-23 |
| 主機備份 | `/opt/caddy/hospital/ssl_tel_tpech_gov_tw_pre_2026_10_backup/` |
> **注意**:這張憑證只有半年效期,**2026-10 月前**必須再次更新。
---
## 0. 前置檢查(動手前必確認)
| # | 檢查項 | 指令 / 說明 |
|---|--------|------------|
| A | **cert.zip** | TWCA 寄來的附件。解壓後應有 3 個 `.cer` 檔 |
| B | **Private Key** | 當初產生 CSR 時留下的私鑰。**TWCA 不會寄這個**,必須自己保留 |
| C | **SSH 可連** | `ssh hospital_media "echo ok"` |
| D | **Caddy 活著** | `ssh hospital_media "sudo docker ps \| grep caddy"` |
> **找不到私鑰怎麼辦?**
>
> 1. 先搜本機:`find ~/Downloads ~/Desktop ~/Documents -name '*.key' -newer <cert.zip 的日期>`
> 2. 再搜主機:`ssh hospital_media "find /opt /root /home -maxdepth 4 -name '*.key' 2>/dev/null"`
> 3. 都找不到 → 重新產生 CSR/key向 TWCA 申請 rekey重核發
---
## 1. 本機準備工作目錄
工作區放在 repo 下的 `ssl-staging/`(已加入 `.gitignore`,不會 commit
```bash
cd /Users/timmy/Projects/Freelance/106_105_181_40
mkdir -p ssl-staging/tel-tpech-<年月> # 例tel-tpech-2026-10
cd ssl-staging/tel-tpech-<年月>
```
`cert.zip``privkey.pem`(或 `*.key`)都放進來。
---
## 2. 解壓
```bash
unzip cert.zip
ls
# TWCA 格式root.cer uca.cer server.cer
# (注意副檔名是 .cer不是 .crt
```
---
## 3. 檢查憑證格式與內容
```bash
# 確認是 PEM 文字格式
file *.cer
# 應為 "PEM certificate" 或 "ASCII text"
# 確認網域、簽發者、效期
openssl x509 -in server.cer -noout -subject -issuer -dates
```
### 若是 DER 格式(`file` 顯示 "data" 或 "ASN.1"),轉 PEM
```bash
for f in root.cer uca.cer server.cer; do
openssl x509 -inform DER -in "$f" -out "$f.pem" && mv "$f.pem" "$f"
done
```
---
## 4. 合成 fullchain.pem 並命名私鑰
```bash
# 合併server 在前,中繼 CA 在後(順序不可反)
cat server.cer uca.cer > fullchain.pem
# 私鑰統一命名
cp <你的key檔> privkey.pem # 例cp tel.key privkey.pem
ls privkey.pem # 確認存在
```
> root.cer 不需放進 fullchain.pemCaddy 只需 leaf + intermediate 就夠。
---
## 5. 驗證「憑證」與「私鑰」是否匹配
**最重要的一步。錯了貼上去 Caddy 會起不來。**
```bash
openssl x509 -in fullchain.pem -noout -modulus | openssl md5
openssl rsa -in privkey.pem -noout -modulus | openssl md5
```
兩個 MD5 **必須完全相同**
```
# 正確範例(兩邊一樣):
# MD5(stdin)= 1c4ae9b6fae3920bb30f76ac792db989
# MD5(stdin)= 1c4ae9b6fae3920bb30f76ac792db989
```
若不同 → **立刻停**。代表這把 key 不是產生 CSR 的那把。回頭找對的 key參考步驟 0 的搜尋方法。
> **2026-04-16 實例**:主機上的 `/opt/caddy/privkey.pem`(舊 HiPKI 那把modulus 為 `c4b56aed...`,新憑證為 `1c4ae9b6...`,不匹配。最後在本機 `~/Downloads/ssl/tel/tel.key` 找到匹配的。
---
## 6. 備份主機上的舊憑證
```bash
ssh hospital_media "sudo mkdir -p /opt/caddy/hospital/ssl_tel_tpech_gov_tw_pre_<年月>_backup && \
sudo cp /opt/caddy/fullchain.pem /opt/caddy/privkey.pem \
/opt/caddy/hospital/ssl_tel_tpech_gov_tw_pre_<年月>_backup/ && \
ls -l /opt/caddy/hospital/ssl_tel_tpech_gov_tw_pre_<年月>_backup/"
```
---
## 7. 上傳新憑證到主機
```bash
# 經由 /tmp 中轉,避免權限問題
scp fullchain.pem privkey.pem hospital_media:/tmp/
ssh hospital_media "sudo mv /tmp/fullchain.pem /tmp/privkey.pem /opt/caddy/ && \
sudo chmod 644 /opt/caddy/fullchain.pem && \
sudo chmod 600 /opt/caddy/privkey.pem && \
ls -l /opt/caddy/fullchain.pem /opt/caddy/privkey.pem"
```
---
## 8. 重啟 Caddy
```bash
# 注意:需要 sudo否則 permission denied
ssh hospital_media "cd /opt/caddy && sudo ./restart.sh"
```
確認 log 無報錯:
```bash
ssh hospital_media "sudo docker logs caddy --tail 20"
# 看到 "serving initial configuration" 且無 error 就算成功
# OCSP stapling timeout 是 warning可忽略
```
---
## 9. 驗證
### 9a. 主機本地驗證(必做,最可靠)
```bash
ssh hospital_media "openssl s_client -connect 127.0.0.1:443 \
-servername tel.tpech.gov.tw </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates"
# 預期:
# subject= ... CN=tel.tpech.gov.tw
# issuer= ... TWCA ...
# notAfter= ...
```
**看到新的 issuer 和到期日 → Caddy 端完成。**
### 9b. 外部驗證(可能看到舊憑證!)
```bash
openssl s_client -connect tel.tpech.gov.tw:443 \
-servername tel.tpech.gov.tw </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
```
> **已知問題**:醫院前端有防火牆 / WAF 做 TLS 終端,從外面連進去看到的可能還是舊憑證。
> 這不是 Caddy 的問題——需要**另外通知網管單位**更新防火牆/WAF 上的憑證。
> 見下方「[防火牆 / WAF 注意事項](#防火牆--waf-注意事項)」。
---
## 10. 歸檔到主機備份目錄
```bash
scp cert.zip fullchain.pem privkey.pem server.cer uca.cer root.cer \
hospital_media:/tmp/
ssh hospital_media "sudo mkdir -p /opt/caddy/hospital/ssl_tel_tpech_gov_tw_<年月> && \
sudo mv /tmp/cert.zip /tmp/fullchain.pem /tmp/privkey.pem \
/tmp/server.cer /tmp/uca.cer /tmp/root.cer \
/opt/caddy/hospital/ssl_tel_tpech_gov_tw_<年月>/ && \
ls -l /opt/caddy/hospital/ssl_tel_tpech_gov_tw_<年月>/"
```
---
## 11. 通知網管 + 更新文件
### 通知網管更新防火牆/WAF
發信或工單給網管單位,內容:
> `tel.tpech.gov.tw:443` 的 SSL 憑證已在伺服器端更新為 TWCA 新憑證(到期 YYYY-MM-DD請同步更新防火牆 / 負載均衡器上的 TLS 終端憑證。
> 新憑證檔案位置:主機 `/opt/caddy/hospital/ssl_tel_tpech_gov_tw_<年月>/`
### 更新本 repo 文件
把以下文件裡 `tel.tpech.gov.tw` 的 CA 與到期日更新:
- [docs/caddy.md](caddy.md) — `Caddy SSL 憑證`
- [docs/ssl.md](ssl.md) — `憑證總覽`
- [docs/maintenance.md](maintenance.md) — `SSL 憑證到期時間`
- [SUMMARY.md](../SUMMARY.md) — 第 6 節
---
## 防火牆 / WAF 注意事項
`106.105.181.40``:443` 前面有醫院的網路設備做 TLS 終端:
```
外部用戶 → [防火牆/WAF :443 (TLS 終端)] → [106.105.181.40 Caddy :443]
```
- Caddy 裝了新憑證,只能讓「防火牆 → Caddy」這段用新憑證。
- 「外部用戶 → 防火牆」那段用的是**防火牆上安裝的憑證**,需要網管另外處理。
- 驗證是否全程更新完成:從外部執行 `openssl s_client`,看到新的 issuer 才算全部搞定。
---
## 回滾流程(萬一 Caddy 起不來)
```bash
ssh hospital_media "sudo cp /opt/caddy/hospital/ssl_tel_tpech_gov_tw_pre_<年月>_backup/fullchain.pem \
/opt/caddy/hospital/ssl_tel_tpech_gov_tw_pre_<年月>_backup/privkey.pem \
/opt/caddy/ && \
cd /opt/caddy && sudo ./restart.sh"
```
回滾後檢查第 5 步的 MD5 是否真的一致、第 4 步的 `cat` 順序是否正確。
---
## 常見地雷
| 症狀 | 通常原因 | 參考步驟 |
|------|----------|----------|
| Caddy 起來但 `ERR_SSL_PROTOCOL_ERROR` | 憑證/私鑰不匹配 | 第 5 步 |
| `NET::ERR_CERT_AUTHORITY_INVALID` | `fullchain.pem` 少了中繼 CA | 第 4 步 |
| `tls: failed to parse private key` | 私鑰格式不對(加密了 / DER 沒轉 PEM | 第 3 步 |
| `scp` 上去後 Caddy 讀不到 | 權限不對644/600 | 第 7 步 |
| `./restart.sh` permission denied | 忘了加 `sudo` | 第 8 步 |
| 外部仍看到舊憑證、本地是新的 | 醫院防火牆/WAF TLS 終端未更新 | 第 9b 步 |
| OCSP stapling timeoutlog warning | 主機對外連線受限,不影響功能 | 可忽略 |
| 主機上的 `privkey.pem` 和新憑證不匹配 | 申請新憑證時用了新 CSR/key舊 key 當然不配 | 第 0/5 步 |
---
## 主機備份目錄結構(供日後查閱)
```
/opt/caddy/hospital/
├── ssl_tel_tpech_gov_tw_2025/ # 2025 HiPKI 憑證原件
├── ssl_tel_tpech_gov_tw_pre_2026_10_backup/ # 2026-04 更新前的舊檔備份
├── ssl_tel_tpech_gov_tw_2026_10/ # 2026 TWCA 憑證原件
├── ssl_tel_server_tpech_gov_tw_2025/ # tel-server 2025 憑證
└── ...
```

112
docs/ssl.md Normal file
View File

@@ -0,0 +1,112 @@
# SSL 憑證管理
## 憑證總覽
兩張憑證分屬不同 CA需各自手動更新。
| 網域 | CA | 到期日 | 使用於 |
|------|----|--------|--------|
| `tel.tpech.gov.tw` | **TWCA**2026-04-16 起) | **2026-10-30** | [Caddy 反向代理](caddy.md) |
| `tel-server.tpech.gov.tw` | 中華電信 HiPKI | 2026-04-23 | [Ant Media Server](antmedia.md) |
> `tel.tpech.gov.tw` 這次只有半年效期4/1510/302026-10 前需再次更新。
## AMS 憑證資訊
| 項目 | 值 |
|------|-----|
| 網域 | `tel-server.tpech.gov.tw` |
| 簽發者 | 中華電信 HiPKI OV TLS CA - G1 |
| 有效期 | 2025-04-23 ~ 2026-04-23 |
| 憑證位置(容器內) | `/usr/local/antmedia/conf/fullchain.pem``privkey.pem``chain.pem` |
| Keystore 密碼 | 網域名稱 `tel-server.tpech.gov.tw`(由容器內 `enable_ssl.sh``generate_password` 決定) |
## 更新 AMS SSL 憑證
### 方法一:使用 `/opt/antmediaserver/enable_ssl.sh`(推薦)
將新的 fullchain.pem + key 放入憑證資料夾,然後一行搞定:
```bash
# 把憑證檔案放到對應資料夾(資料夾內需有 fullchain.pem 和 tel_server_tpech_gov_tw.key
cd /opt/antmediaserver
./enable_ssl.sh ssl_tel_server_tpech_gov_tw_2025
# 或指定網域
./enable_ssl.sh ssl_tel_server_tpech_gov_tw_2025 tel-server.tpech.gov.tw
```
此腳本會自動:`docker cp` 憑證進容器 → 在容器內執行 `enable_ssl.sh` 生成 keystore/truststore 並重啟 AMS。
### 方法二:手動操作
1. 準備 PEM 檔:`fullchain.pem`(伺服器憑證 + 中繼 CA`privkey.pem``chain.pem`(中繼 CA
如果拿到的是 `.cer`DER 格式),先轉換:
```bash
openssl x509 -inform der -in certificate.cer -out certificate.pem
cat server.pem intermediate_ca.pem > fullchain.pem
cp intermediate_ca.pem chain.pem
```
2. 複製進容器並執行:
```bash
docker cp fullchain.pem antmedia:/usr/local/antmedia/
docker cp privkey.pem antmedia:/usr/local/antmedia/
docker cp chain.pem antmedia:/usr/local/antmedia/
docker exec -it antmedia bash -c "cd /usr/local/antmedia && ./enable_ssl.sh \
-d tel-server.tpech.gov.tw \
-f /usr/local/antmedia/fullchain.pem \
-p /usr/local/antmedia/privkey.pem \
-c /usr/local/antmedia/chain.pem"
```
### 驗證
```bash
openssl s_client -connect tel-server.tpech.gov.tw:5443 -servername tel-server.tpech.gov.tw < /dev/null 2>/dev/null | openssl x509 -noout -dates
```
## 更新 Caddy 憑證
詳見 [caddy.md](caddy.md#更新-caddy-憑證)。
## 年度 SSL 更新 checklist
### 步驟一網域驗證DCV
中華電信 HiPKI 簽發憑證前,會要求透過 HTTP 驗證網域所有權。驗證檔案放在:
```
/opt/caddy/tel-server/.well-known/pki-validation/
├── DN_CHECK_FILE.htm # HiPKI DCV 驗證檔JSON 格式,含 randomNumber + expireTime
└── whois.txt # 域名所有權驗證
```
Caddy 中 `tel-server.tpech.gov.tw:80` 設定為靜態檔案服務,就是為了讓 CA 能存取:
`http://tel-server.tpech.gov.tw/.well-known/pki-validation/DN_CHECK_FILE.htm`
流程:
1. 向中華電信提交 CSR 申請憑證
2. 中華電信會提供新的驗證檔案內容
3. 更新 `/opt/caddy/tel-server/.well-known/pki-validation/` 下的檔案
4. 等待 CA 驗證通過後取得新憑證
### 步驟二:安裝新憑證
1. 更新 Caddy 憑證:覆蓋 `/opt/caddy/fullchain.pem` + `privkey.pem` → `./restart.sh`
2. 更新 AMS 憑證:`cd /opt/antmediaserver && ./enable_ssl.sh ssl_tel_server_tpech_gov_tw_<年份>`
3. 備份新憑證到 `/opt/caddy/hospital/` 和 `/opt/antmediaserver/ssl_tel_server_tpech_gov_tw_<年份>/`
4. 備份 AMS 資料:`cd /opt/antmediaserver && ./backup_antmedia_data.sh`
## 具體 SOP
- [SOP更新 Caddy `tel.tpech.gov.tw` 憑證TWCA](sop-update-caddy-ssl.md) — 照著跑
## 相關文件
- [Caddy 反向代理](caddy.md)
- [Ant Media Server](antmedia.md)
- [系統維護與備份](maintenance.md)