#Git #Cloudflare #acme.sh #部署

背景

博客采用如下部署架构:

1
2
3
4
5
6
本地 Mac ──git push──▶ 内网服务器 (hexo.git bare repo)
│ post-receive hook
├─ hexo generate
└─ rsync ──▶ 公网服务器

Nginx 对外提供服务

将域名 DNS 从阿里云迁移到 Cloudflare 后,连锁触发了三个问题:SSL 续签失败、git push 超时、hexo hook 不触发。以下记录完整排查过程。


一、SSL 续签失败

现象

1
2
3
[ERROR] Le_OrderFinalize
[ERROR] error code: 3
[ERROR] Signing failed. Finalize code was not 200.

原因

libcurl 错误码 3 为 CURLE_URL_MALFORMATacme.sh 缓存的 ACME 订单状态中 Le_OrderFinalize URL 损坏,通常在续签中断或订单状态不一致时出现。

解决

1
2
3
4
5
6
7
# 删除损坏的缓存,强制重新发起
rm -rf ~/.acme.sh/<domain>_ecc/

# 手动 DNS 模式重新签发
~/.acme.sh/acme.sh --issue --dns \
-d "<domain>" \
--yes-I-know-dns-manual-mode-enough-go-ahead-please

在 DNS 控制台添加 _acme-challenge TXT 记录,等待解析生效后:

1
2
3
4
5
6
7
~/.acme.sh/acme.sh --renew -d "<domain>" \
--yes-I-know-dns-manual-mode-enough-go-ahead-please

~/.acme.sh/acme.sh --install-cert -d "<domain>" --ecc \
--key-file /etc/nginx/ssl/.../cert.key \
--fullchain-file /etc/nginx/ssl/.../cert.pem \
--reloadcmd "systemctl reload nginx"

二、迁移到 Cloudflare 后 git push 超时

现象

1
2
ssh: connect to host <domain> port 6002: Operation timed out
fatal: Could not read from remote repository.

排查

1
2
ping -c 3 <domain>
# PING <domain> (104.21.56.64)

根本原因104.21.56.64 是 Cloudflare 的代理 IP。DNS 迁移后域名 A 记录默认开启橙云(Proxied),Cloudflare 只代理 HTTP/HTTPS 流量,SSH 端口被拦截,push 无法到达内网服务器。

解决方案

方案一(推荐):git remote 直接使用服务器真实 IP,彻底绕过 CF 代理:

1
git remote set-url deploy ssh://user@<真实IP>:<port>/~/hexo.git

方案二:CF 控制台将 A 记录改为 DNS Only(灰云),域名直接解析到真实 IP。

CF 橙云适合 HTTP/HTTPS 流量加速与防护,SSH / 自定义端口 Git 部署必须用灰云或直连 IP。


三、post-receive hook 不触发

现象

push 命令显示超时失败,服务器上博客未更新,以为是 hook 失效。

实际原因

Push 根本没有到达服务器(被 CF 拦截),hook 从未被调用。fix git remote 后 push 恢复正常,hook 触发正常。

hook 的条件触发逻辑

现有 post-receive 脚本只在特定文件变更时才执行 hexo generate

1
2
3
4
5
6
CHANGED_FILES=$(git diff --name-only HEAD^ HEAD)

if echo "$CHANGED_FILES" | grep -E "(_config\.yml|theme/|_posts/|source/.*\.md)"; then
npx hexo generate
fi
# 无论是否重建,rsync 都会执行

:若 push 的提交只改了 server/README 等非内容文件,hexo 不会重建,新文章不会部署。调试时注意区分"hook 未触发"和"hexo generate 被跳过"。


四、sudo 下 $HOME 路径错误

sudo bash script.sh 运行脚本时,$HOME 解析为调用用户的家目录(如 /home/username),而非 /root,导致 acme.sh 路径、account.conf 写入全部指向错误位置。

修复:脚本中所有 acme.sh 相关路径硬编码为 /root/.acme.sh/,不使用 $HOME~


五、清理 git 历史中的敏感文件

误将包含配置脚本的目录提交进了 git 历史,需要从所有提交中彻底删除。

工具:git-filter-repo

1
2
3
4
pip3 install git-filter-repo

# 从所有历史提交中删除指定路径
git filter-repo --path server/ --path temp.sh --invert-paths --force

之后需要强制推送

1
2
git push deploy master --force
git push origin master --force

git filter-repo 会重写全部提交的哈希值,force push 后所有已克隆的副本都会与新历史diverge,需要重新 clone 或 reset。


总结

问题 根本原因 解决
SSL 续签失败 acme.sh 订单缓存损坏 删除 _ecc/ 目录重新签发
git push 超时 CF 橙云拦截 SSH 端口 remote 改用真实 IP
hook 不触发 push 未到达服务器 同上
hexo 不重建 hook 条件判断跳过 检查变更文件是否匹配触发模式
$HOME 路径错误 sudo 不切换 HOME 脚本内硬编码 /root/
历史含敏感文件 误 git add git-filter-repo + force push