新增分拆文件、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

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)