
脚本解决雷池 WAF 的域名证书自动续签
在没有自动化执行之前,我都是用的 utool 中的域名插件,手动生成泛域名证书,然后拷贝到 WAF 中的。

雷池支持自动申请证书,但是不支持泛域名证书。
最近想要把这件事自动化一下。
折腾第一次~
看到了一个 github 帖子【推荐】纯脚本解决雷池 WAF 自动续签问题 #987 ↗
该帖子发布较早,现在已经无法正确执行。
docker run --rm -it -v "/data/acme":/acme.sh neilpang/acme.sh --issue --dns dns_tencent -d *.987654321.xyz -d 987654321.xyz --yes-I-know-dns-manual-mode-enough-go-ahead-please
会报错:
[Tue Aug 25 07:35:45 UTC 2026] Using CA: https://acme.zerossl.com/v2/DV90
[Tue Aug 25 07:35:45 UTC 2026] No EAB credentials found for ZeroSSL, let's obtain them
[Tue Aug 25 07:35:45 UTC 2026] acme.sh is using ZeroSSL as default CA now.
[Tue Aug 25 07:35:45 UTC 2026] Please update your account with an email address first.
[Tue Aug 25 07:35:45 UTC 2026] acme.sh --register-account -m my@example.com
[Tue Aug 25 07:35:45 UTC 2026] See: https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA
[Tue Aug 25 07:35:45 UTC 2026] Please add '--debug' or '--log' to see more information.
[Tue Aug 25 07:35:45 UTC 2026] See: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh
acme.sh is using ZeroSSL as default CA now. 默认使用服务 ZeroSSL 需要提供邮箱📮信息。
所以脚本需要添加:--register-account -m my@example.com 增加这个以后会自动拿着这个邮箱注册。
我也用的是腾讯云的域名管理,然后按照要求把SAVED_Tencent_SecretId 和 SAVED_Tencent_SecretKey 写入到 account.conf 文件。
如果使用了--issue --dns dns_tencent DNS 验证的话,那么就不需要--yes-I-know-dns-manual-mode-enough-go-ahead-please手动验证的参数了。
再次执行修改后的脚本:
docker run --rm -it -v /opt/myapp/acme:/acme.sh neilpang/acme.sh --register-account -m aaa@qq.com --server zerossl --issue --dns dns_tencent -d *.lichenghao.cn
执行结果,大概如下所示:
Using CA: https://acme.zerossl.com/v2/DV90
Single domain='*.lichenghao.cn'
Getting webroot for domain='*.lichenghao.cn'
Adding TXT value: Dx-5nGnsfULyqNR6K6tqniMbI for domain: _acme-challenge.lichenghao.cn
The TXT record has been successfully added.
Let's check each DNS record now. Sleeping for 20 seconds first.
You can use '--dnssleep' to disable public dns checks.
See: https://github.com/acmesh-official/acme.sh/wiki/dnscheck
Checking lichenghao.cn for _acme-challenge.lichenghao.cn
Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 35
Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 28
Not valid yet, let's wait for 10 seconds then check the next one.
Let's wait for 10 seconds and check again.
You can use '--dnssleep' to disable public dns checks.
See: https://github.com/acmesh-official/acme.sh/wiki/dnscheck
Checking lichenghao.cn for _acme-challenge.lichenghao.cn
Success for domain lichenghao.cn '_acme-challenge.lichenghao.cn'.
All checks succeeded
Verifying: *.lichenghao.cn
Processing. The CA is processing your order, please wait. (1/30)
Pending. The CA is processing your order, please wait. (2/30)
Success
Removing DNS records.
Removing txt: Dx-5nGnsfU5DVC6LyqNJ_lZZIgShP11eR6K6tqniMbI for domain: _acme-challenge.lichenghao.cn
Successfully removed
Verification finished, beginning signing.
Let's finalize the order.
Le_OrderFinalize='https://acme.zerossl.com/v2/DV90/order/suec4vMZuHaDZKQ/finalize'
Order status is 'processing', let's sleep and retry.
Sleeping for 15 seconds then retrying
Polling order status: https://acme.zerossl.com/v2/DV90/order/suec4vMDaDZKQ
Downloading cert.
Le_LinkCert='https://acme.zerossl.com/v2/DV90/cert/LB9E122S4t-g'
Cert success.
-----BEGIN CERTIFICATE-----
MIIDfzCCAyagAwIBAgIRAKWk8AY1fNKWe64zQciAJtcwCgYIKoZIzj0EAwIwRjEL
......
hkjOPQMBBwNCAASmRtrrDZ7ByjaHX11+D76N1I85BsupVmGGOSi+ActjyK7ziO32
......
UAIgdEzu7GvLOBTavFZKZXsshpPb9eMTp3vRMYQDOM+czsc=
-----END CERTIFICATE-----
Your cert is in: /acme.sh/*.lichenghao.cn_ecc/*.lichenghao.cn.cer
Your cert key is in: /acme.sh/*.lichenghao.cn_ecc/*.lichenghao.cn.key
The intermediate CA cert is in: /acme.sh/*.lichenghao.cn_ecc/ca.cer
And the full-chain cert is in: /acme.sh/*.lichenghao.cn_ecc/fullchain.cer
ARI suggestedWindow: 2026-11-10T23:59:59Z to 2026-11-12T23:59:59Z
Next renewal time picked from ARI window: 2026-11-11T01:11:45Z
中间有两个错误码,别担心,不影响最终证书的生成~ 最终会生成 *.lichenghao.cn.cer 和 *.lichenghao.cn.key 这俩是我们最终要用的。
可以先把他俩手动复制到雷池的证书管理中,验证一下是否可用,出现如下就是没问题了哦~

没有问题以后,接下来修改renew.sh。
考虑修改:
- 建立脚本目录, 所有脚本以及生成的文件存放目录,我修改为: /opt/myapp/acme;
- 建立证书归档目录, 我修改为: /opt/myapp/acme/archived/;
- WAF 证书 ID, 雷池 WAF 域名证书的 ID;
- DOMAIN, 需要生成证书的域名,我的域名 lichenghao.cn;
- newfile 和 oldfile 的路径;
修改后的脚本:
#!/bin/bash
#auto renew ssl for safeline waf
#by dominicx
#cert id in safeline for this ssl
CERTID=1
DOMAIN="lichenghao.cn"
ARCHIVEDDIR="/opt/myapp/acme/archived/"
#step 1 renew ssl cert
docker run --rm -it -v "/opt/acme":/acme.sh neilpang/acme.sh --issue --dns dns_tencent -d "*.$DOMAIN" -d "$DOMAIN"
newfile="/opt/myapp/acme/*.$DOMAIN\_ecc/*.$DOMAIN.cer"
oldfile="/data/safeline/resources/nginx/certs/cert_$CERTID.crt"
newkey="/opt/myapp/acme/*.$DOMAIN\_ecc/*.$DOMAIN.key"
oldkey="/data/safeline/resources/nginx/certs/cert_$CERTID.key"
if [ ! -e $newfile ] || [ ! -e $newkey ] ; then
echo "至少有一个文件不存在,请检查文件路径。"
echo $newfile
echo $newkey
exit 1
fi
newfile_ts=$(stat -c %Y $newfile)
oldfile_ts=$(stat -c %Y $oldfile)
if [ $[$newfile_ts - $oldfile_ts] -ge 300 ]; then #5 minutes
echo "Move old SSL cert files to $ARCHIVEDDIR ."
mv $oldfile $ARCHIVEDDIR
mv $oldkey $ARCHIVEDDIR
echo "Copy new SSL cert files."
cp $newfile $oldfile
cp $newkey $oldkey
keystr="$(<$newkey)"
certstr="$(<$newfile)"
sql="update mgt_ssl_cert set updated_at=to_timestamp($newfile_ts),valid_before=CAST(concat(to_timestamp($newfile_ts+90*24*3600)::date+1,' 07:59:59+08') AS TIMESTAMPTZ ),cert_content='$certstr',key_content='$keystr' where id=$CERTID;"
#update safeline pg
docker exec -it safeline-pg psql -U safeline-ce safeline-ce -c "$sql"
#nginx reload ssl cert
docker exec -it safeline-tengine nginx -s reload
echo "updating site $CERTID SSL cert file Done."
fi
最后增加个系统定时任务,每个月的 1 号和 15 号 凌晨 1:15 执行一次。
15 1 1,15 * * /opt/acme/scripts/renew.sh > /opt/acme/logs/update.log 2>&1 &
🎉🎉🎉
折腾第二次~
上面操作有个错误,应该把泛域名证书的 fullchain 证书复制到文件 cert_1.crt。
但是总感觉这个脚本太复杂了呢,然后就有搜索了下文档,直到雷池社区版自动 SSL ↗ , 就是以后还是要第一时间找官网的文档。
官方文档给了两个方式,我选择了第二种。
- freessl 配置域名,省事方案
- dns api 方案,适用于域名多,或者不信任 ✅
安装 acme 脚本
curl https://get.acme.sh | sh -s email=my@example.com
或者
wget -O - https://get.acme.sh | sh -s email=my@example.com
验证
acme.sh -h
整理安装脚本
在参考雷池的官网文档:雷池 WAF 帮助文档 - 雷池社区版自动 SSL ↗ 和 acme 的文档后,我选择使用 DNS api 验证域名所有权;
github.com/acmesh-official/acme.sh/wiki/dnsapi ↗
使用 Use TencentCloud (DNSPod) API 生成证书;得到最终的命令脚本,安装并重启 nginx。
acme.sh --install-cert --issue --dns dns_tencent -d *.lichenghao.cn \
--key-file /data/safeline/resources/nginx/certs/cert_1.key \
--fullchain-file /data/safeline/resources/nginx/certs/cert_1.crt \
--reloadcmd "docker exec safeline-tengine nginx -s reload"
设置 encent_SecretId 和 Tencent_SecretKey
在执行命令之前,需要把腾讯云的 Tencent_SecretId 和 Tencent_SecretKey 加入环境变量。
Please visit https://console.cloud.tencent.com/cam/capi ↗ to obtain the API key.
export Tencent_SecretId="<Your SecretId>"
export Tencent_SecretKey="<Your SecretKey>"
有很多方案,无论使用那种方法,acme.sh 会自动把腾讯云的密钥保存到它的账户配置中,下次自动续期时无需再次 export。
✅ 方案一:写入 acme.sh 的专用配置文件(最安全、最省事)
acme.sh 会自动把腾讯云的密钥保存到它的账户配置中,下次自动续期时无需再次 export。
执行一次签发后(确保这次能成功),acme.sh 会自动将其存入 ~/.acme.sh/account.conf。你也可以手动写入:
echo "Tencent_SecretId='你的SecretId'" >> ~/.acme.sh/account.conf
echo "Tencent_SecretKey='你的SecretKey'" >> ~/.acme.sh/account.conf
✅ 方案二:写入 Shell 的启动文件(永久有效)
如果你想在任意新终端直接使用,把 export 命令写入你的 Shell 配置文件:
# 如果你是 bash
echo "export Tencent_SecretId='你的SecretId'" >> ~/.bashrc
echo "export Tencent_SecretKey='你的SecretKey'" >> ~/.bashrc
source ~/.bashrc
# 如果你是 zsh
echo "export Tencent_SecretId='你的SecretId'" >> ~/.zshrc
echo "export Tencent_SecretKey='你的SecretKey'" >> ~/.zshrc
source ~/.zshrc
✅ 方案三:直接写在脚本 first2.sh 的最前面(测试方便)
把你的 export 命令直接写在 first2.sh 脚本的顶部(放在 acme.sh 命令之前)。这样只要执行脚本,变量就会被自动设置(仅对脚本内的命令生效)。
#!/bin/bash
export Tencent_SecretId="你的SecretId"
export Tencent_SecretKey="你的SecretKey"
# 下面接着你的 acme.sh 命令...
执行脚本证书更新
执行完毕后,查询下证书的更新时间即可。
报错处理
执行脚本报错:acme.sh: command not found
./scripts/first2.sh: line 6: acme.sh: command not found
编辑你的 shell 配置文件(~/.bashrc 或 ~/.zshrc),加入:
export PATH="$HOME/.acme.sh:$PATH"
然后执行:
source ~/.bashrc # 或 source ~/.zshrc
此后任何终端都能直接使用 acme.sh。
🎉🎉🎉


💬 评论区