Skip to content

Certbot 实现 HTTPS 免费证书(Let‘s Encrypt)自动续期

安装 Certbot

bash
sudo snap install --classic certbot

如果提示:sudo: snap:找不到命令。因为 CentOS 默认不支持 snap 包管理工具,因此你需要使用 Certbot 的其他安装方式来申请 SSL 证书。对于 CentOS,通常使用 EPEL(Extra Packages for Enterprise Linux)存储库和 dnf 或 yum 包管理器来安装 Certbot

安装 Certbot 的步骤(适用于 CentOS 7/8):

  1. 启用 EPEL 存储库

    首先需要安装 EPEL 存储库,Certbot 依赖这个存储库中的一些工具。

bash
sudo yum install epel-release

安装 Certbot

安装 Certbot 和 Nginx 插件,一路按 y 回车(如有):

bash
sudo yum install certbot python3-certbot-nginx

验证是否成功安装 Certbot

bash
certbot --version

#输出:certbot 2.11.0

准备 Certbot 命令

bash
sudo ln -s /snap/bin/certbot /usr/bin/certbot

手动运行方式

bash
certbot -d 域名(可以使用*.代表所有二级域名) --manual --config-dir config --work-dir work --logs-dir logs --preferred-challenges dns certonly

我的域名是 seasir.top,命令格式如下:

bash
certbot -d seasir.top -d *.seasir.top --manual --config-dir config --work-dir work --logs-dir logs --preferred-challenges dns certonly
bash
#将调试日志保存到/root/logs/letsencrypt.log输入电子邮件地址(用于紧急续订和安全通知)(输入“c”取消):2429016980@q9.com

Saving debug log to /root/logs/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel):2429016980@qq.com(输入自己的邮箱)
bash
#请阅读服务条款,网址为nttps://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf。您必须同意才能在ACME服务器注册。您同意吗?(Y)是/(N)或:y

Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
bash
#旦您成功获得第一张证书,您是否愿意与电子前沿基金会共享您的电子邮件地址?电子前沿基金会是 Let'sEncrypt项目的创始合作伙伴,也是开发 Certbot的非营利组织。我们希望向您发送有关我们为网络加密的工作、EFF 新闻、活动以及支持数字自由方式的电子邮件
#(Y)是/(N)否:

Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y

根据提示部署 DNS TXT 记录

操作步骤:

登录 DNS 服务提供商控制台:通常是你在注册域名时使用的服务商,可能是腾讯云、阿里云、Cloudflare 等。我自己的是阿里云

找到域名解析设置:在控制台中找到你的域名 seasir.top 的解析设置(通常叫做 "DNS" 或 "域名解析")

