有一个需求是在letencrypt上申请证书并且部署到nginx.
咋一看很简单, 官方提供的certbot就能实现?
不过真实场景比较复杂, 我们还需要更多实用功能:
- 自动申请任何域名的ssl证书并实现多台nginx部署
- 自动续签证书并通知nginx reload
- 可并发申请证书
官方提供的hook功能有限, 而且编码复杂并不能很好的实现"自动", 所以便自行用Golang实现, 记录下思路
服务器架构
首先区分客户端和服务端, 服务端负责获取证书并通知客户端部署, 客户端负责将证书和nginx文件写入nginx目录并reload.
服务端
要做的事情有
- 使用ACME协议向letencrypt申请证书, 并实现http01挑战, 使用的包是"github.com/xenolf/lego/acme"
- 维持与客户端的长连接, 实现消息通知
- 提供接口给客户端获取证书
- 自动续签证书
注意的点
- http01挑战需要实现acme包的Provider接口, 可以实现将key放内存来实现并发挑战. 原来的httpProviderService必须监听80端口, 而这并不是最好的.
- 服务端会将证书存在数据库, 方便存取.
- 长连接使用GRPC stream.
客户端
客户端负责控制nginx.
要做的事情有
- 监听服务端发来的部署消息并执行部署逻辑
- 写入nginx配置文件和证书文件, 并通知nginx reload
- 转发http01挑战到服务端
- 定时判断证书过期时间并向服务端取最新证书
额外说一下 是如果要跨容器控制nginx, 可以使用这个方案:
- 容器挂载宿主机docker.sock, 就可以使用docker exec 控制容器中的nginx了
总体流程
- 服务端通过acme发起申请一个证书, 挑战方式为http01
- letencrypt 会请求域名, 请求会被nginx转发到客户端再转发到服务端.
- 服务端完成挑战接收到证书, 将证书保存到数据库并通知客户端部署.
- 客户端接收到证书之后将证书写入本地目录 并写入对应的nginx配置文件, 再通知nginx重启
有疑问加站长微信联系(非本文作者)