本文最后更新于 343 天前 ,文中信息可能已经过时。如有问题请在评论区留言。

起因

群晖是有默认的DDNS的,也会自动申请SSL证书。但是你只能用群晖的默认二级域名,做分享或者其它东西,还是用自己的域名比较方便。

解析方面,有DDNS-GO来做。证书方面查到基本上有两种,一个是使用cerbot,另一个就是使用acme.sh

初次使用

个人还是比较习惯使用docker,遇到要需要安装的软件第一想法是能不能使用docker来搞。第一次使用来安装acme.sh也是翻了好几篇博客,也没有申请成功,还把默认的群晖证书干掉了,导致连不上DSM。只能下班回家后重新使用默认的DDNS来生成证书,这才恢复了访问。因为设置了强制HTTPS访问,怎么都打不开DSM,强制跳到HTTPS,然后提示证书为空,无法访问。又在网上各种搜索,怎么关闭群晖Nginx强制跳转,最终还是在某一个配置文件中找到了,现在想想,忘记是哪个文件了,回头找找做个记录。

再次尝试

上次失败,主要是证书的备注名称搞错了,结果把默认证书做了替换。这次是先随便上传了一个证书,写了备注与默认证书做区分。

照例贴上参考的帖子: 阿里域名证书(通过群晖)自动续签 acme.sh

已经写的蛮详细了,我简单说一下流程和有些稍微不一样的地方。

1、创建容器目录

2、启动acme.sh容器,一般是使用neilpang/acme.sh这个镜像。在这里我添加了TZ环境变量,设置为Asia/Shanghai,因为docker默认是使用UTC时区,日志中显示的时间会和北京时间不同。如果不敏感的话,可以不用加。

3、复制给到的shell脚本文件,修改为自己的配置,如果登录的帐号设置了双重验证,那么需要你获取到设备ID,文章也有提到。在这里要注意两点:windows下的换行(\r\n)和linux下的换行(\r)是使用的不同字符,在windows下编辑shell文件需要注意,如果使用vscode,可以看到右下角有CRLF(windowns默认)和LF(linux默认)。记得切换到LF。另一个是我的域名是在cloudflare中,需要生成CF_Key。不知道是在生成api-token时勾选的选项有问题还是怎么,后面在调用cf接口会报错。如果你也出现这样的问题,错误代码60036103可以尝试使用global API key。我也是在issues中看到有不少人再问这个问题,再查相关issue,看到有人说文档中写的是使用key不是token(我猜测早期应该还没有token这个参数吧)。Anyway,如果你也遇到了这个问题,记得试一试,没准就行了。

4、最后创建定时任务,运行一次看有没有问题。

使用的脚本

最后贴一下使用的脚本,注意脚本中的容器名称文件路径,要和自己的保持一致。

acme.sh

shell
acme.sh 脚本
#你的域名
DOMAIN='你的域名'
#证书供应商
CERT_SERVER='letsencrypt'
#DNS供应商 可选 dns_dp(腾讯云) dns_ali(阿里云)  dns_cf  其他可查https://github.com/acmesh-official/acme.sh/wiki/dnsapi
DNS="dns_cf"
#群晖账号密码
SYNO_Username='群晖账号'
SYNO_Password='群晖密码'
#如果开启了双重验证请在浏览器登录时选中保存此设备,然后从COOKIE中获取did cookie
SYNO_Device_Name="CertRenewal"
SYNO_DID='通过浏览器获取的did数值'
#以下群晖配置非必要不要更改
SYNO_Hostname="localhost" # Specify if not using on localhost
SYNO_Scheme="http"
SYNO_Port="5000"
#要添加的证书的名字,空字符串("")的话就是替代默认证书,一般建议使用空字符串,除非你有多个证书
SYNO_Certificate='' 

#以下三选一
#DNSPOD.CN 腾讯云
DP_Id=''
DP_Key=''
#阿里云
Ali_Key='阿里云的key'
Ali_Secret='阿里云的密钥'
#CF
CF_Key=''
CF_Email=''

case $DNS in 
    "dns_dp")
    a="DP_Id=${DP_Id}"&&b="DP_Key=${DP_Key}"
    ;;
    "dns_ali")
    a="Ali_Key=${Ali_Key}"&&b="Ali_Secret=${Ali_Secret}"
    ;;
    "dns_cf")
    a="CF_Key=${CF_Key}"&&b="CF_Email=${CF_Email}"
    ;;
esac
SYNOUsername="SYNO_Username=${SYNO_Username}"
SYNOPassword="SYNO_Password=${SYNO_Password}"
SYNODeviceID="SYNO_Device_ID=${SYNO_DID}"
SYNOHostname="SYNO_Hostname=${SYNO_Hostname}"
SYNOScheme="SYNO_Scheme=${SYNO_Scheme}"
SYNOPort="SYNO_Port=${SYNO_Port}"
SYNOCertificate="SYNO_Certificate=${SYNO_Certificate}"
SYNODID="SYNO_DID=${SYNO_DID}"
SYNODeviceName="SYNO_Device_Name=${SYNO_Device_Name}"

docker exec -e ${a} -e ${b} acme acme.sh --log --server "${CERT_SERVER}" --issue -d "${DOMAIN}" -d "*.${DOMAIN}" --dns "${DNS}" >> /volume1/docker/acme.sh/log.txt 2>&1
docker exec -e ${SYNOUsername} -e ${SYNOPassword} -e ${SYNODeviceID} -e ${SYNOHostname} -e ${SYNOScheme} -e ${SYNOPort} -e ${SYNOCertificate} -e ${SYNODID} -e ${SYNODeviceName} acme acme.sh --issue -d "${DOMAIN}" -d "*.${DOMAIN}" --dns "${DNS}" --deploy --deploy-hook synology_dsm  >> /volume1/docker/acme.sh/log.txt 2>&1

*定时脚本*

shell
定时脚本
bash /volume1/docker/acme.sh/acme.sh >> /volume1/docker/acme.sh/log.txt 2>&1