前些日子因为破烂ds216play的证书到期,之前懒得折腾用的腾讯云免费证书,导致依托的证书需要更新(腾讯云免费方案不包含泛域名而且一年一签),于是发奋搞了个acme的自动化,因为ds216play的配置过于简陋,故没有使用caddy一类的现成工具,而是采用较为原始的acme方案当然感觉caddy的caddyfile是有点写不来
ssh和root权限是必要的,咱是直接全程root干下来的。
acme安装与证书申请
安装acme.sh,经过各种奇妙的权限报错,这里建议直接以root用户执行安装脚本,安装到/root
下
1 | curl https://get.acme.sh | sh -s [email protected] --force |
!注意这里邮箱请务必替换成一个正常的邮箱,否则deploy的时候会报错
!注意添加force参数,否则会因群晖没有crontab报错
然后是申请证书,在家宽环境下没有80端口,而各大CA正常是不支持80以外的端口做域名验证的,因此建议使用acme自带的域名服务商的api来验证域名的所有权。
需要在环境变量里设置好已经获取到的自己账号的api
下面是比较常用的腾讯云和Cloudflare使用api完成验证的步骤
DNSPod
前置步骤后,
使用:
1 | export DP_Id="API ID" |
此后acme会保存你设置的api以在未来自动帮你更新(默认30天)
申请到泛域名证书,便于后期统一便捷的证书管理
CloudFlare
cloudflare和dnspod略有不同,需要创建一个API来进行用于验证的解析记录的添加,
可以直接用cf提供的dns区域模版,记得选择你需要验证的域名,一个api可以编辑多个域名的解析记录。
1 | # 设置CF Account ID |
以上。
申请到证书之后,就可以着手准备部署了,这里acme也有做群晖的hook,所以相当的方便,但是问题就出在dsm的deployhook还停留在5.0时代,默认只能更新Default证书,而无法同时管理其他非默认证书,这也是本文要解决的核心痛点之一其实是最主要的,将会在后文提及。
先设置好环境变量(第一次的时候设置好随后acme会将其保存在本地,后续是不需要再次设置的,即使有2FA
1 | export SYNO_Username='Usr' |
虽然可以使用临时管理员
这里建议用现成的有管理员权限的账号密码来实现(用临时管理员的时候出现了奇怪的问题),设备名仅在开启2FA的时候需要
然后调用hook部署即可:
1 | /root/.acme.sh/acme.sh --deploy --home /root/.acme.sh -d "example.com" --deploy-hook synology_dsm |
这时到控制面板中已经可以看到由acme部署到证书了。
最后写个脚本负责定期检查和更新证书并重新自动部署,在控制面板的定时任务里bash一下即可(注意要用root用户,amce.sh要写为/root/.acme.sh/acme.sh
,之后便可以放手不管证书的问题了喵(摊手
然后到下一个问题:多证书管理
去年八月份部署好了单证书的自动化更新和deploy之后无奈地发现,synology在GitHub上提供的api库还停留在5.x时代,甚至还找不到目录并未发现修改配置的方法(首先怀疑我菜,但是没找到相关博文和issue,推测为大佬懒得搞也不需要在这种家用nas上做多证书),也就是说在无法修改 SYNO.Core.Certificate.lib其实是咱没去找 的情况下我们只能按hook默认的直接deploy to default而没法使用dsm官方的deploy hook来管理非默认证书。
这自然让人极为恼火💢
毕竟我[email protected]的mail和gorky.cn的site还挂在这台nas上,而打算折腾的静态博客预备使用nodoka.world的域名,总不能让mail和wp一直裸奔,又不想每次手动更新证书,所以开始想啊想,找能用acme管理非默认证书的方法。
那天在试图寻找hexo多端同步和与wp连接方法的时候突然想能不能直接干到dsm的证书目录下让acme去更新,不管GUI用的那套python证书管理脚本里面能不能识别出证书被更新,于是开始探索dsm的目录结构,在
1 | /usr/syno/etc/certificate |
中找到了所有的证书文件,但是用了一个随机的六位字符串来命名每个存有不同证书的私钥,证书,证书链文件的文件夹。
然后
有意思的,
在nodoka.world的泛域名证书通过deploy hook部署成默认证书之后,咱先用acme和cf的api申请到gorky.cn的泛域名证书,直接按dsm的默认命名和格式生成
fullchain.pem
和
key.pem
下载到本地并用GUI上传,
那么这时候.gorky.cn的证书就分配到了一个唯一且不变的六位字符名称*,同时fullchain.pem
经过python脚本处理生成了对应的占位用的cert.pem
这时只需用acme部署gorky.cn的fullchain.pem
,cert.pem
和key.pem
到gorky.cn的唯一证书存储文件夹中即可,在GUI里设置好gorky.cn分配的服务,就可以通过acme来更新非默认证书了。
如果需要GUI也同时更新gorky.cn的到期时间也很简单,更新完非默认证书后再用deployhook更新一遍默认证书即可,更新的过程中dsm的python脚本会把整个/certificate
目录下的证书重新读一遍而且不会更改属于非默认证书的文件夹,所以把默认与非默认证书的更新放到一个脚本里先后执行ps:注意顺序,就可以保证GUI和对应目录的证书文件被同时更新在最新状态啦。
至此可以实现dsm证书管理的完全自动化。