使用acme.sh获取免费泛域名SSL证书:从DNS验证到自动化部署
1. 项目概述:为什么我们需要免费的泛域名SSL证书?
如果你自己折腾过网站、API服务或者家庭内网应用,肯定对那个“不安全”的浏览器警告深恶痛绝。几年前,一张SSL证书(现在更准确地叫TLS证书)动辄几百上千,还得每年续费,对个人开发者和小项目来说是个不小的负担。后来Let's Encrypt横空出世,提供了免费的DV(域名验证)证书,彻底改变了游戏规则。但它的标准证书只针对单个域名或有限的子域名列表,对于我这种喜欢用*.home.lab、*.api.myproject.com这种模式来管理一堆子域名的人来说,每次新增一个服务都得重新申请证书,实在太麻烦了。
这时候,泛域名证书(Wildcard Certificate)的价值就凸显出来了。一张*.example.com的证书,可以保护blog.example.com、api.example.com、dev.example.com等无限个子域名,管理起来极其方便。虽然Let's Encrypt和ZeroSSL等机构都提供免费的泛域名证书,但申请过程,特别是域名验证环节,对于新手来说可能有点绕。手动操作不仅繁琐,更关键的是无法实现自动化续期,证书90天过期后网站就得“裸奔”。
这就是acme.sh这个工具的价值所在。它本质上是一个用Shell脚本写的ACME协议客户端。ACME协议是像Let's Encrypt这类证书颁发机构(CA)用来自动化验证域名所有权和颁发证书的标准。acme.sh把这个协议封装成简单的命令行工具,让我们可以通过多种方式(HTTP文件验证、DNS的API验证、手动DNS验证等)来完成域名验证,并自动获取、安装乃至续期证书。它的口号是“一个纯Unix shell脚本,从Let‘s Encrypt或ZeroSSL获取SSL证书”,其设计哲学就是简单、强大、无依赖。
我最近在重构自己的家庭服务器架构,所有服务都打算通过子域名来访问,比如nas.home.lab、git.home.lab、portainer.home.lab等等。手动为每一个去申请证书是不可想象的,所以通过acme.sh自动化获取一张泛域名证书就成了必选项。整个流程走下来,虽然中间踩了几个坑,但最终实现了一次配置、自动续期的目标。这篇日记就详细记录下我的操作思路、具体步骤、遇到的坑以及解决方案,希望能帮你省下一些摸索的时间。
2. 核心思路与方案选型:为什么选择DNS验证模式?
使用acme.sh获取证书,第一步也是最重要的一步,就是选择域名验证方式。这决定了你后续操作的复杂度和自动化程度。acme.sh支持多种方式,我们需要根据自身环境做出最合适的选择。
2.1 三种主流验证方式深度解析
HTTP-01验证:这是最常见的方式。CA机构会向你的域名发起一个HTTP请求,访问一个特定的URL(例如http://example.com/.well-known/acme-challenge/某个随机令牌)。acme.sh会在你的Web服务器根目录下自动生成这个包含令牌的文件。如果你的服务器80端口可被公开访问,并且acme.sh有权限在网站目录写文件,这是最省心的方式。它支持全自动续期。但是,对于泛域名证书,Let's Encrypt有一个关键限制:HTTP-01验证方式不能用于颁发泛域名证书。它只能验证具体的、可访问的域名。所以,如果你的目标是*.example.com,这条路从一开始就走不通。
DNS-01验证:这是获取泛域名证书的唯一标准方式。原理是CA机构要求你在域名的DNS解析设置中,添加一条特定的TXT记录。acme.sh会生成一个随机字符串作为记录值,你将其添加到DNS管理后台。CA通过查询DNS来验证你是否拥有该域名的控制权。这种方式的最大优势是它不依赖于你的Web服务器是否在线、80/443端口是否开放,它只验证DNS记录。因此,它天然支持泛域名验证,因为你只需要在根域名(如example.com)下添加记录,就能证明你拥有所有*.example.com子域名的控制权。
TLS-ALPN-01验证:这种方式利用TLS握手过程中的ALPN扩展来验证,通常用于验证443端口。它比HTTP-01更复杂,适用场景也更特殊(比如前端有复杂的负载均衡器时),对于大多数个人用户和小型项目来说,很少用到。它同样不支持泛域名证书。
所以,结论很明确:要获取免费的泛域名SSL证书,必须使用DNS-01验证方式。
2.2 DNS验证的两种实现路径:自动与手动
确定了DNS-01验证,接下来又要面临选择:是使用自动模式还是手动模式?
自动DNS模式:这是理想状态。acme.sh支持超过100种DNS服务商的API,包括Cloudflare、阿里云、腾讯云DNSPod、GoDaddy等主流厂商。你只需要在域名服务商那里获取API Token或密钥,并将其以环境变量的形式提供给acme.sh。之后,整个验证过程完全自动化:acme.sh自动调用API创建TXT记录,等待CA验证,验证成功后自动删除该记录。续期过程也完全无需人工干预,是实现“一次配置,永久自动续期”的关键。
手动DNS模式:如果你的域名服务商不在acme.sh的支持列表内(比如一些国内较小的注册商),或者你不愿意/无法获取API密钥(出于安全或权限考虑),那么就需要使用手动模式。流程是:运行acme.sh命令,它会输出需要添加的TXT记录名称和值;你手动登录DNS管理后台,添加这条记录;等待DNS全球生效(通常几分钟到几小时);最后再运行一条命令,告诉acme.sh去检查验证。证书续期时,你需要重复这个过程。
我的选择与考量:我使用的域名服务商是Cloudflare,它正在acme.sh的完美支持列表中。按道理我应该毫不犹豫选择自动模式。但我最终在测试环境先选择了手动模式,原因有三点:第一,我想彻底搞清楚整个DNS验证的底层流程和原理,手动走一遍是最好的学习方式;第二,对于生产环境,在完全信任自动化流程之前,手动验证一次能确保所有环节都在掌控之中;第三,有些极端环境下(比如某些内网隔离环境),可能只能使用手动模式。因此,下面的实操记录我会以手动DNS模式作为主线,因为它最具普适性,理解了手动模式,自动模式只是简化了中间步骤。在最后,我会补充如何切换到Cloudflare API自动模式。
注意:无论选择哪种模式,核心的安全前提是:你必须拥有该域名的管理权,能够添加或修改其DNS记录。这是CA机构验证你对域名拥有控制权的唯一依据。
3. 环境准备与acme.sh安装详解
在开始操作之前,我们需要一个Linux环境。我使用的是Ubuntu 22.04 LTS的云服务器,但acme.sh几乎兼容所有带有Shell的环境(包括macOS和Windows的WSL)。以下步骤具有通用性。
3.1 基础环境检查
首先,确保你的系统有curl和cron(或systemd timer)服务。curl用于下载安装脚本,cron是acme.sh用来设置自动续期任务的工具。
# 检查curl是否安装 which curl # 如果未安装,在基于Debian/Ubuntu的系统上安装 sudo apt update && sudo apt install curl -y # 检查cron服务是否运行 systemctl status cron # 如果未运行,启动并设置开机自启 sudo systemctl start cron sudo systemctl enable cron3.2 安装acme.sh
安装过程非常简单,官方推荐使用一键安装脚本。这里有一个非常重要的细节:安装命令中-s email=my@example.com参数的作用。这个邮箱地址会被注册到ACME CA(默认是ZeroSSL)的账户中。它主要有两个用途:一是作为证书关联的联系人,在证书即将过期时会收到提醒邮件(如果你用了自动续期,这个提醒可能用不上);二是在某些CA(如Let‘s Encrypt)那里,它作为账户标识。如果你不提供,acme.sh会为你生成一个随机邮箱。
# 执行一键安装脚本,请将 my@example.com 替换为你自己的邮箱 curl https://get.acme.sh | sh -s email=my@example.com这条命令做了以下几件事:
- 从GitHub下载
acme.sh的安装脚本并执行。 - 将
acme.sh安装到当前用户的~/.acme.sh/目录下。所有操作都会限制在这个目录内,不会污染系统目录。 - 为当前用户创建一个别名(alias):
alias acme.sh=~/.acme.sh/acme.sh。这样你可以在任何位置直接输入acme.sh来调用程序。 - 自动为你创建一个每日运行的cronjob(计划任务),用于检查并自动续期即将过期的证书。
安装完成后,必须重新加载Shell配置,让新创建的别名生效。
# 如果你使用的是bash source ~/.bashrc # 如果你使用的是zsh source ~/.zshrc现在,验证安装是否成功:
acme.sh --version你应该能看到类似https://github.com/acmesh-official/acme.sh v3.1.0的输出,表明安装正确。
3.3 关于默认CA的说明
从acme.shv3.0.0开始,默认的证书颁发机构(CA)从Let‘s Encrypt切换到了ZeroSSL。这是一个重要的变化。ZeroSSL同样提供免费的90天DV证书(包括泛域名证书),并且有自己的用户界面和API。对于大多数用途来说,从Let‘s Encrypt切换到ZeroSSL没有功能上的区别。但如果你有特殊需求,比如某些旧设备只信任特定根证书,或者你习惯了Let‘s Encrypt,可以随时切换回来:
# 切换默认CA为Let‘s Encrypt acme.sh --set-default-ca --server letsencrypt # 切换回ZeroSSL acme.sh --set-default-ca --server zerossl在接下来的手动DNS验证示例中,我们将使用默认的ZeroSSL。
4. 手动DNS模式申请泛域名证书全流程
假设我的域名是myawesome.domain,我想要一张能覆盖*.myawesome.domain的泛域名证书。请注意,申请泛域名证书时,通常建议同时申请根域名的证书(即myawesome.domain),因为有些场景下,直接访问根域名和访问www.myawesome.domain是常见需求。
4.1 第一步:发起证书申请命令
我们使用acme.sh的--issue命令,并指定--dns参数表示使用DNS验证。由于是手动模式,需要加上那个长长的--yes-I-know-dns-manual-mode-enough-go-ahead-please参数,这相当于一个“确认开关”,告诉脚本你知道这是手动模式并愿意自己操作。
acme.sh --issue --dns \ -d myawesome.domain \ -d *.myawesome.domain \ --yes-I-know-dns-manual-mode-enough-go-ahead-please命令参数拆解:
--issue:核心命令,表示申请新证书。--dns:指定使用DNS-01验证方式。-d:指定域名。这里有两个-d参数,第一个是根域名,第二个是泛域名。这是必须的,如果你只指定*.myawesome.domain,那么CA颁发的证书只包含泛域名条目,不包含根域名。有些浏览器或客户端在访问myawesome.domain时可能会报证书不匹配的错误。- 那个长参数:就是字面意思,确认进入手动模式。
执行命令后,你会看到类似下面的输出(具体内容会变化):
[Sat Apr 15 10:30:00 CST 2025] Using CA: https://acme.zerossl.com/v2/DV90 [Sat Apr 15 10:30:00 CST 2025] Creating domain key [Sat Apr 15 10:30:01 CST 2025] The domain key is here: /home/user/.acme.sh/myawesome.domain/myawesome.domain.key [Sat Apr 15 10:30:01 CST 2025] Single domain='myawesome.domain' [Sat Apr 15 10:30:01 CST 2025] Getting domain auth token for each domain [Sat Apr 15 10:30:02 CST 2025] Getting webroot for domain='myawesome.domain' [Sat Apr 15 10:30:02 CST 2025] Add the following TXT record: [Sat Apr 15 10:30:02 CST 2025] Domain: '_acme-challenge.myawesome.domain' [Sat Apr 15 10:30:02 CST 2025] TXT value: 'kjHsd8f7D_aSdF9gHjKlOpQyTzXcVaBnmLoPqWeR' [Sat Apr 15 10:30:02 CST 2025] Please make sure to prepend '_acme-challenge.' to your domain [Sat Apr 15 10:30:02 CST 2025] so that the resulting subdomain is: _acme-challenge.myawesome.domain [Sat Apr 15 10:30:02 CST 2025] Please add the TXT records to the domains, and re-run with --renew. [Sat Apr 15 10:30:02 CST 2025] Please add '--debug' or '--log' to see more information.关键信息提取:
- CA机构:
Using CA: https://acme.zerossl.com/v2/DV90,表明正在使用ZeroSSL。 - 需要添加的DNS记录:
- 域名(Name/Host):
_acme-challenge.myawesome.domain - 类型(Type):
TXT - 值(Value):
kjHsd8f7D_aSdF9gHjKlOpQyTzXcVaBnmLoPqWeR(这是一串随机生成的字符串)
- 域名(Name/Host):
重要原理:为什么是
_acme-challenge?这是ACME协议规定的标准子域名前缀,CA机构会通过查询_acme-challenge.your-domain.com的TXT记录值,来验证你是否拥有该域名的DNS控制权。TXT记录可以存储任意文本信息,非常适合用于这种挑战应答式的验证。
4.2 第二步:在DNS服务商处添加TXT记录
现在,你需要登录你的域名注册商或DNS托管服务商(如Cloudflare, GoDaddy, Namecheap,阿里云万网,腾讯云DNSPod等)的管理后台。
- 找到DNS记录管理页面。
- 添加一条新的记录。
- 记录类型选择TXT。
- 主机/名称(Host/Name)填写:
_acme-challenge。这里有个巨大坑点:不同的DNS服务商对这个字段的理解不同!- 情况A(大多数国际服务商如Cloudflare, GoDaddy):你只需要填写
_acme-challenge。系统会自动为你补全域名,最终记录就是_acme-challenge.myawesome.domain。 - 情况B(很多国内服务商如阿里云):你需要填写完整的
_acme-challenge.myawesome.domain。 - 如何判断?最稳妥的方法是,看后台已有的其他记录。如果有一条A记录主机名是
@或空,代表根域名,那么这里就填_acme-challenge。如果有一条A记录主机名是www,代表www.myawesome.domain,那么这里也填_acme-challenge。如果不确定,先按_acme-challenge填写,保存后看记录列表里显示的是什么。如果显示的是_acme-challenge.myawesome.domain,那就对了;如果显示的是_acme-challenge.myawesome.domain.myawesome.domain(重复了两次域名),那就说明应该填完整的_acme-challenge.myawesome.domain。
- 情况A(大多数国际服务商如Cloudflare, GoDaddy):你只需要填写
- 值(Value/Content)填写:
acme.sh输出的那长串随机字符串,例如kjHsd8f7D_aSdF9gHjKlOpQyTzXcVaBnmLoPqWeR。 - TTL(生存时间)保持默认或设置为较低的值(如300秒),以便快速生效。保存记录。
4.3 第三步:等待DNS记录生效并验证
添加记录后,DNS变更需要时间传播到全球。这个过程短则几十秒,长则几小时。我们可以用dig或nslookup命令来检查记录是否生效。
# 使用dig命令查询(如果系统未安装,请先安装`dnsutils`或`bind-utils`) dig -t txt _acme-challenge.myawesome.domain # 或者使用nslookup nslookup -type=txt _acme-challenge.myawesome.domain当查询结果中包含了我们设置的TXT值时,说明记录已生效。务必确保生效后再进行下一步,否则验证会失败。
4.4 第四步:执行验证并获取证书
DNS记录生效后,回到终端,运行--renew命令来完成验证和证书颁发。注意,这里用的不是--issue,而是--renew,并且要带上和之前一样的域名列表以及那个长的手动模式确认参数。
acme.sh --renew \ -d myawesome.domain \ -d *.myawesome.domain \ --yes-I-know-dns-manual-mode-enough-go-ahead-please如果一切顺利,你会看到Success和Cert success.的输出,并告诉你证书和密钥文件存放的位置:
[Sat Apr 15 10:45:00 CST 2025] Verifying: myawesome.domain [Sat Apr 15 10:45:05 CST 2025] Processing. The CA is processing your order, please wait. (1/30) [Sat Apr 15 10:45:10 CST 2025] Success [Sat Apr 15 10:45:10 CST 2025] Verification finished, beginning signing. ... [Sat Apr 15 10:45:15 CST 2025] Cert success. [Sat Apr 15 10:45:15 CST 2025] Your cert is in: /home/user/.acme.sh/myawesome.domain_ecc/myawesome.domain.cer [Sat Apr 15 10:45:15 CST 2025] Your cert key is in: /home/user/.acme.sh/myawesome.domain_ecc/myawesome.domain.key [Sat Apr 15 10:45:15 CST 2025] The intermediate CA cert is in: /home/user/.acme.sh/myawesome.domain_ecc/ca.cer [Sat Apr 15 10:45:15 CST 2025] And the full-chain cert is in: /home/user/.acme.sh/myawesome.domain_ecc/fullchain.cer恭喜!证书已经申请成功。文件存放在~/.acme.sh/目录下以你的域名命名的文件夹中(_ecc后缀表示使用的是ECC椭圆曲线加密密钥,这是默认且更推荐的方式)。
4.5 第五步:安装证书到Web服务器
acme.sh不建议你直接从它的工作目录复制证书文件,因为它内部需要这些文件来管理续期。它提供了--install-cert命令来安全地“安装”证书。
假设我使用Nginx,希望将证书安装到/etc/nginx/ssl/myawesome.domain/目录下。
# 首先创建目标目录(如果不存在) sudo mkdir -p /etc/nginx/ssl/myawesome.domain # 使用acme.sh安装证书 acme.sh --install-cert -d myawesome.domain \ --key-file /etc/nginx/ssl/myawesome.domain/key.pem \ --fullchain-file /etc/nginx/ssl/myawesome.domain/cert.pem \ --reloadcmd "sudo systemctl reload nginx"参数解释:
--key-file:指定私钥文件的安装路径。--fullchain-file:指定完整证书链文件的安装路径。这个文件包含了你的站点证书和中间CA证书,是Nginx等服务器ssl_certificate指令需要的文件。--reloadcmd:这是一个非常实用的参数。它指定一个命令,在证书自动续期成功后自动执行。这里我们设置为重载Nginx配置,这样续期后服务能无缝使用新证书,实现真正的零停机续期。
执行这个命令后,acme.sh会将证书和密钥复制到指定路径,并记录这个安装位置。未来自动续期时,新证书会直接覆盖这些文件,并执行--reloadcmd命令。
最后,配置你的Nginx虚拟主机,指向这些证书文件:
server { listen 443 ssl http2; server_name myawesome.domain www.myawesome.domain api.myawesome.domain; ssl_certificate /etc/nginx/ssl/myawesome.domain/cert.pem; ssl_certificate_key /etc/nginx/ssl/myawesome.domain/key.pem; # 其他SSL优化配置... ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:...; ssl_prefer_server_ciphers off; location / { # 你的应用配置 } } server { listen 80; server_name myawesome.domain www.myawesome.domain api.myawesome.domain; return 301 https://$server_name$request_uri; }配置完成后,执行sudo nginx -t测试配置无误,然后sudo systemctl reload nginx重载服务。现在,用浏览器访问https://myawesome.domain,你应该能看到安全的锁标志了。
5. 进阶:配置自动化DNS API验证(以Cloudflare为例)
手动模式虽然通用,但每次续期都要手动操作,违背了我们自动化的初衷。如果你的DNS服务商支持API,强烈建议切换到自动模式。这里以Cloudflare为例。
5.1 获取Cloudflare API Token
- 登录Cloudflare控制台,进入你的域名概览页。
- 点击右下角的“获取您的API令牌”。
- 点击“创建令牌”。
- 选择“编辑区域 DNS”模板。这个模板权限足够,且范围可控。
- 在“区域资源”部分,选择“包括” -> “特定区域” -> 选择你的域名(如
myawesome.domain)。 - 点击“继续以显示摘要”,然后“创建令牌”。
- 非常重要:复制生成的API令牌(一串长字符)。它只显示一次,请妥善保存。
5.2 配置acme.sh使用Cloudflare API
将API令牌设置为环境变量。有几种方式,最安全的是将其添加到你的用户profile文件(如~/.bashrc或~/.zshrc)中,然后source它。
# 编辑 ~/.bashrc nano ~/.bashrc # 在文件末尾添加 export CF_Token="你的API令牌" export CF_Account_ID="你的Cloudflare账户ID(在域名概览页右侧可以找到)" export CF_Zone_ID="你的区域ID(在域名概览页右侧可以找到)" # 保存退出后,使环境变量生效 source ~/.bashrc安全提示:
CF_Token拥有修改你DNS的权限,务必像保护密码一样保护它。不要在命令行历史中明文留下它,也不要提交到版本控制系统。
5.3 使用自动模式申请证书
现在,申请证书的命令变得极其简单,不再需要手动干预和那个长参数。
# 清理之前手动模式可能留下的旧记录和状态(可选,但推荐) acme.sh --revoke -d myawesome.domain --ecc acme.sh --remove -d myawesome.domain --ecc rm -rf ~/.acme.sh/myawesome.domain* # 使用自动DNS模式申请(指定dns_cf) acme.sh --issue --dns dns_cf \ -d myawesome.domain \ -d *.myawesome.domaindns_cf是acme.sh内置的Cloudflare DNS模块标识。执行后,acme.sh会自动调用Cloudflare API添加TXT记录,等待验证,获取证书,并在验证成功后自动删除TXT记录。全程无需人工介入。
5.4 安装证书并设置自动续期
安装命令和之前一样,但此时--reloadcmd的价值就完全体现了。
acme.sh --install-cert -d myawesome.domain \ --key-file /etc/nginx/ssl/myawesome.domain/key.pem \ --fullchain-file /etc/nginx/ssl/myawesome.domain/cert.pem \ --reloadcmd "sudo systemctl reload nginx"至此,你完成了全自动化的配置。acme.sh的cronjob会每天检查证书有效期,在到期前30天左右自动续期,续期成功后自动将新证书安装到指定路径,并执行重载Nginx的命令。你几乎可以忘记证书续期这回事了。
6. 常见问题、排查技巧与实操心得
在实际操作中,你几乎一定会遇到一些问题。下面是我踩过坑后总结出来的经验。
6.1 DNS记录生效慢或验证失败
这是手动模式最常见的问题。acme.sh在--renew时提示超时或验证失败。
- 排查工具:使用
dig或在线DNS查询工具(如digwebinterface.com、mxtoolbox.com),从多个地点查询_acme-challenge.your-domain.com的TXT记录,确认值是否正确、是否已全球生效。 - 耐心等待:DNS传播可能需要时间,特别是TTL设置较高时。可以先将TTL改为300秒(5分钟),生效后再改回去。
- 检查记录格式:反复确认第4.2步中关于主机名填写的坑点。这是失败的主要原因之一。
- 使用
--debug参数:在--renew命令后加上--debug,acme.sh会输出更详细的日志,有助于定位问题。
6.2 证书续期失败或安装了旧证书
正如参考文章作者在2025年3月22日补充的,他遇到了续期后安装的是旧证书的问题。这通常是因为acme.sh的工作目录存在旧的状态文件。
- 彻底清理:在申请新证书前,尤其是从手动模式切换到自动模式,或者域名、验证方式发生变化时,先清理旧数据:
# 吊销旧证书(可选,如果证书已过期或无效可跳过) acme.sh --revoke -d myawesome.domain --ecc # 从acme.sh的配置中移除该域名 acme.sh --remove -d myawesome.domain --ecc # 删除该域名在.acme.sh目录下的所有文件 rm -rf ~/.acme.sh/myawesome.domain* - 检查续期日志:
acme.sh的日志在~/.acme.sh/acme.sh.log。查看最近一次的续期记录,看是否有错误。 - 手动强制续期:你可以手动触发一次续期来测试:
acme.sh --renew -d myawesome.domain --force
6.3 关于ECC与RSA密钥的选择
acme.sh默认使用ECC(椭圆曲线)密钥。ECC密钥比传统的RSA密钥更短,但安全性相当甚至更高,且计算速度更快,是现代TLS的最佳实践。除非你有非常特殊的兼容性需求(例如某些极其古老的客户端不支持ECC),否则强烈建议坚持使用ECC。
如果你必须使用RSA密钥,可以在--issue命令中加入--keylength 2048(或4096)参数。但请注意,一些CA(如Let‘s Encrypt)对RSA密钥长度有要求,2048位是最低标准。
6.4 证书文件说明与使用
在~/.acme.sh/your.domain_ecc/目录下,你会看到几个文件:
your.domain.cer: 你的站点证书。your.domain.key: 你的私钥。这是最敏感的文件,绝对不能泄露!ca.cer: 中间CA证书。fullchain.cer: 完整证书链(your.domain.cer+ca.cer)。Web服务器(如Nginx, Apache)的ssl_certificate指令需要的就是这个文件。your.domain.conf:acme.sh为该域名保存的配置信息。
在配置服务器时,你只需要fullchain.cer(作为证书)和your.domain.key(作为私钥)。通过--install-cert安装,就是将它们复制到了你指定的位置。
6.5 多域名与SAN证书
acme.sh同样支持申请包含多个不同域名的SAN(主题备用名称)证书。只需在命令中列出多个-d参数即可:
acme.sh --issue --dns dns_cf \ -d example.com \ -d *.example.com \ -d another.net \ -d www.another.net这样你会得到一张同时包含example.com,*.example.com,another.net,www.another.net的证书。这在管理多个相关域名时非常方便。
7. 总结与最终建议
走完这一整套流程,从手动DNS验证的“知其所以然”,到配置Cloudflare API实现全自动化的“知其然”,你应该对如何使用acme.sh这个神器获取免费泛域名SSL证书有了透彻的理解。整个过程的核心就是ACME协议的DNS-01挑战验证。
最后,再分享几个我个人的心得:
- 测试环境先行:如果你有备用的域名或子域名,先在测试环境走通整个流程,特别是DNS API的配置。在生产环境操作时会更从容。
- 备份私钥:证书丢了可以重申请,私钥丢了就真麻烦了。定期备份你的
key.pem文件到安全的地方。 - 监控证书状态:虽然
acme.sh自动续期很可靠,但建议设置一个简单的监控,比如用crontab每周运行一次acme.sh --list,检查所有证书的状态和过期时间,并将结果邮件通知自己。 - 关于证书有效期:无论是Let‘s Encrypt还是ZeroSSL,免费证书有效期都是90天。这比传统的1年或2年证书短,但正是这种短有效期,配合
acme.sh这样的自动化工具,强制我们建立了自动化的运维流程,从长远看,安全性反而更高了。
将HTTPS作为服务的默认标准,已经不再是可选项,而是必选项。利用acme.sh,我们几乎可以零成本、自动化地实现这一目标,即使是对于拥有大量子域名的复杂场景。希望这篇详细的开发日记,能帮你扫清障碍,顺利为自己的所有服务披上安全的外衣。
