前些日子因为破烂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
2
3
4
export DP_Id="API ID"
export DP_Key="API Key"

/root/.acme.sh/acme.sh --issue --dns dns_dp -d example.com -d *.example.com --server letsencrypt

此后acme会保存你设置的api以在未来自动帮你更新(默认30天)

申请到泛域名证书,便于后期统一便捷的证书管理

CloudFlare

cloudflare和dnspod略有不同,需要创建一个API来进行用于验证的解析记录的添加,

可以直接用cf提供的dns区域模版,记得选择你需要验证的域名,一个api可以编辑多个域名的解析记录。

1
2
3
4
5
6
7
# 设置CF Account ID
export CF_Account_ID="your account"

# 设置CF dns Token
export CF_Token="your token"

/root/.acme.sh/acme.sh --issue --server letsencrypt --dns dns_cf -d example.com -d *.example.com

以上。

申请到证书之后,就可以着手准备部署了,这里acme也有做群晖的hook,所以相当的方便,但是问题就出在dsm的deployhook还停留在5.0时代,默认只能更新Default证书,而无法同时管理其他非默认证书,这也是本文要解决的核心痛点之一其实是最主要的,将会在后文提及。

先设置好环境变量(第一次的时候设置好随后acme会将其保存在本地,后续是不需要再次设置的,即使有2FA

1
2
3
4
5
6
export SYNO_Username='Usr'
export SYNO_Password='Passwd'

#export SYNO_DEVICE_NAME="CertRenewal"

#配置用户名密码与设备名(2FA)

虽然可以使用临时管理员
这里建议用现成的有管理员权限的账号密码来实现(用临时管理员的时候出现了奇怪的问题),设备名仅在开启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.pemcert.pemkey.pem到gorky.cn的唯一证书存储文件夹中即可,在GUI里设置好gorky.cn分配的服务,就可以通过acme来更新非默认证书了。

如果需要GUI也同时更新gorky.cn的到期时间也很简单,更新完非默认证书后再用deployhook更新一遍默认证书即可,更新的过程中dsm的python脚本会把整个/certificate目录下的证书重新读一遍而且不会更改属于非默认证书的文件夹,所以把默认与非默认证书的更新放到一个脚本里先后执行ps:注意顺序,就可以保证GUI和对应目录的证书文件被同时更新在最新状态啦。

至此可以实现dsm证书管理的完全自动化。


© 2019-2025 Nodoka ,using Stellar.
All contents from this site are under CC BY-NC-SA 4.0 license, please indicate the source when reprinting.