使用 acme.sh 自动续签谷歌 SSL 证书
本文主要讲述 acme.sh(SSL 证书自动续签工具)
+ cloudflare(免费域名托管服务商)
+ Google Trust Services(SSL 证书颁发机构)
如何使用的标准流程。
前言
以前免费 SSL 证书时效一年的时候,一年折腾一次没啥感觉。现在所有的免费 SSL 证书时效都变成了 3 个月,折腾次数变多了之后就愈发感到困扰,所以拥有一个自动续期证书的工具就显得很重要了。这类工具常用的有 ohttps、acme.sh、certbot、Traefik(k8s 使用)。
OHTTPS 是我最早开始使用 SSL 证书的服务商,能够免费续迁证书,也可以 docker 部署自动更新,但是自动更新部署需要类似积分的东西,不充钱估计自动更新部署功能应该用不到两年。
acme.sh 顾名思义是一个使用 ACME 协议的客户端工具,由 shell 编写,支持Let’s Encrypt、zerossl、google、sslcom、buypass 等常见 CA 签发机构、支持自动更新部署、支持多个 DNS 服务商的 API,应该是当前使用的最多的免费 SSL 证书签发与续签工具。
Certbot 是官方(EFF电子前哨基金会)推荐的客户端,同样是一个使用 ACME 协议的经典客户端工具。它由 python 编写,主要是支持 Let’s Encrypt 的签发、自动续签。对于常见的 DNS 服务商 API 也提供支持,同时它还可以自动识别并修改 Nginx 或 Apache 的配置文件来安装证书。
Traefik 是一个非常流行的云原生边缘路由器或反向代理,它深度集成了 Let’s Encrypt,可以为 k8s 集群中的后端服务提供证书自动申请和管理功能。
本文主要是想写在 vps 上如何部署自动申请、续签 SSL 证书的工具,Traefik 由于主要是在 k8s 里面使用这个后面发文再说。长期免费续签 SSL 证书的工具就只有 acme.sh 和 Certbot 了。为什么我最终选择了 acme.sh 呢?原因主要是有三点:
- acme.sh 支持更多的 CA 机构
- acme.sh 支持更多的 DNS API,由于通配符证书必须要使用 DNS 验证,这一点很重要
- acme.sh 完全由 shell 编写,不需要额外安装依赖
以上是背景,下面开始部署教程。
1. 安装 acme.sh
命令中的 [email protected]
换成自己的邮箱
1 | curl https://get.acme.sh | sh -s [email protected] |
这一条命令执行完成,会在你当前的家目录下面新建一个 .acme.sh
文件夹,后面生成的证书以及所有与之相关的文件都会在这个文件夹里面。同时还会新建一个定时任务每天0点自动检测证书有效期,如果临近过期则会自动发起更新证书的操作。
执行这条命令加载环境变量,让 acme.sh 命令能被识别
1 | source ~/.bashrc |
2. DNS 记录验证准备
本文指的 SSL 证书都是为域名颁发的,因为现在为 ipv4 颁发 SSL 证书也是很常见的一个操作,所以这里提一下以免混淆!对于域名的 SSL 证书在颁发之前必须要做域名所有权验证,常见的验证方式有两种。
- 为需要颁发证书的域名添加指定的 DNS 记录进行验证
- 在需要颁发证书的域名网站的根目录,添加指定文件进行验证
我这里因为是要给通配符域名颁发证书,所以只能选择使用 DNS 记录进行验证,我的域名免费托管在 cloudflare 上而 acme.sh 可以调用 cloudflare 的 api 进行自动化部署,下面说明如何操作。
2.1 创建 APi 令牌
登录 cloudflare 后选择需要操作的域名,假如我有一个域是 hello.com
,后面都以这个域名来描述。
选择域之后,往下看到右边的 API 标题那里记录自己的 区域ID
,然后点击 获取您的API令牌
,然后再点击 创建令牌
并选择 编辑区域 DNS
给区域编辑权限,特定区域
选择 hello.com
, 同时建议为令牌的使用指定来源 ip 以加强安全
令牌创建完成后会获得一个 key 并记录下来。
2.2 添加环境变量
下面的命令中 CF_Token
换成你完成创建令牌后获得的 key,CF_Zone_ID
后面的内容换成你的 区域 ID
1 | export CF_Token="xxxxxxxxxxxxxxxxxxxxxxxxx" |
这一步是为后面 acme.sh 调用 API 添加 DNS 记录进行验证做准备的,在使用 acme.sh 第一次申请证书的时候会被 acme.sh 自动保存,后面证书过期自动续签的时候就不需要人为干预了。
3.Google API 权限配置
acme.sh 本身是支持多个 CA 机构的,默认使用的是 zerossl,其次用的最多的是 let’s encrypt,不过我一般偏好 google(无他,个人偏好)
3.1登录 GCP 控制台
GCP控制台 点击登录,选择右上角的激活 cloud shell。
额外说下,这里登录 GCP 控制台的账号跟上面第一步安装 acme.sh 的时候邮箱账号是没有任何关联的。
第一个步骤里面的邮箱账号是注册 ACME 账号的,仅用于向 CA 机构说明身份和接收通知;
这里登录 GCP 控制台的账号是用来向谷歌获取颁发证书的授权的,两者无任何关联关系!
3.2启用 publicca
在 cloud shell 里面执行命令启用 publicca
1 | gcloud services enable publicca.googleapis.com |
3.3获取 EAB 密钥 ID 和 HMAC
记录下获取到的密钥和 HMAC 值
1 | gcloud publicca external-account-keys create |
4.颁发证书
4.1 申请证书
在自己部署 acme.sh
的 vps 上执行命令申请证书
1 | acme.sh --issue --dns dns_cf -d hello.com -d '*.hello.com' --keylength 2048 --dnssleep 120 |
--keylength 2048
指定使用 RSA 加密算法,长度为 2048-d hello.com -d '*.hello.com'
指定要申请证书的域名。(这里要注意*.hello.com
是不包含 hello.com 这个根域名的,如果你有直接使用 hello.com 访问加密的站点则必须要额外加上-d hello.com
)--dns dns_cf
指定 dns 服务商为 cloudflare--issue
核心命令,它的作用是向一个证书颁发机构(CA)发起请求并获取一个新的SSL证书--dnssleep 120
DNS 指定记录检查等待时间为 120 秒。默认是 20 秒,如果指定多个域名建议调整长一点
4.2安装证书
这一步也可以不使用下面的命令,安装证书本质上的操作就是把生成的证书、密钥文件复制到指定的路径,自己手动复制完全没问题的。
不过相对于手动操作,使用命令安装证书有个好处是后面自动更新证书的时候,acme.sh 会在证书更新完成后自动的执行这里相同的安装命令以达成自动更新本地证书的目的,这样就不用在证书续签之后再手动复制了!
1 | acme.sh --install-cert -d hello.com --fullchain-file /etc/pki/nginx/fullchain.cer --key-file /etc/pki/nginx/fullchain.pem --reloadcmd "systemctl reload nginx.service" |
fullchain.cer
是我习惯用来保存证书的文件fullchain.pem
是我习惯用来保存密钥的文件--reloadcmd
因为我 vps 上是用 nginx 部署的 web 服务,所以这里可以顺便指定本地证书替换完成后 reload 的操作
5.结束
全程大概五分钟不到,一次操作终身免于证书更新的困扰!
补充一个关于常见证书文件后缀相关的小知识:
.key
私钥 (Private Key)文件。不应该给任何人看的核心机密。对应 Nginx 里面的ssl_certificate_key
.pem
通用后缀。文件里可以包含私钥、服务器证书、中间证书、根证书,或任意组合。必须根据上下文或文件名来判断其内容.crt
公钥证书 (Certificate)文件。通常只包含一个公钥证书(服务器证书或中间证书),一般不包含私钥。与.cer
常常可以互换使用.cer
公钥证书 (Certificate)文件。和.crt
基本一样,也是代表公钥证书。acme.sh
默认生成.cer
,而Windows系统也常用.cer
.csr
证书签名请求 (Certificate Signing Request)文件。通常会把域名信息和公钥打包在这个文件里提交给CA,请求CA用他们的私钥来“签名”这个请求,从而生成 SSL 证书