部署目标¶
cert.deploy 步骤通过 target + config 选择部署目标。所有目标共享以下
语义:
- 原子写入:先写临时文件再替换,任何时刻目标路径要么是旧证书要么是新 证书,不存在写一半的中间态。
- 幂等:目标键(输入的稳定 SHA-256 摘要)+ 证书指纹一致且未
force→ 跳过文件写入,但重载命令仍执行。部署记录只在成功后写入(失败的部署 不算「已部署」,否则重试会被误判跳过)。 - 重载失败:非 0 退出码视为失败(错误携带命令、退出码与合并输出), 此时文件已写好。
local — 本地文件系统¶
| 字段 | 必需 | 默认 | 说明 |
|---|---|---|---|
cert_path |
是 | — | 证书链 PEM 目标路径 |
key_path |
是 | — | 私钥 PEM 目标路径 |
cert_mode |
否 | 0644 |
证书权限(八进制字符串) |
key_mode |
否 | 0600 |
私钥权限(比证书严) |
uid / gid |
否 | — | 文件属主;不填保持写入者所有(改他人所有需 root) |
reload_command |
否 | — | 写完后执行的重载命令,走 shell(sh -c) |
细节:
- 权限在创建时用
OpenOptions::mode设定,不留「先落盘后 chmod」的 umask 窗口;写后再set_mode一次覆盖历史改动。 - 临时文件与目标同目录(保证
rename原子性),失败时自动清理。 - 非 Unix 平台不支持设置属主(报
uid字段错)。
ssh — SSH 远程主机¶
连接方式两种可混用:直接填(认证材料经 credential_id 引用 SSH 私钥/口令
凭据)或引用 SSH 主机档案(顶层 credential_id 指向 ssh 类型凭据)。
合并优先级:输入显式值 > 主机档案值 > 系统缺省(端口 22、证书 0644、 私钥 0600)。空白输入值不算显式,回退档案。合并后必填缺失报错并指出缺哪个 字段,绝不带半个配置去连主机。
| 字段 | 来源 | 说明 |
|---|---|---|
credential_id |
输入 | 引用 ssh 类型主机档案 |
host / port / user |
输入或档案 | 连接参数 |
auth |
输入或档案 | {"kind": "private_key", "credential_id": N} 或 {"kind": "password", "credential_id": N} |
cert_path / key_path |
仅输入 | 远端目标路径(档案不含路径——一份档案可服务多条流水线) |
cert_mode / key_mode |
输入或档案 | 文件权限 |
reload_command |
仅输入 | 远端重载命令 |
细节:
- 远端写入与本地同构:临时文件 +
mv原子替换;证书内容经 stdin 灌进cat(不进命令行参数,避免出现在进程列表);脚本set -e+trap ... EXIT保证失败清理。 - 私钥支持 OpenSSH 与 PEM 格式。
- ⚠️ 主机密钥未接入 known_hosts:接受任何主机密钥,每次连接记 warn 并 打出 SHA-256 指纹。有中间人风险的环境请配合网络层隔离使用。
- 凭据的「连通性测试」对
ssh类型是真实探测(10 秒超时)。
部署记录¶
每次部署(含跳过写入的)成功后落一条记录:目标键、指纹、是否跳过写入、
路径清单、重载输出、时间。用于幂等判断与历史回溯(库表
acmecast_deployment,按时间倒序可查)。
示例¶
{
"target": "ssh",
"config": {
"credential_id": 5,
"cert_path": "/etc/nginx/ssl/example.com.crt",
"key_path": "/etc/nginx/ssl/example.com.key",
"reload_command": "systemctl reload nginx"
}
}
credential_id: 5 是 ssh 类型主机档案;路径与重载命令随部署输入给出。