概述
前情提要:
这会是一篇系列文章,本想先从 SSL 基本概念科普讲起,结果坑越挖越大。为了不鸽太久,就先把最近刚更完的证书相关操作先来逐步填坑,等后续再反补科普向内容(但愿)。
本系列内容大致分为四篇:
- SSL 相关基础知识-科普向 (有生之年)
- acme.sh 快速入门-主要功能及申请SSL证书实践
- acme.sh 最佳实践-自动申请证书与自动部署群晖 DSM
- acme.sh 进阶版-多域名自动化管理 (本篇)
- acme.sh 阶段性终结-批量部署
在上一篇 acme.sh 最佳实践-自动申请证书与自动部署群晖 DSM 中,我们已经完成了单个域名的证书申请及自动化维护。但在我们日常生活中,难免会有多个域名、多个 NS 托管商,进而需要申请和维护多套 SSL 证书的情况,这时候光靠简单的指令执行可能不利于集中维护。
因此,本篇将以笔者个人用途场景出发,以简单脚本的方式统一维护多域名、多 NS 配置,实现多套 SSL 证书的便捷维护操作。
环境准备
在开始”最佳实践”之前,重申一下后续执行 acme.sh 的相关环境,方便还没阅读过前文的读者直接上手。
基础环境
在开始之前需要升级系统的 CA 证书,以避免后续在申请 SSL 证书时遇到问题。
yum install -y ca-certificates
安装 acme.sh
在本例中将以 root 用户进行安装。
export ACME_HOME="/usr/local/acme.sh"
mkdir -p $ACME_HOME/data
cd /usr/local/src
curl -so acme.sh https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh
chmod +x acme.sh && ./acme.sh --install-online \
--home $ACME_HOME \
--cert-home $ACME_HOME/data \
--accountemail "nestealin@gmail.com" \
--nocron
ls ./acme.sh && rm -f ./acme.sh && cd $ACME_HOME && ls -l
参数释义:
--home
: 表示安装主目录(默认含config-home
),用于安装acme.sh
。默认情况下,它安装在~/.acme.sh
。--cert-home
: 用于保存你签发的证书 ( 如:/usr/local/acme.sh/data/
)。默认情况下,它跟随--config-home
默认值。--accountemail
: 用于在 Let’s Encrypt 注册账户的电子邮件地址,以便后续收到续期通知邮件。--nocron
: 安装acme.sh
后不自动创建定时任务。
更换签发 CA
注: 该步骤非必须,可以根据实际情况按需修改。
由于 acme.sh 默认向 ZeroSSL CA 申请 SSL 证书。然而,本次笔者将其修改为 Let’s Encrypt 作为证书的 CA。
acme.sh --set-default-ca --server letsencrypt
以上,完成环境的基本准备,可以开始实践操作。
工具下载
在本仓库 Release 中已提供 Linux 系统打包好的二进制文件,可以在有限的操作系统中做到”开箱即用”。
mkdir /usr/local/acme.sh/scripts
cd /usr/local/acme.sh/scripts
curl -sL https://github.com/nestealin/acme_cli/releases/download/v1.0.0/acme_cli -o acme_cli
chmod +x ./acme_cli
ln -s /usr/local/acme.sh/scripts/acme_cli /usr/local/bin/acme_cli
curl -sL https://github.com/nestealin/acme_cli/releases/download/v1.0.0/domains_config.yaml.sample -o domains_config.yaml
基本配置
参照 domains_config.yaml 内容,结合域名、NS特性进行修改。
cd /usr/local/acme.sh/scripts
vim domains_config.yaml
主域名证书
以下是一个 example.com 域名将 DNS 托管在 Cloudflare,打算申请 example.com
及 *.example.com
域名证书的配置格式:
domains:
# Cloudflare-SingleDomain
# issue for example.com and *.example.com
- domain_name: example.com
domain_ns: dns_cf
ns_key: CF_Token
ns_key_value: ABCDEFG1234567890
ns_secret: CF_Account_ID
ns_secret_value: HIJKLMN0987654321
SAN_domains: ""
参数释义:
domain_name
: 证书主域名,即主要签发的域名,默认签发三级泛域名*.foo.org
;domain_ns
: 主域名所属 DNS 服务商,语法格式遵循acme.sh DNS API 简称;ns_key
: DNS API 参数环境变量”Key”名称,遵循acme.sh DNS API 变量;ns_key_value
: DNS API 参数环境变量”Key”对应值;ns_secret
: DNS API 参数环境变量”Secret”名称,遵循acme.sh DNS API 变量;ns_secret_value
: DNS API 参数环境变量”Secret”对应值SAN_domains
: 证书是否需要签发多个子域名,如果不存在则保持""
即可,如果存在则以列表格式追加;
多SAN证书
以下是一个主域名为 foo.net,其 DNS 托管在 DNSPod,打算申请:
foo.net
*.foo.net
dev.foo.net
*.dev.foo.net
test.foo.net
*.test.foo.net
多SAN域名证书的配置格式:
domains:
# DNSPod-MultiSANs
# issue for foo.net, *.foo.net, dev.foo.net, *.dev.foo.net, test.foo.net and *.test.foo.net
- domain_name: foo.net
domain_ns: dns_dp
ns_key: DP_Id
ns_key_value: 123456
ns_secret: DP_Key
ns_secret_value: ABCDEFG1234567890
SAN_domains:
- dev.foo.net
- test.foo.net
注:
- 更多供应商配置信息请参考: 自动 DNS API 简称及变量速查 | Nes的草稿箱
基本功能
前提条件:
- 已经安装 acme.sh 基本环境;
- 已经完成 domains_config.yaml 文件的域名与DNS API配置;
以下,将主要介绍二进制工具的管理功能。
查询当前托管中的证书
acme_cli list
效果:
# acme_cli list
Main_Domain KeyLength SAN_Domains CA Created Renew
example.com "ec-256" *.example.com,*.dev.example.com,*.pre.example.com LetsEncrypt.org 2024-08-30T14:37:23Z 2024-10-28T14:37:23Z
续期单一证书
acme_cli renew ${CERT_DOMAIN}
注意: 这里的
CERT_DOMAIN
指的是证书的主域名,即使用acme_cli list
输出中的 “Main_Domain” 字段。
该指令允许使用 --force
参数可以实现强制更新,如: 即使当前证书距离到期大于30天,也可以执行强制更新。
更新单一域名 | 新增 SAN 域名
该功能具备如下几种能力:
- 可以是新增域名时的首次证书申请;
- 可以是在已有证书的情况下追加SAN域名重新签发;
- 可以是对现有证书执行更新,效果等同于
acme_cli renew ${CERT_DOMAIN}
;
acme_cli issue example.com --force
可以增加 --force
参数可以实现强制更新,如: 即使当前证书距离到期日期大于30天,也可以执行强制更新。
续期所有证书
acme_cli renew_all
该指令默认为强制更新维护中的所有证书。
移除证书
acme_cli remove example.com
该功能会同时移除 acme.sh 维护中的证书,以及本地证书目录,避免需要人为二次清理。(因为删除操作是高危操作,所以会有二次确认的交互内容)
注: 由于该工具只是根据笔者习惯简单封装了 acme.sh 的几个常用核心功能,如有自定义扩展需求,可以拉取仓库源码自定义扩展/修改。
最佳实践
1. 新增域名
假设现在有一个新的域名(foo.org),其 DNS 托管在”阿里云DNS”上,现在要签发一套 foo.org
和 *.foo.org
域名的 SSL 证书。可以参照如下流程进行:
在配置文件中新增域名
cd /usr/local/acme.sh/scripts
vim domains_config.yaml
新增域名 foo.org
如:
- domain_name: foo.org
domain_ns: dns_ali
ns_key: Ali_Key
ns_key_value: LTA123456
ns_secret: Ali_Secret
ns_secret_value: ABCDEFG1234567890
SAN_domains: ""
参数释义:
domain_name
: 证书主域名,即主要签发的域名,默认签发三级泛域名*.foo.org
;domain_ns
: 主域名所属 DNS 服务商,语法格式遵循acme.sh DNS API 简称;ns_key
: DNS API 参数环境变量”Key”名称,遵循acme.sh DNS API 变量;ns_key_value
: DNS API 参数环境变量”Key”对应值;ns_secret
: DNS API 参数环境变量”Secret”名称,遵循acme.sh DNS API 变量;ns_secret_value
: DNS API 参数环境变量”Secret”对应值SAN_domains
: 证书是否需要签发多个子域名,如果不存在则保持""
即可,如果存在则以列表格式追加;
执行新增
acme_cli issue foo.org
静候执行结束即可。
2. 追加SAN域名
假设现在要给以前发过证书的 foo.org 域名证书中追加 SAN 域名,其中 SAN 域名有:
dev.foo.org
bar.foo.org
那么,签发后的证书理论上应该包含如下几个域名:foo.org
*.foo.org
dev.foo.org
*.dev.foo.org
bar.foo.org
*.bar.foo.org
可以参照如下流程进行:
在配置文件中新增域名
cd /usr/local/acme.sh/scripts
vim domains_config.yaml
找到已存在的域名 foo.org
,对 SAN_domains
字段追加预期的子域名:
- domain_name: foo.org
domain_ns: dns_ali
ns_key: Ali_Key
ns_key_value: LTA123456
ns_secret: Ali_Secret
ns_secret_value: ABCDEFG1234567890
SAN_domains:
- dev.foo.org
- bar.foo.org
参数释义:
domain_name
: 证书主域名,即主要签发的域名,默认签发三级泛域名*.foo.org
;domain_ns
: 主域名所属 DNS 服务商,语法格式遵循acme.sh DNS API 简称;ns_key
: DNS API 参数环境变量”Key”名称,遵循acme.sh DNS API 变量;ns_key_value
: DNS API 参数环境变量”Key”对应值;ns_secret
: DNS API 参数环境变量”Secret”名称,遵循acme.sh DNS API 变量;ns_secret_value
: DNS API 参数环境变量”Secret”对应值SAN_domains
: 因为存在多个 SAN 域名,则以列表格式追加;
执行新增
acme_cli issue foo.org --force
静候执行结束即可。
总结
本篇主要讲述如何使用 acme_cli 工具简单实现多域名、多 NS 托管商的统一管理,来进一步降低用户的维护复杂度。