
用 GitHub Actions + 动态密码部署构建产物
前提是服务端已经按 用时间戳 + HMAC 给 rsync 生成一次性密码 配置好了每 5 分钟轮换的 rsyncd.secrets。这篇只讲 CI 这一侧
Secrets
不存放密码,存放生成密码的命令。三个 Secrets:
RSYNC_ADDRESS:user@host::moduleRSYNC_PORT:873RSYNC_PASSWORD_COMMAND:
echo -n "deploy_user" | openssl dgst -sha256 -hmac "deploy_user$(( $(date -u +%s) / 300 * 300 ))SALT" | awk '{print $2}'
密钥格式和服务端脚本一致:用户名 + 窗口时间戳 + 盐。命令本身就算泄露,算出来的密码也只在当前 5 分钟内有效
生成密码文件
- name: Generate Rsync Password
run: |
set +x
PASSWORD=$(eval "${{ secrets.RSYNC_PASSWORD_COMMAND }}")
echo "$PASSWORD" > /tmp/rsync.password
chmod 600 /tmp/rsync.password
set +x 关闭命令回显,避免密钥被输出到日志
上传
用 nick-fields/retry 包装上传步骤。上传如果正好跨过 5 分钟边界会认证失败,重试前重新生成一次密码:
- name: Deploy to Server
uses: nick-fields/retry@v3
with:
max_attempts: 3
timeout_minutes: 5
command: |
rsync -avz --password-file=/tmp/rsync.password ./dist/ ${{ secrets.RSYNC_ADDRESS }} \
--delete --port=${{ secrets.RSYNC_PORT }} 2>&1 | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/[REDACTED-IP]/g'
on_retry_command: |
rm -f /tmp/rsync.password
set +x
PASSWORD=$(eval "${{ secrets.RSYNC_PASSWORD_COMMAND }}")
echo "$PASSWORD" > /tmp/rsync.password
chmod 600 /tmp/rsync.password
末尾那段 sed 把 rsync 输出里的 IPv4 地址替换掉,公开仓库的 Actions 日志谁都能看
清理
- name: Cleanup Password File
if: always()
run: rm -f /tmp/rsync.password
if: always() 保证上传失败时也会删除
效果
- 仓库和 CI 里没有任何长期有效的凭证
- 密码只在当前构建的几分钟内有效,重放无效
- 服务端不需要额外开启认证服务,rsyncd 原生的密码认证就足够
配合 commit message 触发发布的做法见 用 commit message 触发 GitHub Actions 自动发版
评论
评论加载中…