【问题标题】:How to do auto-renewal of TLS certificates with certbot?如何使用 certbot 自动更新 TLS 证书?
【发布时间】:2021-06-12 17:48:05
【问题描述】:

我有一个带有 Nginx docker 容器的应用程序,其 TLS 证书是在部署应用程序的主机(使用 Ubuntu 操作系统)中使用以下命令手动生成的:

certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns -d my.app.com

当证书过期时,我必须更新它们。

但我不能为此使用以下certbot renew 命令,因为它会报错:

$ sudo certbot renew

Failed to renew certificate my.app.com with error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.')

所以,我现在要做的是再次创建证书(使用之前使用的相同 certbot certonly 命令)而不是更新它们。

如何使用certbot renew 命令修复错误?

如何自动执行此设置?

【问题讨论】:

    标签: ubuntu ssl-certificate certbot manual auto-renewing


    【解决方案1】:

    这是我的设置。它涉及生活在 nginx 和 certbot 之间共享的 docker 卷中的 LE 机密,以及 nginx 将续订请求代理到 certbot,因此您不必在 certbot 进行验证时停止 nginx。

    nginx 设置

    将 LE 验证代理到 certbot 后端

    端口 80 上的 letencrypt 验证请求被转发到 certbot,其他任何东西都被重定向到 https。 (如果您想知道为什么我将代理传递后端定义为变量,请参阅this SO answer

      server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
    
        location /.well-known/acme-challenge {
          resolver 127.0.0.11 valid=30s;
          set $upstream letsencrypt;
          proxy_pass http://$upstream:80;
          proxy_set_header Host            $host;
          proxy_set_header X-Forwarded-For $remote_addr;
          proxy_set_header X-Forwarded-Proto https;
        }
    
        location / {
          return 301 https://$host$request_uri;
        }
      }
    

    SSL 设置

    这里有很多标准的东西:

      server {
        listen 443 ssl;
        server_name ${DOMAINNAME};
    
        ssl_certificate /etc/letsencrypt/live/${DOMAINNAME}/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/${DOMAINNAME}/privkey.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1.2;
        ssl_ciphers 'EECDH+AESGCM: EDH+AESGCM:AES256+EECDH:AES256+EDH';
        ssl_prefer_server_ciphers on;
    
        ssl_session_cache shared:SSL:10m;
        ssl_dhparam dhparam.pem;
    
        ... your lcoation block goes here ...
    
    }
    

    docker-compose 魔法

    证书机器人

    有一个特殊的“docker-compose-LE.yml”来单独运行 certbot:

    version: '3.4'
    
    services:
    
      letsencrypt:
        image: certbot/certbot:latest
        command: sh -c "certbot certonly --standalone -d ${DOMAINNAME} --text --agree-tos --email you@example.com --server https://acme-v02.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --preferred-challenges=http"
        entrypoint: ""
        volumes:
          - "letsencrypt:/etc/letsencrypt"
        environment:
          - TERM=xterm
    
    volumes:
      letsencrypt:
        name: letsencrypt_keys
    

    通过运行“docker-compose -f docker-compose-LE.yml up”,您将创建并验证证书。您可以使用相同的命令来更新证书,certbot 就是这么聪明。您可以(每天)尽可能频繁地运行此命令,因为它只会在您的证书即将到期时更新您的证书。

    在第一次运行此命令之前,请参阅下面的“警告”。

    nginx

    在 docker-compose.yml 中挂载卷中的证书。该卷已由letsencrypt创建,因此将其声明为外部。

    services:
      nginx:
        image: nginx:1.18
        restart: always
        volumes:
          - letsencrypt:/etc/letsencrypt:ro
    
    volumes:
      letsencrypt:
        external:
          name: letsencrypt_keys
    

    警告

    此方法在第一次创建证书时会导致鸡蛋问题:没有证书文件,nginx 将无法启动并且无法代理 LE 验证。没有nginx就是没有证书,没有证书就是没有nginx。

    要解决这个问题,您必须在没有 nginx 的情况下首次调用 certbot 并使用 certbots 暴露的内部 http 服务器。因此,第一次运行 certbot 时,将这些行添加到 docker-compose-LE.yml:

      letsencrypt:
        ports:
          - "80:80"
    

    证书更新

    只需在每日 cronjob 中运行这两个命令:

    docker-compose -f docker-compose-LE.yml up
    

    将检查证书并在到期后开始续订过程。现在正在运行的 nginx 会将认证验证代理到 certbot。

    docker-compose exec nginx nginx -s reload
    

    一旦证书在 docker 卷 certbot 和 nginx 共享中就地更新,只需向 nginx 发送一个 SIGHUP 以便它重新加载证书文件而不会中断服务。

    【讨论】:

      【解决方案2】:

      我需要使用“外部”网络来允许来自两个 docker-compose 文件的容器进行通信。谢谢!

      version: '3.4'
      services:
        letsencrypt:
          container_name: "letsencrypt"
            #ports:
              #- "80:80"
          image: certbot/certbot:latest
          command: sh -c "certbot certonly --standalone --rsa-key-size 4096 --agree-tos --preferred-challenges http -d ${DOMAINNAME} -m ${CONTACT_EMAIL} -n"
          entrypoint: ""
          volumes:
            - "letsencrypt:/etc/letsencrypt"
          networks:
            - web_nw
      networks:
        web_nw:
          external: true
      volumes:
        letsencrypt:
          name: letsencrypt
      

      【讨论】:

        猜你喜欢
        • 2019-08-17
        • 1970-01-01
        • 2017-02-23
        • 2021-01-19
        • 1970-01-01
        • 2017-05-22
        • 2017-10-28
        • 2019-09-10
        • 2021-06-12
        相关资源
        最近更新 更多