基于acme.sh的泛域名HTTPS证书自动化管理实践
1. 项目概述自动化泛域名证书管理方案在Web服务运维中HTTPS证书管理一直是个令人头疼的问题。传统单域名证书需要为每个子域名单独申请而手动更新更是运维人员的噩梦。我最近在生产环境成功落地了基于acme.sh的全自动泛域名证书方案配合腾讯云DNS的API实现无人值守的证书签发与更新整套流程从申请到Nginx部署仅需3分钟。这个方案特别适合拥有大量子域名的中大型项目比如SaaS平台、多租户系统等场景。泛域名证书Wildcard Certificate的优势在于可以用一张证书保护主域名及其所有子域名*.example.com。相比单域名证书它不仅简化了管理流程还能显著降低证书采购成本。以腾讯云为例单域名证书年费约200元而泛域名证书仅需800元当子域名超过4个时就已经开始节省开支。2. 核心组件选型解析2.1 为什么选择acme.sh在众多ACME客户端中acme.sh以零依赖、纯Shell编写的特性脱颖而出。实测对比发现Certbot需要Python环境功能复杂LegoGo语言编译但更新策略保守acme.sh安装即用支持80DNS服务商API特别值得一提的是它的证书目录设计所有证书按域名分类存储并自动生成Nginx/Apache等服务的配置片段这在多证书管理时尤为实用。2.2 腾讯云DNS的API优势选择腾讯云DNS主要基于三点考量响应速度国内解析延迟50msAPI稳定性SLA保证99.95%权限控制支持子账号密钥避免使用主账号其他云服务商如阿里云、Cloudflare也提供类似功能但腾讯云的免费额度100万次/月对中小项目完全够用。3. 完整部署流程实录3.1 环境准备与工具安装# 在CentOS 7上的安装示例 yum install -y socat curl curl https://get.acme.sh | sh source ~/.bashrc注意避免使用root用户运行acme.sh脚本会自动创建cron任务处理续期3.2 腾讯云API密钥配置登录腾讯云控制台 - 访问管理 - API密钥管理创建子账号仅赋予DNSPod全读写权限获取SecretId和SecretKeyexport TXY_SecretIdAKIDxxxxxxxx export TXY_SecretKeyxxxxxxxx3.3 证书申请与验证acme.sh --issue --dns dns_tencent \ -d example.com \ -d *.example.com \ --yes-I-know-dns-manual-mode-enough-go-ahead-please关键参数说明--dns dns_tencent指定腾讯云DNS验证-d声明主域名和泛域名末尾参数确认使用DNS验证模式3.4 Nginx证书部署acme.sh生成的证书默认存放在~/.acme.sh/example.com/目录。推荐使用安装命令自动配置acme.sh --install-cert -d example.com \ --key-file /etc/nginx/ssl/example.com.key \ --fullchain-file /etc/nginx/ssl/example.com.crt \ --reloadcmd systemctl reload nginx对应的Nginx配置示例server { listen 443 ssl; server_name app.example.com api.example.com; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; # 启用TLS 1.3 ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256; }4. 高级配置与优化技巧4.1 证书自动更新机制acme.sh默认创建的cron任务如下0 0 * * * /home/user/.acme.sh/acme.sh --cron可以通过以下命令检查任务状态crontab -l | grep acme.sh4.2 多级子域名支持泛域名证书默认只覆盖一级子域名.example.com如需支持多级如.dev.api.example.com需要额外申请acme.sh --issue -d example.com -d *.example.com -d *.dev.api.example.com4.3 证书监控方案建议添加证书过期监控这里给出一个简单的Shell检查脚本#!/bin/bash openssl x509 -enddate -noout -in /etc/nginx/ssl/example.com.crt | cut -d -f25. 常见问题排查指南5.1 DNS验证失败典型错误Verify error:Invalid response from https://acme-v02.api.letsencrypt.org排查步骤检查API密钥是否有DNS写入权限确认域名解析已生效dig TXT _acme-challenge.example.com临时关闭防火墙测试5.2 Nginx配置错误常见症状ERR_SSL_VERSION_OR_CIPHER_MISMATCHSSL_ERROR_RX_RECORD_TOO_LONG解决方案确保证书链完整使用fullchain文件检查私钥是否匹配openssl x509 -noout -modulus重启Nginx前测试配置nginx -t5.3 续期失败处理当自动续期失败时可以手动触发acme.sh --renew -d example.com --force如果多次失败建议清理旧证书重新申请acme.sh --remove -d example.com rm -rf ~/.acme.sh/example.com6. 安全加固建议私钥保护chmod 400 /etc/nginx/ssl/example.com.key chown root:root /etc/nginx/ssl/*证书透明度日志监控订阅certspotter监控定期检查证书签发记录HSTS增强add_header Strict-Transport-Security max-age63072000; includeSubDomains; preload;这套方案在我负责的电商平台上已稳定运行18个月管理着超过50个子域名的证书。最大的收获是再也不用担心凌晨三点被证书过期告警吵醒了。对于需要管理多个子域名的团队建议将acme.sh的安装和配置过程编写成Ansible剧本可以实现新服务器的一键部署。