使用 acme.sh 自动续期 SSL 证书


腾讯云免费 SSL 证书有效期较短。手动续期、下载并替换证书很容易遗漏,因此将博客切换为 Let’s Encrypt + acme.sh 自动续期。

本文的环境如下:

  • 腾讯云轻量应用服务器
  • OpenCloudOS
  • Nginx
  • Hexo 静态博客目录:/var/www/hexo
  • 域名:caiguu.cn

开始前,请确认域名的 A 记录已经解析到服务器;若配置了 AAAA 记录,也要确保 IPv6 的 80 和 443 端口可从公网访问。

为 ACME 验证保留 HTTP 路径

博客通常会将所有 HTTP 请求跳转到 HTTPS:

1
return 301 https://$server_name$request_uri;

但 ACME 的 HTTP 验证需要通过 /.well-known/acme-challenge/ 读取验证文件。不能将这条 return 直接写在 server 作用域中,否则它会先于 location 执行,导致验证请求也被跳转到 HTTPS。

编辑 /etc/nginx/conf.d/hexo.conf,让 80 端口的虚拟主机结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80;
listen [::]:80;
server_name caiguu.cn;
charset utf-8;

location ^~ /.well-known/acme-challenge/ {
root /var/www/acme;
default_type text/plain;
try_files $uri =404;
}

location / {
return 301 https://$host$request_uri;
}
}

创建验证目录并重载 Nginx:

1
2
mkdir -p /var/www/acme/.well-known/acme-challenge
nginx -t && systemctl reload nginx

可以先写入一个测试文件:

1
2
printf 'acme-ok\n' > /var/www/acme/.well-known/acme-challenge/test
curl -4 -i http://caiguu.cn/.well-known/acme-challenge/test

返回 HTTP/1.1 200 OKacme-ok,说明验证路径已经生效。

安装 acme.sh

使用 root 用户安装,并填写真实邮箱:

1
curl https://get.acme.sh | sh -s email=你的邮箱@example.com

指定默认 CA 为 Let’s Encrypt:

1
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

申请证书

使用 Webroot 模式申请 RSA 证书:

1
2
3
4
~/.acme.sh/acme.sh --issue \
-d caiguu.cn \
-w /var/www/acme \
--keylength 2048

如果还需要支持 www.caiguu.cn,应先添加对应 DNS 记录,再一并申请:

1
2
3
4
5
~/.acme.sh/acme.sh --issue \
-d caiguu.cn \
-d www.caiguu.cn \
-w /var/www/acme \
--keylength 2048

部署到 Nginx 并自动重载

原有 Nginx 配置使用以下证书路径:

1
2
ssl_certificate     /etc/cert/caiguu.cn_bundle.crt;
ssl_certificate_key /etc/cert/caiguu.cn.key;

因此让 acme.sh 在每次成功续期后更新相同的文件,并重载 Nginx:

1
2
3
4
~/.acme.sh/acme.sh --install-cert -d caiguu.cn \
--key-file /etc/cert/caiguu.cn.key \
--fullchain-file /etc/cert/caiguu.cn_bundle.crt \
--reloadcmd "systemctl reload nginx"

证书续期后,acme.sh 会自动写入新证书并执行 Nginx 重载,不需要再去腾讯云控制台手动申请和替换。

查看下次续期时间

查看证书的创建时间、下次续期时间和部署参数:

1
~/.acme.sh/acme.sh --info -d caiguu.cn

重点关注:

1
2
3
4
Le_CertCreateTimeStr=...
Le_NextRenewTimeStr=...
Le_ReloadCmd=systemctl reload nginx
Le_Webroot=/var/www/acme

查看当前 Nginx 实际使用的证书有效期:

1
2
openssl x509 -in /etc/cert/caiguu.cn_bundle.crt \
-noout -subject -issuer -dates

确认定时任务

acme.sh 安装时会创建定时任务。检查 cron 配置:

1
crontab -l | grep -F '.acme.sh/acme.sh --cron'

确认 cron 服务已启动并设置为开机自启:

1
2
systemctl is-enabled crond
systemctl is-active crond

也可以手动运行一次日常检查:

1
/root/.acme.sh/acme.sh --cron --home /root/.acme.sh

不要随意添加 --force。正常情况下,未到续期时间时 acme.sh 会跳过本次更新;到期前会自动申请新证书并重载 Nginx。

IPv6 验证失败的排查

如果申请时出现类似错误:

1
2
Fetching https://caiguu.cn/.well-known/acme-challenge/...:
Timeout during connect

通常表示域名的 AAAA 记录可解析,但 IPv6 的 HTTPS 连通性尚未正常。一个常见场景是 HTTP 请求被跳转到 HTTPS,随后 CA 通过 IPv6 访问 443 端口时超时。

为 ACME 验证路径保留 HTTP 例外可以避免这次跳转;不过 IPv6 的地址、路由、防火墙与 443 端口仍应尽快修复,否则 IPv6 用户仍可能无法正常访问博客。

Chrome 仍显示“不安全”

若其他浏览器和 Chrome 无痕窗口均可正常访问 HTTPS,而只有 Chrome 普通窗口显示异常,通常是本地缓存、旧的 301 跳转、站点数据或 Service Worker 导致。

可依次尝试:

  • 使用 Cmd + Shift + R 强制刷新;
  • 删除 caiguu.cn 的站点数据;
  • 重启 Chrome;
  • 确认访问地址是 https://caiguu.cn,而不是 HTTP、www 子域名或服务器 IP。

总结

证书有效期短并不可怕。通过 acme.sh 自动申请、自动续期,并在成功后自动重载 Nginx,博客证书维护就从周期性手工操作变成了一次配置、长期运行的后台任务。


文章作者: Jack Zhang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Jack Zhang !
  目录