摘要
如果你有一个域名并用它来搭建互联网服务,提供 https 服务是基本的安全要求,那么就绕不开 SSL 证书的申请。本文介绍一种基于基于 acme.sh 和 dnspod API 生成网站泛域名证书的详细流程与方法,以供有类似场景和需求的同学参考。
如果你有一个域名并用它来搭建互联网服务,提供 https 服务是基本的安全要求,那么就绕不开 SSL 证书的申请。
目前阿里云、腾讯云等云产商都提供了免费申请和管理 SSL 证书的功能支持,但如果你需要使用的子域名比较多,泛域名 SSL 证书才是最好的选择,然而各厂商提供的泛域名证书基本都是需要收费的。
本文介绍一种基于基于 acme.sh 和 dnspod API 生成网站泛域名证书的详细流程与方法,以供有类似场景和需求的同学参考。其基本思路为:
- 通过
ZeroSSL
平台可以申请有效期为 90 天的免费泛域名 SSL 证书; - 将域名免费托管至 dnspod.cn,借助 dnspod 提供的 API 可以以代码编程方式程序化验证和设置域名解析;
- 著名的开源项目 acme.sh 以程序化脚本的方式,支持自动化的从
ZeroSSL
申请和续期泛域名 SSL 证书,支持调用 dnspod 平台 API 设置和验证域名解析。
下面的内容均以在 CentOS 7.x 系统下的操作为例,仅供参考。首先应保证 curl
和 cron
已安装,否则可执行如下安装命令:
yum update & yum install curl cron socat -y
1 基于 acme.sh 和 dnspod API 生成网站泛域名证书
1.0 快速开始
一键执行脚本参考:
# 设置 dnspod 的 DNS API Token export DP_Id="你的 ID" export DP_Key="你的 KEY" # 安装 acme.sh curl https://get.acme.sh | sh source ~/.bashrc acme.sh --version # 注册账号 acme.sh --register-account -m test@lzw.me # 获取证书 acme.sh --issue --dns dns_dp -d lzw.me -d *.lzw.me # 查看已安装的证书 acme.sh --list # 安装证书 mkdir -p /etc/nginx/acme.sh/lzw.me/ acme.sh --install-cert -d lzw.me \ --cert-file /etc/nginx/acme.sh/lzw.me/cert.pem \ --key-file /etc/nginx/acme.sh/lzw.me/key.pem \ --fullchain-file /etc/nginx/acme.sh/lzw.me/fullchain.pem \ --reloadcmd "nginx -s reload" # 开启 acme.sh 自动更新 acme.sh --upgrade --auto-upgrade # 查看定时任务 crontab -l # TODO: 请手动配置 nginx
- 以上为一键执行脚本示例,具体说明可参考下文介绍。
- 请注意设置你的 dnspod API Token 信息,并将
lzw.me
替换为你的域名。
1.1 安装 acme.sh
一键安装:
curl https://get.acme.sh | sh source ~/.bashrc acme.sh --version
提示:
如果安装了 git
,也可以直接使用 git 拉取仓库的方式安装。参考:
git clone https://github.com/acmesh-official/acme.sh.git alias acme.sh=~/.acme.sh/acme.sh
1.2 使用邮箱注册 ZeroSSL
账号
acme.sh
当前默认使用 ZeroSSL
服务,ZeroSSL
可以颁发有效期为 90 天的 SSL 证书。我们需要先注册一个 ZeroSSL 的账号:
$ acme.sh --register-account -m test@lzw.me # 输出信息参考: No EAB credentials found for ZeroSSL, let's get one Registering account: https://acme.zerossl.com/v2/DV90 Registered ACCOUNT_THUMBPRINT='9d1k6jRbSrzKy9iqiaMwaLz3kv2vmQ5LwAhc7tlEXN8'
1.3 生成 dnspod API Token
登录 dnspod.cn
,打开地址 https://console.dnspod.cn/account/token/apikey,在API秘钥 -> DNSPod Token
下创建一个秘钥,接着复制 ID 和 Token,执行如下命令将其配置到环境变量中:
export DP_Id="你的 ID" export DP_Key="你的 KEY"
1.4. 基于 dnspod
的 dns API 验证生成泛域名证书
这里以 lzw.me
为例,基于 dnspod 的 dns 验证方式生成泛域名证书。参考命令:
acme.sh --issue --dns dns_dp -d lzw.me -d *.lzw.me # 主要输出信息参考: Cert success. Your cert is in: /root/.acme.sh/lzw.me_ecc/lzw.me.cer Your cert key is in: /root/.acme.sh/lzw.me_ecc/lzw.me.key The intermediate CA cert is in: /root/.acme.sh/lzw.me_ecc/ca.cer And the full chain certs is there: /root/.acme.sh/lzw.me_ecc/fullchain.cer
执行成功后,DP_Id
和 DP_Key
会被保存到 ~/.acme.sh/account.conf
文件中,后续再执行时会自动读取并使用它。
查看已生成的证书:
acme.sh list
提示:
这里是我的域名托管在了 dnspod 上,如果你托管在其他服务商,可以从官方文档中查找对应的实现方式及命令:How to use DNS API
1.5 安装证书
acme.sh
生成的证书默认保存在 ~/.acme.sh
目录下,原则上可以直接使用它进行 nginx 的 https 配置。但是当需要续签重新生成证书时,还需要手动去重载 nginx。通过 acme.sh
提供的 install 命令,可以在自动续签完成后将证书安装到指定的位置,并调用 nginx 配置重载动作。命令参考:
mkdir -p /etc/nginx/acme.sh/lzw.me/ acme.sh --install-cert -d lzw.me \ --cert-file /etc/nginx/acme.sh/lzw.me/cert.pem \ --key-file /etc/nginx/acme.sh/lzw.me/key.pem \ --fullchain-file /etc/nginx/acme.sh/lzw.me/fullchain.pem \ --reloadcmd "nginx -s reload" # --reloadcmd "sesystemctl restart nginx"
2 配置 nginx 使用该证书
请参考以下配置:
# 禁用 http,80 端口重定向到 https server { listen 80; server_name lzw.me *.lzw.me; location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; server_name lzw.me; ssl on; ssl_certificate /etc/nginx/acme.sh/lzw.me/fullchain.pem; ssl_certificate_key /etc/nginx/acme.sh/lzw.me/key.pem; ssl_trusted_certificate /etc/nginx/acme.sh/lzw.me/cert.pem; # api 服务 nginx 反向代理示例 location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
3 acme.sh
与证书的自动更新
设置 acme.sh
自动更新:
acme.sh --upgrade --auto-upgrade
acme.sh
成功生成证书后,还会自动生成一条 cron 定时任务用于自动更新证书,这样就不用每次手动执行了。可以通过 crontab -l
查看:
$ crontab -l # 每天 20:25 自动检测是否需要更新证书 25 20 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
我们手动执行一下这条命令试一试:
$ "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" [Wed Jan 31 15:34:10 CST 2024] ===Starting cron=== [Wed Jan 31 15:34:11 CST 2024] Already uptodate! [Wed Jan 31 15:34:11 CST 2024] Upgrade success! [Wed Jan 31 15:34:11 CST 2024] Auto upgraded to: 3.0.8 [Wed Jan 31 15:34:11 CST 2024] Renew: 'lzw.me' [Wed Jan 31 15:34:11 CST 2024] Renew to Le_API=https://acme.zerossl.com/v2/DV90 [Wed Jan 31 15:34:11 CST 2024] Skip, Next renewal time is: 2024-03-30T04:10:45Z [Wed Jan 31 15:34:11 CST 2024] Add '--force' to force to renew. [Wed Jan 31 15:34:11 CST 2024] Skipped lzw.me_ecc [Wed Jan 31 15:34:11 CST 2024] ===End cron===
4 扩展参考
- https://github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dpi
- https://letsencrypt.org/zh-cn/docs/client-options/
这篇文章写得深入浅出,让我这个小白也看懂了!