HTTPS 证书申请与自动续期:acme.sh + Let‘s Encrypt 完整记录

HTTPS 证书申请与自动续期:acme.sh + Let's Encrypt 完整记录

证书过期这事的惩罚机制很公平:你忘了续,全站用户帮你发现。

我的博客和几个小服务全跑在自己服务器上,最早用宝塔点按钮签证书,有一次续期失败没发现,站上挂着"不安全"红标整整两天。后来全部换成 acme.sh 全自动签发续期,两年多零事故。这篇是完整复刻:从装 acme.sh 到签发、部署、自动续期、常见报错,一条链讲完。

一、方案选型:为什么是 acme.sh

免费证书就两个主流来源:Let's Encrypt 和 ZeroSSL(acme.sh 默认会在这两者间自动选择)。签发工具我对比过三个:

工具 优点 缺点
certbot 官方出品、文档多 Python 依赖重,自动续期要配 systemd timer
acme.sh 纯 shell、零依赖、DNS API 支持最全 文档偏散
宝塔/面板 点按钮 黑盒,续期失败不通知,出问题难排查

选 acme.sh 的核心理由:支持几十家 DNS 服务商的 API 自动验证 ,这意味着通配符证书(*.example.com)和内网机器都能签,而且续期完全无人值守。

二、安装与签发:两条路

安装就一行:

bash 复制代码
curl https://get.acme.sh | sh -s email=my@example.com
source ~/.bashrc
acme.sh --version

路线 A:HTTP 验证(适合单机、能开 80 端口)

前提:域名已解析到这台服务器,80 端口可访问。

bash 复制代码
acme.sh --issue -d example.com -d www.example.com \
  --webroot /var/www/html

如果你用 nginx 且懒得配 webroot,用 standalone 模式(会临时占用 80 端口,签完自动释放):

bash 复制代码
systemctl stop nginx        # 或者用 --nginx 模式免停
acme.sh --issue -d example.com --standalone
systemctl start nginx

路线 B:DNS API 验证(推荐,能签通配符)

以 DNSPod(腾讯云)为例,先在控制台创建 API 密钥,然后:

bash 复制代码
export DP_Id="123456"
export DP_Key="xxxxxxxx"
acme.sh --issue --dns dns_dp -d example.com -d "*.example.com"

acme.sh 会自动添加 TXT 记录、等传播、验证、删记录,全程无感。密钥会被保存在 ~/.acme.sh/account.conf,续期时自动复用------这就是"自动"的根基。阿里云是 --dns dns_ali(需要 AccessKey),Cloudflare 是 --dns dns_cf(用 Global API Key 或 Token)。

安全提醒:用于签证书的 API Key 权限只给 DNS 编辑就够了,别用账号主密钥。Key 泄露等于域名解析权泄露。

三、部署到 Nginx:不要直接用 ~/.acme.sh 里的文件

acme.sh 生成的证书在 ~/.acme.sh/example.com_ecc/ 下,但官方明确说这个目录是内部工作目录,结构可能变。正确姿势是用 --install-cert 让它把证书拷贝 到你的稳定路径,并且续期后自动 reload nginx:

bash 复制代码
mkdir -p /etc/nginx/certs/example.com

acme.sh --install-cert -d example.com --ecc \
  --key-file       /etc/nginx/certs/example.com/key.pem \
  --fullchain-file /etc/nginx/certs/example.com/fullchain.pem \
  --reloadcmd      "nginx -s reload"

--reloadcmd 是整个自动化的点睛之笔:证书续期成功后自动执行。没有它,续期再成功 nginx 还在用内存里的旧证书,一样全站报错。

nginx 站点配置(关键部分):

nginx 复制代码
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/certs/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/example.com/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # 80 跳 443 由另一个 server 块处理
}

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

四、自动续期:装完就忘,但要会检查

