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,一步到位。

相关推荐
Lsetea9 小时前
部署证书后提示“证书名称与输入不匹配”:Safari 报错的三层排查
nginx·https·safari·ssl证书·openssl
打工仔折腾 AI1 天前
FastAPI 从本机到生产服务器:Nginx+Gunicorn+Uvicorn 完整部署实录
人工智能·后端·python·nginx·fastapi·gunicorn
Linux运维技术栈1 天前
如何避免绕过CDN的攻击?基于 CDN 回源请求头鉴权的防御实操与安全性剖析
nginx·安全·cdn
其实防守也摸鱼1 天前
DeepSeek Harness 开源贡献手记:从入门到合入主线
服务器·数据库·windows·https·ssl
Lsetea1 天前
OpenSSL快速生成域名证书:含SAN的自签命令、验证与排错
nginx·https·ssl证书·openssl·自签证书
2501_916008891 天前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp
其实防守也摸鱼1 天前
堆叠注入(Stacked Injection)详解
服务器·数据库·windows·https·ssl
小小的木头人2 天前
CentOS 7 下 Nginx 访问自定义目录报 403 的完整排查:从端口权限到 SELinux
nginx·centos
新时代农民工~2 天前
【双机高可用部署方案-前后端部署】
java·nginx·springboot