Traefik 自動化 HTTPS:Let's Encrypt 自動憑證申請與設定

Traefik 整合了 ACME 協定,能夠自動向 Let's Encrypt 申請並更新 SSL 憑證。這意味著你不再需要手動跑 Certbot,也不用擔心憑證過期。

要啟用這個功能,我們需要做兩件事:

  1. 設定 Certificate Resolver (憑證解析器)。
  2. 在 Router 上啟用 TLS 並指定使用哪個 Resolver。

1. 設定 Certificate Resolver

我們需要在 Traefik 的啟動參數 (Static Configuration) 中定義 Resolver。

修改 docker-compose.yml 中的 command 區塊,加入以下內容:

command:
  # ... (保留之前的設定) ...
  # 定義一個名為 "myresolver" 的 Resolver
  - '--certificatesresolvers.myresolver.acme.email=your-email@example.com' # 填入你的 Email (用於接收通知)
  - '--certificatesresolvers.myresolver.acme.storage=acme.json' # 憑證儲存位置
  # 使用 TLS Challenge (最簡單的驗證方式)
  - '--certificatesresolvers.myresolver.acme.tlschallenge=true'
  # (選用) 測試階段建議使用 Staging Server,以免因為設定錯誤導致請求次數過多被封鎖
  # - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"

持久化 acme.json

我們設定憑證儲存在 acme.json。為了避免重新部署容器時憑證遺失 (導致重新申請次數過多被 Let's Encrypt 封鎖),我們必須將這個檔案掛載到 host 上。

docker-compose.ymlvolumes 區塊加入:

volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro
  # 建立一個空的 acme.json 檔案並掛載
  - ./acme.json:/acme.json

注意:在 Linux/Mac 上,acme.json 的權限必須是 600。請先在 host 端執行:

touch acme.json
chmod 600 acme.json

2. 在 Router 上啟用 TLS

接著,在你的服務 (例如 whoami) 的 Labels 中啟用 TLS:

whoami:
  image: traefik/whoami
  labels:
    - 'traefik.enable=true'
    # 修改 Host 為你的真實網域 (Let's Encrypt 需要公網域名)
    - 'traefik.http.routers.whoami.rule=Host(`whoami.your-domain.com`)'
    - 'traefik.http.routers.whoami.entrypoints=websecure' # 注意:改用 websecure (443)
    # 指定使用我們定義的 resolver
    - 'traefik.http.routers.whoami.tls.certresolver=myresolver'

並且別忘了在 Traefik 的 command 中啟用 HTTPS 入口點 (EntryPoints):

command:
  # ...
  - '--entrypoints.websecure.address=:443'

以及在 ports 開放 443:

ports:
  - '80:80'
  - '443:443'
  - '8080:8080'

3. 強制 HTTP 轉 HTTPS (Global Redirection)

為了安全性,我們通常希望將所有 HTTP (Port 80) 的流量自動導向 HTTPS (Port 443)。

最簡單的方法是在 EntryPoint 層級做全域設定。在 command 加入:

command:
  # ...
  - '--entrypoints.web.address=:80'
  # 全域轉址:所有進入 web (80) 的流量都轉到 websecure (443)
  - '--entrypoints.web.http.redirections.entryPoint.to=websecure'
  - '--entrypoints.web.http.redirections.entryPoint.scheme=https'

驗證 HTTPS

重新啟動 Docker Compose:

docker compose up -d

等待幾秒鐘後,打開瀏覽器存取 https://whoami.your-domain.com。你應該會看到鎖頭圖示,並且憑證是由 Let's Encrypt 簽發的。

Challenge Types (驗證方式)

Let's Encrypt 需要驗證你擁有該網域的控制權。Traefik 支援三種驗證方式:

  1. TLS Challenge (tlschallenge)

    • 原理:Let's Encrypt 會透過 TLS (Port 443) 連線到你的伺服器並驗證憑證。
    • 優點:設定最簡單,不需要額外配置。
    • 限制:只能驗證單一網域,不支援萬用字元 (Wildcard) 網域。且 Port 443 必須對外開放。
  2. HTTP Challenge (httpchallenge)

    • 原理:Let's Encrypt 會存取 http://your-domain.com/.well-known/acme-challenge/...
    • 設定
      - '--certificatesresolvers.myresolver.acme.httpchallenge=true'
      - '--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web'
      
    • 限制:不支援 Wildcard。Port 80 必須對外開放。
  3. DNS Challenge (dnschallenge)

    • 原理:Traefik 會透過 API 在你的 DNS 服務商 (如 Cloudflare, AWS Route53) 新增 TXT 記錄。
    • 優點:支援 Wildcard Certificates (*.example.com)。不需要開放 Port 80/443 (適合內網服務)。
    • 缺點:設定較複雜,需要提供 DNS 服務商的 API Key。

對於初學者,建議先從 TLS Challenge 開始。如果有 Wildcard 需求,再進階到 DNS Challenge。