如何在群中将 SNI 证书上传到 traefik/consul

How to upload SNI certificates to traefik/consul in a swarm

我们正在使用下面的 docker 堆栈文件在 docker 群中部署 consul 和 traefik。这从 Lets Encrypt 生成了 SSL 证书并按预期工作。但是,我们已经预先购买了我们希望用于某些域的通配符链证书(.crt 和 .key)。我们如何上传这些以代替 lets encrypt 证书使用?

version: '3'

services:
  consul-leader:
    container_name: consul-leader
    image: consul
    command: agent -server -client=0.0.0.0 -bootstrap -ui
    volumes:
      - consul-data-leader:/consul/data
    environment:
      - CONSUL_BIND_INTERFACE=eth0
      - 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true}'
    networks:
      - default
      - front-end
    deploy:
      labels:
        - traefik.frontend.rule=Host:consul.domain.com
        - traefik.port=8500
        - traefik.docker.network=front-end
        # Traefik service that listens to HTTP
        - traefik.redirectorservice.frontend.entryPoints=http
        - traefik.redirectorservice.frontend.redirect.entryPoint=https
        # Traefik service that listens to HTTPS
        - traefik.webservice.frontend.entryPoints=https

  consul-replica:
    container_name: consul-replica
    image: consul
    command: agent -server -client=0.0.0.0 -retry-join="consul-leader"
    volumes:
      - consul-data-replica:/consul/data
    environment:
      - CONSUL_BIND_INTERFACE=eth0
      - 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true}'
    networks:
      - default
      - front-end
    deploy:
      replicas: 0
      placement:
        preferences:
          - spread: node.id

  traefik:
    container_name: traefik
    image: traefik:v1.7
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
        preferences:
          - spread: node.id
      labels:
        - traefik.frontend.rule=Host:traefik.domain.com
        - traefik.port=8080
        - traefik.docker.network=front-end
        # Traefik service that listens to HTTP
        - traefik.redirectorservice.frontend.entryPoints=http
        - traefik.redirectorservice.frontend.redirect.entryPoint=https
        # Traefik service that listens to HTTPS
        - traefik.webservice.frontend.entryPoints=https
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /docker/ssl:/docker/ssl
    command: >
      --docker
      --docker.swarmmode
      --docker.watch
      --docker.exposedbydefault=true
      --entrypoints='Name:http Address::80'
      --entrypoints='Name:https Address::443 TLS'
      --consul
      --consul.watch
      --consul.endpoint="consul-leader:8500"
      --acme
      --acme.email=example@email.com
      --acme.storage="traefik/acme/account"
      --acme.entryPoint=https
      --acme.httpChallenge.entryPoint=http
      --acme.onhostrule=true
      --acme.acmelogging=true
      --logLevel=INFO
      --accessLog
      --api
    networks:
      - default
      - front-end
    depends_on:
      - consul-leader

volumes:
  consul-data-leader:
  consul-data-replica:

networks:
  front-end:
    name: front-end
    driver: overlay

Traefik 可以为每个入口点配置多个证书,即

[entryPoints.http.tls]      
  [[entryPoints.http.tls.certificates]]
    certFile = "path/to/my-lets-encrypt.cert"
    keyFile = "path/to/my-lets-encrypt.key"
  [[entryPoints.http.tls.certificates]]
    certFile = "path/to/my-purchased.cert"
    keyFile = "path/to/my-purchased.key"

将根据请求的 host header 决定投放。这意味着如果您希望域:my-important-domain.com 与购买的证书一起提供,您必须确保只为该域颁发该证书作为主题或圣。这意味着这些域需要从 ACME traefik 配置中排除。

检查下面的相关 docs,其中描述了如何做到这一点

# Domains list.
# Only domains defined here can generate wildcard certificates.
# The certificates for these domains are negotiated at traefik startup only.
#
# [[acme.domains]]
#   main = "local1.com"
#   sans = ["test1.local1.com", "test2.local1.com"]
# [[acme.domains]]
#   main = "local2.com"
# [[acme.domains]]
#   main = "*.local3.com"
#   sans = ["local3.com", "test1.test1.local3.com"]