添加 TXT 记录

  • 记录类型:选择 TXT 记录。

  • 主机记录:输入 _acme-challenge(完整的记录将变成 _acme-challenge.seasir.top

  • 记录值:输入 Certbot 返回的 value 值,比如: hMPUVxWJ_SfLRabX7xpE1OJ_blSEzrvaxuabkNwKPyc

警告

使用 DNS 验证可以很方便的手动生成 SSL 证书,但是每次续期的时候要求填写的 TXT 记录都不同,这意味着基于 DNS 验证的自动续期必须动态修改DNS 的 TXT 记录。

提示

每次重新运行记录值会发生改变,以自己实际为准!

bash
certbot -d seasir.top -d *.seasir.top --manual --config-dir config --work-dir work --logs-dir logs --preferred-challenges dns certonly
  • TTL:可以选择默认值(例如 10 分钟或 600 秒)。
bash
Successfully received certificate.   #成功领取证书。
Certificate is saved at: /root/config/live/seasir.top/fullchain.pem  #证书保存为位置--关键文件
Key is saved at:         /root/config/live/seasir.top/privkey.pem    #证书保存为位置--关键文件
This certificate expires on 2025-01-03.                              #证书有效日期
These files will be updated when the certificate renews.

Nginx 配置

拷贝文件

由于我的服务器是本地虚拟机 frp 出去的,所以在云服务器/etc/nginx/ssl新建 ssl 目录

bash
#进入/etc/nginx/目录
cd /etc/nginx/

#创建ssl文件夹
mkdir ssl

进入云服务器文件路径:/root/config/live/seasir.top把这两个fullchain.pemprivkey.pem文件 copy 进刚刚创建的 ssl 文件夹:/etc/nginx/ssl

可使用Xftp软件进行拷贝操作,可视化界面,对小白友好,当然使用 linux 命令拷贝也行~

bash
[root@VM-4-16-centos nginx]# cd ssl
[root@VM-4-16-centos ssl]# ll
总用量 8
-rw-r--r-- 1 root root 2843 10月  5 17:12 fullchain.pem
-rw-r--r-- 1 root root  241 10月  5 17:12 privkey.pem

设置fullchain.pemprivkey.pem文件权限

bash
sudo chmod 644 fullchain.pem
sudo chmod 600 privkey.pem

创建 SSL 和反向代理公共配置文件

创建common_configs文件夹

bash
#进入/etc/nginx/目录
cd /etc/nginx/

#创建common_configs文件夹
mkdir common_configs

common_configs文件夹下分别创建common_proxy_params.confcommon_ssl_params.conf

bash
#进入/etc/nginx/common_configs目录
cd /etc/nginx/common_configs

#创建common_proxy_params.conf和common_ssl_params.conf文件
sudo touch /etc/nginx/common_configs/common_proxy_params.conf
sudo touch /etc/nginx/common_configs/common_ssl_params.conf

填入common_proxy_params.confcommon_ssl_params.conf配置,如下:

nginx
#common_proxy_params.conf

# 定义反向代理公用参数
client_max_body_size 100M;  # 设置客户端最大请求体大小为 100M
proxy_set_header Host $host;  # 转发 Host 头
proxy_set_header X-Real-IP $remote_addr;  # 转发客户端真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 转发代理链中的 IP
proxy_set_header X-Forwarded-Proto $scheme;  # 转发请求协议
bash
#common_ssl_params.conf

# 定义 SSL 配置的公用参数
ssl_certificate "ssl/fullchain.pem";  # SSL 证书路径
ssl_certificate_key "ssl/privkey.pem";  # SSL 私钥路径
ssl_session_cache shared:SSL:1m;  # SSL 会话缓存
ssl_session_timeout  10m;  # SSL 会话超时时间
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;  # 加密套件
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;  # 支持的 TLS 协议版本
ssl_prefer_server_ciphers on;  # 优先使用服务器端的加密套件

使用 chmod 命令来为 common_proxy_params.confcommon_ssl_params.conf 这两个文件设置 644 权限。以下是具体命令:

bash
chmod 644 common_proxy_params.conf common_ssl_params.conf

Nginx.conf 配置文件

ecs 的 Nginx.conf 路径:/etc/nginx.nginx.conf,配置如下:

nginx
user  root;  # 设置 Nginx 运行的用户为 root
worker_processes auto;  # 自动设置工作进程的数量
error_log /var/log/nginx/error.log;  # 错误日志文件的路径
pid /run/nginx.pid;  # Nginx 进程的 PID 文件路径

# 加载动态模块
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;  # 每个工作进程允许的最大连接数
}

