前言
今天原本使用好好的政府 OpenData API (https://gcis.nat.gov.tw) 在 Dify 的 Http 節點中居然出現[SSL:CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1010)
的錯誤。
以下紀錄在部署 Dify 至 Ubuntu Docker Compose 環境時,遇到 SSL 憑證驗證失敗的問題,包含台灣政府 CA 安裝、Python certifi 處理、Proxy 設定與完整排查修復流程。
問題
先在 Ubuntu 執行 curl 就出現curl: (60) SSL certificate problem: unable to get local issuer certificate的錯誤。
Step 1.確認 ubuntu SSL 問題
使用 openssl 檢查憑證鏈:
1 | openssl s_client -connect data.gcis.nat.gov.tw:443 |
結果如下,
1 | Server certificate |
Verification error: unable to verify the first certificate可以發現沒有 Root CA。
Step 2.安裝 HiPKI OV TLS CA
到中華電信公開憑證下載HiPKI OV TLS CA,
並放到 /usr/local/share/ca-certificates/
目錄中
1 | wget https://epki.com.tw/repository-h/download/OVTLSCA1_b64.crt -O /usr/local/share/ca-certificates/OVTLSCA1_b64.crt |
更新系統 CA
1 | sudo update-ca-certificates |
結果如下,
1 | 1 added, 0 removed; done. |
再使用 openssl 檢查憑證鏈echo | openssl s_client -showcerts -connect data.gcis.nat.gov.tw:443
可以發現已經驗證成功,
1 | SSL handshake has read 7920 bytes and written 448 bytes |
完成後,再到 Dify 執行,還是出現[SSL:CERTIFICATE_VERIFY_FAILED]
錯誤,
接下來,要來查看 Dify Docker 中的問題
Step 3.查看 Api Log
查看 Api 的 Log
1 | docker compose logs api |
輸出如下,
1 | [ssrf_proxy.py:78] - Request to URL http://data.gcis.nat.gov.tw/od/data/api/5F64D864-61CB-4D0D-8AD9-492047CC1EA6?$format=json&$filter=Business_Accounting_NO eq 22425662 failed on attempt 1: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1010) |
Step 4.確認 API Container 的憑證環境
進入 API Container
1 | docker compose exec api bash |
確認 Python certifi 使用的憑證:
1 | python3 -c "import certifi; print(certifi.where())" |
結果如下,
1 | /app/api/.venv/lib/python3.12/site-packages/certifi/cacert.pem |
Step 5.替換 certifi 的憑證檔
ubuntu host 的憑證是 OK 的,所以可以在docker-compose.yaml
設定 volume,
修改 dify 的 docker-compose.yaml 在 api 的 volumes 加入以下設定
1 | api: |
- 將 VM Host 上最新的 CA cert 掛到 container 的 OS 層 /etc/ssl/certs/ca-certificates.crt
- 將 VM Host 的 CA cert 掛到 Python certifi 套件的 cert 檔案路徑
重新執行docker compose
並測試看看,
1 | docker compose down |
再從 dify 去測試,可以發現 Http 節點,已經可以順利執行成功了。
結語
以上的 SSL 問題排查流程,驗證了一個 Containerized 架構下的典型 SSL 問題:
- VM 憑證要先驗證成功。
- Docker Container 須確認 CA cert 路徑。
- Python 的 certifi 使用獨立 cert,若寫死 verify=certifi.where() 就要特別處理。
參考資源
中華電信公開憑證
SSL Cert Verification
Install a root CA certificate in the trust store
update-ca-certificates 說明