【问题标题】:Use existing LetsEncrypt certificates in Traefik在 Traefik 中使用现有的 LetsEncrypt 证书
【发布时间】:2018-11-07 14:19:10
【问题描述】:

是否可以在 Traefik 中使用现有的 LetsEncrypt 证书(.pem 格式)?

我已设置 Traefik/Docker 以生成 acme.json - 我可以为一组域导入现有证书吗?

【问题讨论】:

    标签: lets-encrypt traefik


    【解决方案1】:

    尽管可能有人想知道你为什么真的想要/需要这个,并且任何人都会建议你不要这样做,因为 traefik 很好地处理了自动重新挑战,这就是 acme.json 的样子:

    {
      "Account": {
        "Email": "acme@example.com",
        "Registration": {
          "body": {
            "status": "valid",
            "contact": [
              "mailto:acme@example.com"
            ]
          },
          "uri": "https://acme-v02.api.letsencrypt.org/acme/acct/12345678"
        },
        "PrivateKey": "ABCD...EFG="
      },
      "Certificates": [
        {
          "Domain": {
            "Main": "example.com",
            "SANs": null
          },
          "Certificate": "ABC...DEF=",
          "Key": "ABC...DEF"
        },
        {
          "Domain": {
            "Main": "anotherexample.com",
            "SANs": null
          },
          "Certificate": "ABC...DEF==",
          "Key": "ABC...DEF=="
        }
      ],
      "HTTPChallenges": {}
    }
    

    现在由您来编写导入脚本或模板解析器来遍历您的证书/密钥并将内容放入括号中,或者只生成您自己的该格式的 json 文件。

    请注意,它的格式与经典 pem 样式略有不同(即没有换行符)。

    【讨论】:

    • 感谢指针和对这种解析废话的警告!我发布了我最终找到的(更明智的)解决方案的完整文章。
    【解决方案2】:

    最终我找到了正确的解决方案——不使用 Traefik 的 ACME 集成,而是简单地挂载一个包含 certbot 在手动模式下颁发的证书的网络卷 (EFS)。

    为什么这是我选择的方法?因为我在 两个 服务器(蓝色和绿色)上安装了持有证书的 NFS 卷。这些服务器是 Web 服务器的实时和登台服务器。在任何时候,一个都将处于“实时”状态,另一个可以运行候选版本或以其他方式处于“热备用”角色。

    因此,最好分离关注点并让第三台服务器作为专用的“证书管理器”运行。这台 t2.nano 服务器基本上不会被触动,它只负责每周运行一次 certbot,将证书写入一个 NFS 挂载,由两个 Web 服务器共享(以只读模式)。

    通过这种方式,Traefik 在蓝色和绿色服务器上运行,以处理代理 Web 流量的主要问题,并简单地指向 certbot 颁发的证书文件。对于那些发现此页面并可以从相同解决方案中受益的人,以下是我的 traefik.toml 文件中的相关摘录:

    defaultEntryPoints = ["https","http"]
    
    [docker]
    watch = true
    exposedbydefault = false
    swarmMode = true
    
    [entryPoints]
      [entryPoints.http]
      address = ":80"
        [entryPoints.http.redirect]
        entryPoint = "https"
      [entryPoints.https]
      address = ":443"
      [entryPoints.https.tls]
        [[entryPoints.https.tls.certificates]]
        certFile = "/cert.pem"
        keyFile = "/privkey.pem"
    

    这是我的 Docker swarm 堆栈文件中的相关部分:

    version: '3.2'
    
    volumes:
     composer:
    
    networks:
      traefik:
        external: true
    
    services:
      proxy:
        image: traefik:latest
        command: --docker --web --docker.swarmmode --logLevel=DEBUG
        ports:
          - "80:80"
          - "443:443"
          - "8080:8080"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - ./traefik.toml:/traefik.toml
          - "./certs/live/example.com/fullchain.pem:/cert.pem"
          - "./certs/live/example.com/privkey.pem:/privkey.pem"
        networks:
          - traefik
    

    最后是 cron 在专用证书服务器上每周运行一次的命令,配置为使用 ACME v2 进行通配符证书和 Route 53 集成以实现挑战自动化:

    sudo docker run -it --rm --name certbot                                      \
                -v `pwd`/certs:/etc/letsencrypt                                  \
                -v `pwd`/lib:/var/lib/letsencrypt                                \
                -v `pwd`/log:/var/log/letsencrypt                                \
                --env-file ./env                                                 \
                certbot/dns-route53                                              \
                certonly --dns-route53                                           \
                         --server https://acme-v02.api.letsencrypt.org/directory \
                         -d example.com                                          \
                         -d example.net                                          \
                         -d *.example.com                                        \
                         -d *.example.net                                        \
                         --non-interactive                                       \
                         -m me@example.org                                       \
                         --agree-tos
    

    文件夹certs是三台服务器共享的NFS卷。

    【讨论】:

      【解决方案3】:

      我只想补充一点,我在需要使用 HAProxy 的同时找到了另一种方法:

      • 仅在 HAProxy 后面的 81 端口为 acme 运行一个 traefik
        acl acme path_beg -i /.well-known/acme-challenge/
        use_backend acme if acme
      
      • 有一个小型网络服务器提供 acme.json(即 shell2http)
      • 有一个 cronjob(我使用 gitlab ci)下载 acme.json 并提取证书 (https://github.com/containous/traefik/blob/821ad31cf6e7721ba231164ab468ee554983560f/contrib/scripts/dumpcerts.sh)
      • 将证书附加到 traefik.toml 模板
      • 构建 docker 镜像并推送到私有注册表
      • 在 HAProxy 后面的任何后端服务器上以只读模式在 80/443 上将此私有 traefik 实例作为主 traefik 运行
      • 编写一个文件监视脚本,当 acme.json 更改并触发 dumpcert-script 时,它会重新启动所有 ro-traefiks

      【讨论】:

        【解决方案4】:

        完成sgohl回复:

        重要提示:确保私钥长度为 4096 位。 2048 位将工作,并且 traefik 将尝试向 Letsencrypt 请求新证书。

        1. 识别您的(在此示例中为 certbot)证书。示例:
        /etc/letsencrypt/live
        
        ├── example.com
        │   ├── cert.pem -> ../../archive/example.com/cert6.pem
        │   ├── chain.pem -> ../../archive/example.com/chain6.pem
        │   ├── fullchain.pem -> ../../archive/example.com/fullchain6.pem
        │   ├── privkey.pem -> ../../archive/example.com/privkey6.pem
        │   └── README
        
        1. 检查私钥是否为 4096 位长:
        openssl rsa -text -in privkey.pem | grep bit
        

        预期结果类似于:

        writing RSA key
        RSA Private-Key: (4096 bit, 2 primes)
        
        1. 生成包含所需证书的字符串。

        3.1。证书

        _IN=/etc/letsencrypt/live/example.com/fullchain.pem
        _OUT=~/traefik_certificate
        cat $_IN | base64 | tr '\n' ' ' | sed --expression='s/\ //g' > $_OUT
        

        3.2。私钥

        _IN=/etc/letsencrypt/live/example.com/privkey.pem
        _OUT=~/traefik_key
        cat $_IN | base64 | tr '\n' ' ' | sed --expression='s/\ //g' > $_OUT
        
        1. 准备包含上述字符串的代码 sn-p:
        ...
            "Certificates": [
              {
                "domain": {
                  "main": "example.com"
                },
                "certificate": "CONTENT_OF_traefik_certificate",
                "key": "CONTENT_OF_certificate",
                "Store": "default"
              },
        ...
        
        1. 将上述代码 sn-p 放在 traefik 的 acme.json 文件中的正确位置(在“证书”JSON 键下方):
        vim /path/to/acme.json
        

        无需重启 traefik 容器即可选择新证书。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-18
          • 2021-10-13
          • 2020-11-09
          • 2019-07-19
          • 2016-11-13
          相关资源
          最近更新 更多