http {
    gzip on;  # 启用 gzip 压缩
    gzip_vary on;  # 根据请求中的 `Accept-Encoding` 响应头决定是否启用 gzip
    gzip_proxied any;  # 在所有代理请求中启用压缩
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;  # 指定需要压缩的响应类型
    gzip_comp_level 5;  # 压缩等级(1-9)
    gzip_min_length 256;  # 只对超过指定长度的响应启用压缩

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';  # 定义日志格式

    access_log  /var/log/nginx/access.log  main;  # 访问日志的路径

    sendfile            on;  # 启用高效文件传输
    tcp_nopush          on;  # 优化 TCP 数据包传输
    tcp_nodelay         on;  # 关闭 Nagle 算法,减少延迟
    keepalive_timeout   65;  # 设置保持连接的超时时间
    types_hash_max_size 4096;  # 设置 MIME 类型哈希表的最大大小

    include             /etc/nginx/mime.types;  # 包含 MIME 类型定义文件
    default_type        application/octet-stream;  # 默认的响应类型

    # 从 /etc/nginx/conf.d 目录加载模块化配置文件
    include /etc/nginx/conf.d/*.conf;  # 加载其他配置文件
    charset utf-8;  # 设置字符集为 UTF-8

    # 公共配置文件引入
    include /etc/nginx/common_configs/common_ssl_params.conf;  # 引入 SSL 公用参数
    include /etc/nginx/common_configs/common_proxy_params.conf;  # 引入反向代理公用参数

    # 其他 server 块可以类似配置...
}

blog.conf 配置文件

ecs 的 blog.conf 路径:/etc/nginx/conf.d/blog.conf,配置如下:

nginx
# 定义一个公共的 error_page 配置
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

# HTTP 服务器块
server {
    listen 80;  # 监听 80 端口
    server_name blog.seasir.top;  # 前台域名

    # 配置 HTTP 到 HTTPS 的重定向
    return 301 https://$host$request_uri;  # 重定向到 HTTPS
}

server {
    listen 443 ssl;  # 监听 443 端口,启用 SSL
    listen [::]:443 ssl;  # 支持 IPv6
    server_name blog.seasir.top;  # 前台域名

    location / {
        proxy_pass http://云服务器IP:8082/;  # 反向代理到实际后台路径
        include /etc/nginx/common_configs/common_proxy_params.conf;  # 引入反向代理公用参数
    }

    include /etc/nginx/common_configs/common_ssl_params.conf;  # 引入 SSL 公用参数
}

# 后台域名的 HTTP 服务器块
server {
    listen 80;  # 监听 80 端口
    server_name admin.seasir.top;  # 后台域名

    # 配置 HTTP 到 HTTPS 的重定向
    return 301 https://$host$request_uri;  # 重定向到 HTTPS
}

server {
    listen 443 ssl;  # 监听 443 端口,启用 SSL
    listen [::]:443 ssl;  # 支持 IPv6
    server_name admin.seasir.top;  # 后台域名

    location / {
        proxy_pass http://云服务器IP:8083/;  # 反向代理到实际后台路径
        include /etc/nginx/common_configs/common_proxy_params.conf;  # 引入反向代理公用参数
    }

    include /etc/nginx/common_configs/common_ssl_params.conf;  # 引入 SSL 公用参数
}

# Minio 域名的 HTTP 服务器块
server {
    listen 80;  # 监听 80 端口
    server_name minio.seasir.top;  # Minio 域名

    # 配置 HTTP 到 HTTPS 的重定向
    return 301 https://$host$request_uri;  # 重定向到 HTTPS
}

server {
    listen 443 ssl;  # 监听 443 端口,启用 SSL
    listen [::]:443 ssl;  # 支持 IPv6
    server_name minio.seasir.top;  # Minio 域名

    location / {
        proxy_pass http://云服务器IP:9000/;  # 反向代理到实际后台路径
        include /etc/nginx/common_configs/common_proxy_params.conf;  # 引入反向代理公用参数
    }

    include /etc/nginx/common_configs/common_ssl_params.conf;  # 引入 SSL 公用参数
}

# Hitokoto 域名的 HTTP 服务器块
server {
    listen 80;  # 监听 80 端口
    server_name hitokoto.seasir.top;  # Hitokoto 域名

    # 配置 HTTP 到 HTTPS 的重定向
    return 301 https://$host$request_uri;  # 重定向到 HTTPS
}

server {
    listen 443 ssl;  # 监听 443 端口,启用 SSL
    listen [::]:443 ssl;  # 支持 IPv6
    server_name hitokoto.seasir.top;  # Hitokoto 域名

    location / {
        proxy_pass http://云服务器IP:8084/;  # 反向代理到实际后台路径
        include /etc/nginx/common_configs/common_proxy_params.conf;  # 引入反向代理公用参数
    }

    include /etc/nginx/common_configs/common_ssl_params.conf;  # 引入 SSL 公用参数
}

ecs 里的 nginx 配置目录和文件(配置后的

bash
[root@VM-4-16-centos nginx]# ll
总用量 40
drwxr-xr-x 2 root root 4096 12月 22 22:49 common_configs
drwxr-xr-x 2 root root 4096 2月  28 23:28 conf.d
-rw-r--r-- 1 root root 1007 5月  30 2024 fastcgi_params
-rw-r--r-- 1 root root 5349 5月  30 2024 mime.types
-rw-r--r-- 1 root root 2374 1月   4 23:34 nginx.conf
-rw-r--r-- 1 root root 2109 10月  9 22:49 nginx.conf.bak
-rw-r--r-- 1 root root  636 5月  30 2024 scgi_params
drwxr-xr-x 2 root root 4096 10月  5 17:12 ssl
-rw-r--r-- 1 root root  664 5月  30 2024 uwsgi_params

CND 证书配置

警告

如果二级域名配置了CND加速,也需要前往CND服务商配置下HTTPS证书,否则访问网站还是之前过期的证书,会提示不安全!

配置详细步骤如下: 进入CND 服务商后台,找到您的二级域名进入管理-HTTPS 配置-更新证书-上传新证书

  • /etc/nginx/ssl目录下的fullchain.pem文件全部内容复制到证书内容,把privkey.pem文件全部内容复制到私钥内容,最后等待部署,访问网站查看证书是否是最新的

以上配置完成重启 Nginx,命令如下:

bash
nginx -s reload
#或
sudo systemctl reload nginx

测试成功(24.10.5)

访问:博客前台

自动续期(指定)

通过 http 验证生成 SSL 证书,适用于指定域名ssl自动续期

教程来源:https://blog.csdn.net/as604049322/article/details/134957466

sh
# 使用 vi 编辑器打开 Nginx 虚拟主机配置文件 proj.conf
vi /usr/local/nginx/conf/vhost/proj.conf

添加 nginx 配置

nginx
# 全局错误页面配置
# 当服务器返回 404 状态码时,将请求重定向到 /404.html 页面
error_page 404 /404.html;
# 当服务器返回 500、502、503、504 这些状态码时,将请求重定向到 /50x.html 页面
error_page 500 502 503 504 /50x.html;

# proj.seasir.top 域名的 HTTP -> HTTPS 重定向
server {
    # 监听 IPv4 的 80 端口,用于接收 HTTP 请求
    listen 80;
    # 监听 IPv6 的 80 端口,用于接收 IPv6 地址的 HTTP 请求
    listen [::]:80;
    # 指定该虚拟主机所处理的域名,这里是 proj.seasir.top
    server_name proj.seasir.top;

    # 配置 HTTP 到 HTTPS 的重定向
    # 当接收到 HTTP 请求时,返回 301 永久重定向状态码,将请求重定向到对应的 HTTPS 地址
    # $host 表示请求的域名,$request_uri 表示请求的 URI 路径
    return 301 https://$host$request_uri;
}

# proj.seasir.top 域名的 HTTPS 反向代理
server {
    # 监听 IPv4 的 443 端口,用于接收 HTTPS 请求,并且启用 SSL 加密
    listen 443 ssl;
    # 监听 IPv6 的 443 端口,用于接收 IPv6 地址的 HTTPS 请求,并且启用 SSL 加密
    listen [::]:443 ssl;
    # 指定该虚拟主机所处理的域名,这里是 proj.seasir.top
    server_name proj.seasir.top;

    # 设置该虚拟主机的根目录,即网站文件所在的目录
    root /root/rsync/rsync-vue/dist;
    # 配置请求的根路径匹配规则
    location / {
        # 当访问根路径时,默认尝试访问的文件列表,按顺序查找,找到第一个存在的文件则返回
        index index.html index.htm;
    }
    # 此处缺少 SSL 证书和私钥的配置,后续需要添加类似如下配置
    # ssl_certificate /etc/letsencrypt/live/proj.seasir.top/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/proj.seasir.top/privkey.pem;
}
  • 重载配置
sh
service nginx reload

# 输出
[root@VM-4-16-centos ~]# service nginx reload
Redirecting to /bin/systemctl reload nginx.service

添加解析记录

  • 去域名解析添加好您的二级域名解析记录,然后通过 http 验证生成证书:
sh
certbot certonly --email seasir666@gmail.com --webroot -w /root/rsync/rsync-vue/dist --preferred-challenges http-01 -d proj.seasir.top
  • 参数说明:

    --email seasir666@gmail.com:这里的 seasir666@gmail.com 是用于接收 Let's Encrypt 证书相关通知(如证书即将到期提醒等)的电子邮件地址,你需要将其替换为你自己有效的电子邮件地址

    -w /root/rsync/rsync-vue/dist:-w 选项后面指定的是 Web 服务器的根目录,Certbot 会在这个目录下创建一个临时文件以完成 ACME(自动证书管理环境)的 HTTP-01 挑战验证。你需要将其替换为你实际网站文件所在的根目录。

    -d proj.seasir.top:-d 指定要申请证书的域名,你可以添加多个 -d 参数来为多个域名申请通配符证书或多域名证书,例如 -d example.com -d www.example.com。你需要将 proj.seasir.top 替换为你自己的域名。

输出:

sh
# 以 root 权限运行 Certbot 命令,用于申请 SSL 证书
# --email seasir666@gmail.com:指定用于接收证书相关通知的电子邮件地址
# --webroot:指定使用 webroot 验证方式,Certbot 会在指定的 Web 根目录下创建临时文件以完成验证
# -w /root/rsync/rsync-vue/dist:指定 Web 根目录,Certbot 会在该目录下创建验证文件
# --preferred-challenges http-01:指定优先使用 HTTP-01 挑战方式进行验证
# -d proj.seasir.top:指定要为其申请证书的域名
[root@VM-4-16-centos ~]# sudo certbot certonly --email seasir666@gmail.com --webroot -w /root/rsync/rsync-vue/dist --preferred-challenges http-01 -d proj.seasir.top

# 提示将调试日志保存到指定文件,方便后续排查问题
Saving debug log to /var/log/letsencrypt/letsencrypt.log

# 显示正在为指定域名申请证书
Requesting a certificate for proj.seasir.top

# 提示成功获取到证书
Successfully received certificate.

# 显示证书文件的保存路径,fullchain.pem 包含了服务器证书和中间证书链
Certificate is saved at: /etc/letsencrypt/live/proj.seasir.top/fullchain.pem

# 显示私钥文件的保存路径,私钥用于加密和解密与客户端的通信
Key is saved at:         /etc/letsencrypt/live/proj.seasir.top/privkey.pem

# 显示证书的过期时间,提醒用户需要在该日期前进行证书更新
This certificate expires on 2025-05-29.

# 提示当证书需要续期时,这些文件会自动更新
These files will be updated when the certificate renews.

# 提示 Certbot 已经设置了定时任务,会在后台自动续期证书,无需用户手动干预
Certbot has set up a scheduled task to automatically renew this certificate in the background.

# 分割线及提示信息,鼓励用户支持 Let's Encrypt 和电子前沿基金会(EFF)的工作
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

然后可以看到 ssl 生成成功的提示Successfully received certificate.

配置 SSL 证书

nginx
# 全局错误页面配置
# 当服务器返回 404 状态码时,将请求重定向到 /404.html 页面
error_page 404 /404.html;
# 当服务器返回 500、502、503、504 这些状态码时,将请求重定向到 /50x.html 页面
error_page 500 502 503 504 /50x.html;

# proj.seasir.top 域名的 HTTP -> HTTPS 重定向
server {
    #此处省略,可以复制上面的
}

# proj.seasir.top 域名的 HTTPS 反向代理
server {
    #此处省略,可以复制上面的

    # 此处缺少 SSL 证书和私钥的配置,后续需要添加类似如下配置
    ssl_certificate /etc/letsencrypt/live/proj.seasir.top/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/proj.seasir.top/privkey.pem;
}

再次重载配置nginx -s reload

sh
nginx -s reload

自动更新证书

sh
#使用以下命令即可更新证书:
certbot renew

#输出:
# 执行 certbot renew 命令,该命令用于检查已有的证书是否需要续期,并在需要时自动进行续期操作
[root@VM-4-16-centos ~]# certbot renew

# 提示将调试日志保存到指定文件,方便后续排查可能出现的问题
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 表示 Certbot 正在处理 proj.seasir.top 域名对应的续期配置文件
# 该配置文件中记录了证书申请时的相关配置信息,如验证方式、域名等
Processing /etc/letsencrypt/renewal/proj.seasir.top.conf
# 分割线,用于区分不同信息块
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# 提示当前检查的 proj.seasir.top 域名的证书还未到需要续期的时间
# Let's Encrypt 证书有效期一般为 90 天,Certbot 通常会在证书有效期还剩 30 天左右时尝试续期
Certificate not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 列出所有尚未到续期时间的证书信息
The following certificates are not due for renewal yet:
  # 具体指出 proj.seasir.top 域名的证书文件 fullchain.pem 未到期
  # 显示该证书的到期时间为 2025-05-29,因此本次检查会跳过该证书的续期操作
  /etc/letsencrypt/live/proj.seasir.top/fullchain.pem expires on 2025-05-29 (skipped)
# 提示由于所有证书都未到续期时间,本次没有尝试进行任何证书的续期操作
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

但有效期超过一个月的会自动跳过。我们将该命令配置为 crontab 定时任务即可实现自动续签

添加定时任务

首先执行crontab -e,然后添加以下配置:

sh
0 0 * * 1 /usr/bin/certbot renew >> /var/log/certbot-renew.log

crontab 从左至右分别是:分钟、小时、日期、月份、星期几,以上配置代表每周一执行一次证书更新。

表示每周一的凌晨 0 点执行任务。/usr/bin/certbot renew:这是要执行的具体命令,即调用 Certbot 工具的 renew 命令来检查并尝试续期证书。>> /var/log/certbot-renew.log:这部分是重定向操作,>> 表示以追加的方式将命令的输出结果写入到指定的日志文件 /var/log/certbot-renew.log 中。

crontab -e/var/spool/cron 目录下

/var/spool/cron 目录下原本有这个命令:_/5 _ * * * flock -xn /tmp/stargate.lock -c '/usr/local/qcloud/stargate/admin/start.sh > /dev/null 2>&1 &'

现在需要添加新的命令:0 0 * * 1 /usr/bin/certbot renew >> /var/log/certbot-renew.log

完整合并如下:

*/5 * * * * flock -xn /tmp/stargate.lock -c '/usr/local/qcloud/stargate/admin/start.sh > /dev/null 2>&1 &'
0 0 * * 1 /usr/bin/certbot renew >> /var/log/certbot-renew.log

完成上述操作后,系统会自动加载新的 crontab 配置,定时任务就会按照设定的时间规则执行。

自动续期(推荐)

通过 dns 通配符去实现自动续期这里推荐 @justjavac 大佬写的:https://github.com/justjavac/certbot-dns-aliyun 参考大佬资料:http://blog.mnxz.fun/index.html?model=articleInfo&id=10

当我们使用 certbot 申请通配符证书时,需要手动添加 TXT 记录。每个 certbot 申请的证书有效期为 3 个月,虽然 certbot 提供了自动续期命令,但是当我们把自动续期命令配置为定时任务时,我们无法手动添加新的 TXT 记录用于 certbot 验证。

好在 certbot 提供了一个 hook,可以编写一个 Shell 脚本。在续期的时候让脚本调用 DNS 服务商的 API 接口动态添加 TXT 记录,验证完成后再删除此记录。

前提条件

  • 你已经有一个域名,并且域名解析托管在阿里云。
  • 服务器上已经安装了 Certbot。
  • 你已经配置了 alidns 脚本,用于自动添加和清理 DNS 记录
  • 拥有阿里云的访问密钥(AccessKey IDAccessKey Secret),用于操作阿里云 DNS 服务。获取阿里云访问密钥(AccessKey ID 和 AccessKey Secret)请参考官方文档:https://help.aliyun.com/zh/acr/create-and-obtain-an-accesskey-pair

环境

  • 系统: centos7
  • 域名: 阿里云购买的域名
  • python
  • nginx 提供反向代理

安装 aliyun cli 工具

sh
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
tar xzvf aliyun-cli-linux-latest-amd64.tgz
sudo cp aliyun /usr/local/bin
rm aliyun
  • 验证 aliyun cli 工具是否成功:

    打开终端,输入 aliyun 命令并回车。如果安装成功,会显示阿里云 CLI 的帮助信息,包含可用的命令和选项

    sh
    aliyun

    示例输出如下:

    详细信息
    sh
    [root@VM-4-16-centos certbot-alicli]# aliyun
    阿里云CLI命令行工具 3.0.255
    
    Usage:
      aliyun <product> <operation> [--parameter1 value1 --parameter2 value2 ...]
    
    Commands:
      configure       配置身份认证和其他信息
      oss             阿里云OSS对象存储
      auto-completion 启用自动完成
    
    Flags:
      --mode               使用 `--mode {AK|StsToken|RamRoleArn|EcsRamRole|RsaKeyPair|RamRoleArnWithRoleName}` 指定认证方式
      --profile,-p         使用 `--profile <profileName>` 指定操作的配置集
      --language           使用 `--language [en|zh]` 来指定语言
      --region             使用 `--region <regionId>` 来指定访问大区
      --config-path        使用 `--config-path` 指定配置文件路径
      --access-key-id      使用 `--access-key-id <AccessKeyId>` 指定AccessKeyId
      --access-key-secret  使用 `--access-key-secret <AccessKeySecret>` 指定AccessKeySecret
      --sts-token          使用 `--sts-token <StsToken>` 指定StsToken
      --sts-region         使用 `--sts-region <StsRegion>` 指定StsRegion
      --ram-role-name      使用 `--ram-role-name <RamRoleName>` 指定RamRoleName
      --ram-role-arn       使用 `--ram-role-arn <RamRoleArn>` 指定RamRoleArn
      --role-session-name  使用 `--role-session-name <RoleSessionName>` 指定RoleSessionName
      --private-key        使用 `--private-key <PrivateKey>` 指定RSA私钥
      --key-pair-name      使用 `--key-pair-name <KeyPairName>` 指定KeyPairName
      --read-timeout       使用 `--read-timeout <seconds>` 指定I/O超时时间(秒)
      --connect-timeout    使用 `--connect-timeout <seconds>` 指定请求连接超时时间(秒)
      --retry-count        使用 `--retry-count <count>` 指定重试次数
      --skip-secure-verify 使用 `--skip-secure-verify` 跳过https的证书校验 [不推荐使用]
      --expired-seconds    使用 `--expired-seconds <seconds>` 指定凭证过期时间
      --process-command    使用 `--process-command <ProcessCommand>` 指定外部程序运行命令
      --oidc-provider-arn  使用 `--oidc-provider-arn <OIDCProviderARN>` 来指定 OIDC 提供者 ARN
      --oidc-token-file    使用 `--oidc-token-file <OIDCTokenFile>` 来指定 OIDC Token 文件路径
      --secure             使用 `--secure` 开关强制使用https方式调用
      --force              添加 `--force` 开关可跳过API与参数的合法性检查
      --endpoint           使用 `--endpoint <endpoint>` 来指定接入点地址
      --version            使用 `--version <YYYY-MM-DD>` 来指定访问的API版本
      --header             使用 `--header X-foo=bar` 来添加特定的HTTP头, 可多次添加
      --body               使用 `--body $(cat foo.json)` 来指定在RESTful调用中的HTTP包体
      --pager              使用 `--pager` 在访问分页的API时合并结果分页
      --output,-o          使用 `--output cols=Field1,Field1 [rows=jmesPath]` 使用表格方式打印输出
      --waiter             使用 `--waiter expr=<jmesPath> to=<value>` 来轮询调用OpenAPI,直到返回期望的值
      --dryrun             使用 `--dryrun` 在执行校验后打印请求包体,跳过实际运行
      --quiet,-q           使用 `--quiet` 关闭正常输出
      --method             使用 `--method {GET|POST}` 来指定 RPC 请求的 Method
      --help               打印帮助信息
    
    Sample:
      aliyun ecs DescribeRegions
    
    Use `aliyun --help` for more information.

配置凭证

  • 安装完成后,你需要对阿里云 CLI 进行配置,使其能够访问你的阿里云账户。可以使用以下命令进行配置:

    sh
    aliyun configure set  --profile AkProfile --mode AK  --access-key-id 替换为你自己的真实 AccessKey ID --access-key-secret 替换为你自己的真实 AccessKey Secret   --region 替换为你希望使用的阿里云地域的 ID

    示例命令

    sh
    aliyun configure set  --profile AkProfile --mode AK  --access-key-id LTAI5txxxxxx --access-key-secret k71Bxxxxxx   --region cn-guangzhou

    按照提示输入你的阿里云访问密钥(AccessKey ID 和 AccessKey Secret)、默认的地域 ID 等信息,配置完成后就可以使用阿里云 CLI 工具来管理你的阿里云资源了。

    如何获取阿里云访问密钥(AccessKey ID 和 AccessKey Secret)请参考官方文档:https://help.aliyun.com/zh/acr/create-and-obtain-an-accesskey-pair

    获取 Region Id 请参考官方文档:https://help.aliyun.com/zh/cli/configure-credentials?spm=a2c4g.11186623.0.i1#41e7063556zzq或者使用 aliyun ecs DescribeRegions 命令获取阿里云 ECS 支持的地域信息

    输出:

    详细信息
    sh
    [root@VM-4-16-centos ~]# aliyun configure
    Configuring profile 'default' in 'AK' authenticate mode...
    Access Key Id []: #输入您的AccessKey ID
    Access Key Secret []: #输入您的AccessKey Secret
    Default Region Id []: cn-guangzhou  #地域id选择离您最近的地区
    Default Output Format [json]: json (Only support json)  #默认输出格式,仅支持json格式!
    Default Language [zh|en] zh: zh  #选择语言,输入zh即可
    Saving profile[default] ...Done.
    
    #以下是配置凭证-交互事配置完整提示信息
    Configure Done!!!
    ..............888888888888888888888 ........=8888888888888888888D=..............
    ...........88888888888888888888888 ..........D8888888888888888888888I...........
    .........,8888888888888ZI: ...........................=Z88D8888888888D..........
    .........+88888888 ..........................................88888888D..........
    .........+88888888 .......Welcome to use Alibaba Cloud.......O8888888D..........
    .........+88888888 ............. ************* ..............O8888888D..........
    .........+88888888 .... Command Line Interface(Reloaded) ....O8888888D..........
    .........+88888888...........................................88888888D..........
    ..........D888888888888DO+. ..........................?ND888888888888D..........
    ...........O8888888888888888888888...........D8888888888888888888888=...........
    ............ .:D8888888888888888888.........78888888888888888888O ..............

验证配置

配置完成后,你可以使用以下命令来验证配置是否生效:

sh
aliyun configure list

输出:

sh
[root@VM-4-16-centos certbot-alicli]# aliyun configure list
Profile     | Credential         | Valid   | Region           | Language
---------   | ------------------ | ------- | ---------------- | --------
default     | AK:***MHb          | Valid   | cn-guangzhou     | zh
AkProfile * | AK:***MHb          | Valid   | cn-guangzhou     | zh

#目前存在两个配置文件,分别是 default 和 AkProfile。其中 AkProfile 后面带有 * 号,这表明当前使用的默认配置文件是 AkProfile。

安装 certbot-dns-aliyun 插件

sh
#下载、部署并配置一个名为 alidns.sh 的脚本
wget https://cdn.jsdelivr.net/gh/justjavac/certbot-dns-aliyun@main/alidns.sh
sudo cp alidns.sh /usr/local/bin
sudo chmod +x /usr/local/bin/alidns.sh
sudo ln -s /usr/local/bin/alidns.sh /usr/local/bin/alidns

如果下载失败手动前往 github 下载:https://github.com/justjavac/certbot-dns-aliyun/blob/main/alidns.sh

申请证书

测试是否能正确申请:

警告

.seasir.top 请换成自己的主域名

sh
certbot certonly -d *.seasir.top --manual --preferred-challenges dns --manual-auth-hook "alidns" --manual-cleanup-hook "alidns clean" --dry-run
sh
#输出
[root@VM-4-16-centos bin]# certbot certonly -d *.seasir.top --manual --preferred-challenges dns --manual-auth-hook "alidns" --manual-cleanup-hook "alidns clean" --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Simulating a certificate request for *.seasir.top
Hook '--manual-auth-hook' for seasir.top ran with output:
 {
        "RecordId": "1895874534617010176",
        "RequestId": "D634D1CA-6CD8-5278-BED9-A1BFDF967B03"
 }
Hook '--manual-cleanup-hook' for seasir.top ran with output:
 {
        "RecordId": "1895874534617010176",
        "RequestId": "E73F9702-88E5-5950-BAD2-751F59432AA1"
 }
The dry run was successful.
#看到"The dry run was successful."模拟成功!

正式申请时去掉 --dry-run 参数:

sh
certbot certonly -d *.seasir.top --manual --preferred-challenges dns --manual-auth-hook "alidns" --manual-cleanup-hook "alidns clean"

参数说明

  • -d example.com:指定域名(可以指定多个域名)。
  • manual:手动模式。
  • preferred-challenges dns:使用 DNS 挑战。
  • manual-auth-hook “alidns”:在 DNS 挑战时调用 alidns 脚本。
  • manual-cleanup-hook “alidns clean”:在 DNS 挑战完成后调用 alidns clean 脚本。
  • —dry-run:模拟续期过程,不会实际续期证书。正式申请时去掉—dry-run 参数:

证书续期

sh
certbot renew --manual --preferred-challenges dns --manual-auth-hook "alidns" --manual-cleanup-hook "alidns clean" --dry-run

如果以上命令没有错误,把 --dry-run 参数去掉。

sh
certbot renew --manual --preferred-challenges dns --manual-auth-hook "alidns" --manual-cleanup-hook "alidns clean"

检查证书状态

运行以下命令查看证书的到期时间:

sh
certbot certificates

自动续期

添加定时任务 crontab。

sh
crontab -e

然后添加以下配置:

sh
1 1 */1 * * root certbot renew --manual --preferred-challenges dns --manual-auth-hook "alidns" --manual-cleanup-hook "alidns clean" --deploy-hook "nginx -s reload"

上面脚本中的 --deploy-hook "nginx -s reload" 表示在续期成功后自动重启 nginx。

常见问题排查

1.没有日志输出,如果 /var/log/certbot-renew.log 没有日志输出,可能是以下原因: 权限问题:确保日志文件可写:

sh
sudo touch /var/log/certbot-renew.log
sudo chmod 644 /var/log/certbot-renew.log

cron 任务未执行:检查 cron 日志:

sh
grep CRON /var/log/syslog

2.证书未到期

如果证书未到期,Certbot 会跳过续期。可以通过以下命令强制续期:

sh
certbot renew --force-renewal --preferred-challenges dns --manual-auth-hook "alidns" --manual-cleanup-hook "alidns clean"

通过 Certbot 和阿里云 DNS 的集成,我们可以轻松实现 SSL 证书的自动续期。只需设置一次 cron 任务,Certbot 就会在证书到期前自动续期,并调用 alidns 脚本处理 DNS 挑战。

声明

作者:Hyde

版权:此文章版权归 Teek 所有,如有转载,请注明出处!

链接:可点击右上角分享此页面复制文章链接

上次更新时间:

最近更新