用 Ansible 批量检查多台服务器的 Certbot 证书并自动续签

日常运维中经常在多台服务器上使用 Certbot 来管理 HTTPS 证书(Let’s Encrypt)。
Certbot 虽然可以单机自动续签,但如果服务器多:

  • 很难统一查看所有证书的到期情况
  • 如果某台机器的自动续签失败,可能会在业务中断时才发现
  • 每台机器都去登录查看很费时间

为了解决这个问题,我写了一个 Ansible Playbook,可以批量:

  1. 检查所有服务器上的证书有效期
  2. 低于阈值(如 30 天)自动续签
  3. 自动重新加载 Nginx
  4. 可选邮件告警

这样,无论多少台服务器,都可以一键执行并集中查看结果。

Playbook 功能概述

  • 多机批量执行:只要 Ansible inventory 中列出目标主机,就能统一管理
  • 可配置过期阈值:默认 30 天
  • 邮件告警:发现即将过期的证书会发送告警邮件
  • 自动续签:通过 certbot renew 自动续签
  • 自动 reload Nginx:续签成功后立即生效

脚本

---
- name: Smart certbot renewal and nginx reload
  hosts: renew
  become: true
  gather_facts: no

  vars:
    expire_threshold_days: 30

  tasks:
    - name: 检查证书是否快过期
      shell: certbot certificates
      register: certs
      changed_when: false
      ignore_errors: true

    - name: 提取快过期证书信息
      set_fact:
        expiring_certs: >-
          {{ expiring_certs | default([]) +
             [ {'line': item, 'days_left': (item.split('VALID:')[1].split()[0] | int) } ]
             if ('VALID:' in item and (item.split('VALID:')[1].split()[0] | int) < expire_threshold_days)
             else expiring_certs | default([]) }}
      loop: "{{ certs.stdout_lines }}"

    - name: 显示发现的快过期证书(仅调试用)
      debug:
        var: expiring_certs
      when: expiring_certs is defined and expiring_certs | length > 0

    - name: 设置需要续签标志位
      set_fact:
        renew_needed: "{{ (expiring_certs | length) > 0 }}"

    - name: 输出:证书有效,无需续签
      debug:
        msg: "✅ 所有证书均有效(大于 {{ expire_threshold_days }} 天)"
      when: not renew_needed | default(false)

    - name: 发送邮件告警(如果有低于 {{ expire_threshold_days }} 天的证书)
      mail:
        host: smtp服务器
        port: 587
        secure: tls
        username: 邮箱
        password: 密码
        from: 收件邮箱
        to: 收件邮箱
        subject: "证书到期警告"
        body: |
          警告:发现证书有效期低于 {{ expire_threshold_days }} 天,请及时处理。
          具体证书信息如下:
          {% for cert in expiring_certs %}
          - {{ cert.line }}:有效期剩余 {{ cert.days_left }} 天
          {% endfor %}
      when: renew_needed | default(false)
      ignore_errors: true

    - name: 执行证书续签(仅当需要)
      shell: certbot renew --quiet
      register: renew_result
      when: renew_needed | default(false)
      ignore_errors: true

    - name: 输出续签失败信息
      debug:
        msg: "❌ {{ inventory_hostname }} 上续签失败:{{ renew_result.stderr }}"
      when: renew_result is failed

    - name: 重新加载 nginx 服务
      shell: nginx -s reload
      register: nginx_reload_result
      when: renew_needed | default(false) and (renew_result is defined and renew_result.rc == 0)

    - name: 输出 nginx reload 成功提示
      debug:
        msg: "✅ {{ inventory_hostname }} 的 nginx 已重新加载"
      when:
        - nginx_reload_result is defined
        - nginx_reload_result.rc is defined
        - nginx_reload_result.rc == 0

    - name: 输出 nginx reload 失败信息
      debug:
        msg: "❌ {{ inventory_hostname }} nginx reload 失败"
      when:
        - nginx_reload_result is defined
        - nginx_reload_result.rc is defined
        - nginx_reload_result.rc != 0

用 Ansible 做证书检查和续签的好处是:

  • 跨多台服务器统一管理
  • 自动化执行,减少人工干预
  • 邮件、监控等可扩展
  • Playbook 结构清晰,易维护

这样,即使有几十台服务器,也能在几分钟内完成证书检查与续签,最大化减少证书过期风险。