acme.sh 安装时已经自动写入了 cron(crontab -l 能看到一行 acme.sh --cron)。它每次运行会检查证书剩余有效期,不足 30 天才真正续期,续期成功后执行你的 --reloadcmd。

装完做一次"续期演练",确认整条链路真的通:

bash 复制代码
acme.sh --renew -d example.com --ecc --force   # 强制立即续期一次
acme.sh --list                                  # 看证书状态和剩余天数

如果 --list 里 Le_NextRenewTime 正常往后推、nginx reload 没报错,这条链路就是通的。建议在日历上放一个 60 天一次的提醒 ,跑一次 acme.sh --list,让"自动"也有一道人工保险。

五、报错速查:我踩过的和群友问爆的

现象 原因与解法
Timeout during connect (HTTP 验证) 80 端口没开放/被防火墙挡。云服务器安全组放行 80;国内服务器 80/443 需备案,没备案用 DNS 验证绕开
DNS 验证一直 pending TXT 记录传播慢,多等 2~5 分钟;用 dig TXT _acme-challenge.example.com 确认记录已生效
dns_dp: API error DP_Id/DP_Key 错了,或者密钥是账号密码不是 API 密钥
浏览器报证书链不全 用的是 cert.pem 而不是 fullchain.pem,换成全链文件
续期成功但网站还是旧证书 忘了 --reloadcmd 或 reload 没执行成功,acme.sh --renew -d xx --force 后看日志
频率限制 too many certificates Let's Encrypt 对同域名每周 5 张,测试加 --test(测试环境务必用 staging,别耗真额度)

查看详细日志永远是第一步:

bash 复制代码
tail -50 ~/.acme.sh/acme.sh.log

六、进阶:多机部署与内网机器

证书签在一台机器上,其他机器怎么用?两个思路:

  1. 集中部署 :主机器续期后,--reloadcmd 里用 scp/rsync 把证书推给其他机器并触发对端 reload(需要对端配置免密登录)。适合 2~5 台的规模。
  2. 每台自己签:DNS 验证方式下每台机器都能独立走完整流程,互不依赖,规模大了之后反而更稳。

内网机器(无公网 80)只能走 DNS 验证,这也是我推荐 DNS API 路线的根本原因------它对网络环境零要求。

七、总结

HTTPS 的配置成本其实一次性只有 15 分钟:装 acme.sh → DNS API 签发(可带通配符)→ --install-cert 部署 + 自动 reload → 演练一次续期。做完之后这件事就从你的运维清单里消失了,剩下的只是每两个月扫一眼 acme.sh --list。今晚就可以把那个还挂着"不安全"的站处理掉,顺便把 80 端口 301 到 443,一步到位。

相关推荐
zxanz13 小时前
网站为什么需要 SSL 证书来实现 https?
https
Lsetea8 小时前
curl报58 unable to set private key file:客户端证书与私钥加载排查
运维·https·ssl证书·openssl·curl
Lsetea9 小时前
OpenSSL报certificate is not yet valid:error 9与notBefore时间排查
linux·运维·https·ssl证书·openssl
2501_915909069 小时前
iOS应用从开发到上架App Store的完整发布流程与步骤指南
android·ios·小程序·https·uni-app·webview
Joy T11 小时前
从 Nginx 到 Gateway 再到微服务:一次 AI 请求的完整链路
nginx·微服务·gateway·controller·路由转发·ai service·接口错误排查
Smoothcloud润云11 小时前
GPU服务器租用实例DNS与HTTPS下载排障实战
大数据·运维·服务器·人工智能·https·gpu算力
小匠石钧知11 小时前
07_在k8s集群中安装ingress-nginx
nginx·容器·kubernetes·ingress
神一样的老师14 小时前
WS63 访问 HTTPS 握手失败(-0x7780)根治
数据库·网络协议·https
百度一下吧1 天前
Nginx 使用手册:从安装配置到实战部署
运维·nginx
JAVA面经实录9171 天前
Java高级后端 · 全套面试通关手册(Nginx)
java·nginx·面试