起因
群晖是有默认的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接口会报错。如果你也出现这样的问题,错误代码6003和6103可以尝试使用global API key。我也是在issues中看到有不少人再问这个问题,再查相关issue,看到有人说文档中写的是使用key不是token(我猜测早期应该还没有token这个参数吧)。Anyway,如果你也遇到了这个问题,记得试一试,没准就行了。
4、最后创建定时任务,运行一次看有没有问题。
使用的脚本
最后贴一下使用的脚本,注意脚本中的容器名称和文件路径,要和自己的保持一致。
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*定时脚本*
bash /volume1/docker/acme.sh/acme.sh >> /volume1/docker/acme.sh/log.txt 2>&1