合者离之始
Record:006

阿里云 ESA Pages 部署实录

从 GitHub 私有仓库到自定义域名 HTTPS,把踩过的每一个坑按顺序记下来。

Posted2026-05-24Words1462Reading4 min

静态站点部署本来应该是最省心的环节,但域名、备案、证书三件事凑在一起,还是花了一整天。

一、为什么不用 GitHub Pages

对国内读者来说,github.io 的访问质量不稳定。自定义域名能解决 DNS 层面的问题,但源站仍然在境外,体验依旧取决于链路。

所以选了阿里云 ESA Pages:国内的边缘节点,并且我的域名备案接入商本来就是阿里云——这省掉了「接入备案」这一整个流程。

二、构建配置

仓库根目录放一个 esa.jsonc,它是唯一配置来源,会覆盖控制台设置:

{
  "name": "hzlzs",
  "installCommand": "npm install",
  "buildCommand": "npm run build",
  "assets": {
    "directory": "./dist",
    "notFoundStrategy": "404Page"
  }
}

notFoundStrategy 选 404Page 而不是 singlePageApplication——静态博客有真正的 404 页面,不该把所有未命中路径都返回 index.html。

三、域名接入的顺序

这里最容易绕晕。正确顺序是:

  1. 在 ESA 站点管理里添加站点(不是先建 Pages 项目)
  2. 按提示加一条 _esaauth 的 TXT 记录做归属验证
  3. 站点给一条 CNAME 接入域名,加到云解析
  4. 等站点状态变成「已启用」
  5. 最后回到 Pages 项目绑定域名

顺序错了会报 ActiveSiteNotExist,意思是「你绑定的域名还没有对应的已激活站点」。

四、证书这一关

平台自带的免费证书第一次签发时,边缘节点只下发了叶子证书,没有中间证书:

echo | openssl s_client -connect example.com:443 -servername example.com \
  2>/dev/null | grep -c "BEGIN CERTIFICATE"
# 1  ← 不完整

浏览器因此判定「不安全」——有些浏览器会自己去补拉中间证书,所以会出现「Chrome 正常、Edge 报错」的诡异现象。

解法是换成自定义证书,下载含链版本再上传:

# 期望输出 2 或更多
echo | openssl s_client -connect example.com:443 -servername example.com \
  2>/dev/null | grep -c "BEGIN CERTIFICATE"

上传后在站点的 HTTPS 配置里选中并启用,等 5-15 分钟边缘同步。

五、几个排查命令

# 看线上实际下发的证书
echo | openssl s_client -connect example.com:443 -servername example.com \
  2>/dev/null | openssl x509 -noout -issuer -dates
 
# 看 DNS 是否生效
dig +short example.com CNAME
 
# 看 HTTP 响应头
curl -sSI https://example.com | head -20

六、最后的清单

  • 生产分支要设成仓库实际分支(很多人仓库是 master,平台默认 main,结果 push 了不构建)
  • 私有仓库在仓库列表里默认不显示,要用搜索框搜
  • 强制 HTTPS 要在站点配置里开,否则 http:// 仍然可访问
  • 证书到期前记得续期:自定义证书一般 90 天

部署这件事没有技术含量,但每一步的顺序都不能错。把它写下来,下次换平台时能省一天。