acme.sh 本身不直接支持阿里云 OSS 备份,但可以通过自定义 deploy hook 脚本实现证书续签后自动上传到 OSS,适合需要异地备份证书的场景。
先说结论:acme.sh 的证书默认存储在服务器本地 ~/.acme.sh/ 目录,要实现 OSS 备份需要自行编写部署脚本,在证书更新完成后触发上传。
- 适合:有多台服务器需要统一证书备份、或希望证书文件异地存储的场景
- 核心:利用 acme.sh 的
`--deploy-hook`参数调用自定义脚本 - 建议:先确保本地证书续签正常,再添加 OSS 备份逻辑,脚本执行失败不应影响续签流程
环境准备
在编写脚本前,需要在服务器上安装阿里云 OSS 命令行工具 ossutil,并配置好访问凭证。
1. 安装 ossutil
wget https://gosspublic.alicdn.com/ossutil/1.7.13/ossutil64 -O /usr/bin/ossutil64 chmod +x /usr/bin/ossutil64
2. 配置凭证(建议使用子账户)
不要在脚本中硬编码密钥,建议在系统环境变量中配置,或运行一次 config 命令。
ossutil64 config -e oss-cn-hangzhou.aliyuncs.com -i LTAI5t... -k Secret...
注意:为了安全,建议创建阿里云 RAM 子账户,仅授予 oss:PutObject 权限,避免使用主账户 AccessKey。
编写部署脚本
在 ~/.acme.sh/deploy/ 目录下创建 deploy_oss.sh 脚本。acme.sh 在执行 deploy hook 时会传入证书路径等环境变量,脚本需读取这些变量并执行上传。
#!/bin/bash
# ~/.acme.sh/deploy/deploy_oss.sh
# acme.sh 传入的环境变量
DOMAIN="${CERT_DOMAIN}"
CERT_PATH="${CERT_PATH}"
KEY_PATH="${KEY_PATH}"
FULLCHAIN_PATH="${FULLCHAIN_PATH}"
# OSS 配置(根据实际修改)
OSS_ENDPOINT="oss-cn-hangzhou.aliyuncs.com"
OSS_BUCKET="your-backup-bucket"
OSS_PREFIX="ssl-certs/${DOMAIN}"
# 检查 ossutil 是否存在
if ! command -v ossutil64 > /dev/null 2>&1; then
echo "[Error] ossutil64 not found" >&2
exit 0
fi
# 上传证书文件
ossutil64 cp "${CERT_PATH}" "oss://${OSS_BUCKET}/${OSS_PREFIX}/cert.pem" -f -e "${OSS_ENDPOINT}" > /dev/null
ossutil64 cp "${KEY_PATH}" "oss://${OSS_BUCKET}/${OSS_PREFIX}/key.pem" -f -e "${OSS_ENDPOINT}" > /dev/null
ossutil64 cp "${FULLCHAIN_PATH}" "oss://${OSS_BUCKET}/${OSS_PREFIX}/fullchain.pem" -f -e "${OSS_ENDPOINT}" > /dev/null
if [ $? -ne 0 ]; then
echo "[Warn] OSS backup failed for ${DOMAIN}, but renewal continues" >&2
fi
# 关键:无论上传成功与否,都返回 0,避免阻断证书续签
exit 0赋予脚本执行权限:
chmod +x ~/.acme.sh/deploy/deploy_oss.sh
配置 acme.sh 对接
确认证书签发或安装时指定 deploy hook。如果是已有证书,可重新执行 installcert 命令关联脚本:
acme.sh `--installcert` -d yourdomain.com \ `--key-file` /etc/nginx/ssl/key.pem \ `--fullchain-file` /etc/nginx/ssl/cert.pem \ `--reloadcmd` "service nginx force-reload" \ `--deploy-hook` ~/.acme.sh/deploy/deploy_oss.sh
如果是新签发证书,直接在 issue 命令后加上 `--deploy-hook` 参数即可。配置完成后,acme.sh 会在每次续签成功后自动调用该脚本。
验证方法
1. 手动测试脚本
在不触发续签的情况下,手动执行脚本测试 OSS 连通性:
~/.acme.sh/deploy/deploy_oss.sh
检查 OSS 控制台是否生成文件。如果报错,检查 ossutil 配置及网络连通性。
2. 强制续签测试
acme.sh `--renew` -d yourdomain.com `--force`
观察输出日志中是否有 deploy hook 执行记录,并检查 ~/.acme.sh/acme.sh.log 确认无报错。
3. 验证 OSS 文件
登录阿里云 OSS 控制台,查看备份目录下的文件时间戳是否与本地 ~/.acme.sh/yourdomain.com/ 下的证书一致。
常见坑与排查
1. 脚本导致续签失败
acme.sh 默认认为 deploy hook 返回非零值即部署失败。对于备份类脚本,务必在脚本末尾使用 exit 0,确保即使 OSS 上传失败也不会影响证书续签。
2. 密钥泄露风险
严禁将 AccessKey 和 Secret 明文写在脚本中。推荐使用阿里云 RAM 角色(如果是 ECS)或系统环境变量。若使用 ossutil config,配置文件 ~/.ossutilconfig 权限应设置为 600。
chmod 600 ~/.ossutilconfig
3. 权限不足
如果上传报错 AccessDenied,检查 RAM 子账户权限策略。最小权限建议如下:
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": "oss:PutObject",
"Resource": "acs:oss:*:*:your-bucket-name/*"
}
]
}4. 路径变量差异
不同版本的 acme.sh 传入的环境变量名可能略有差异,建议在脚本开头添加 env > /tmp/acme_env.log 调试,确认证书路径变量名是 CERT_PATH 还是其他。