容器与平台

Heroku 自动证书管理(ACM)配置教程

作者: · 最后核实

Heroku 的 Automated Certificate Management(ACM,自动证书管理)会为应用的自定义域名申请并续期 Let's Encrypt 证书,所有应用免费使用。做法是:逐个添加域名,把 DNS 指向 Heroku 给出的 herokudns.com 目标地址,ACM 就会签发证书,一般 45 到 60 分钟。证书在到期前一个月自动续期。如果改为上传自己的证书,这个应用的 ACM 会被关闭。

步骤和命令以 Heroku Dev Center 文档为准(截至 2026 年 11 月)。应用名 example-app 和域名 example.com 是示例。

速查表

问题 Heroku 的做法
自动证书的 CA Let's Encrypt(通过 ACM)
费用 所有应用免费包含
子域名 www.example.com CNAME 指向它自己的 <随机名>.herokudns.com
根域名 example.com ALIAS/ANAME/拉平的 CNAME 指向目标地址;不支持 A 记录
CAA 要放行 letsencrypt.org
ACM 通配符 通用运行时(Common Runtime)文档未提及;Private Space 规则见下文
上传自有证书 支持,heroku certs:add(会关闭 ACM)
续期 自动,到期前一个月
TLS 版本 只支持 TLS 1.2 和 TLS 1.3

国内访问说明

Heroku 的运行区域在境外,从中国大陆访问的速度和稳定性没有保证,这和证书配置无关。面向国内用户的业务、需要 ICP 备案的网站,建议放在阿里云、腾讯云等国内云上,证书参考 阿里云 SSL 证书 或 腾讯云 SSL 证书。

第一步:添加域名

根域名和 www 要分别添加,Heroku 规定根域名必须在子域名之外单独加:

heroku domains:add www.example.com -a example-app
heroku domains:add example.com -a example-app
heroku domains -a example-app

每个域名都有自己的 DNS 目标地址,例如 whispering-willow-5678.herokudns.com。添加域名不收费,但 Heroku 账户必须先完成验证。

第二步:把 DNS 指向目标地址

每个域名都指向 Heroku 为它分配的 herokudns.com 目标地址,根域名不能用 A 记录:

名字 类型 记录值
www.example.com CNAME whispering-willow-5678.herokudns.com
example.com ALIAS、ANAME 或拉平的 CNAME hidden-sierra-7936.herokudns.com

Heroku 明确说根域名只用 A 记录是不够的,因为它的 IP 地址是动态变化的。支持 ALIAS 或 ANAME 的服务商有 DNSimple、DNS Made Easy、easyDNS、Namecheap、DreamHost 等,Cloudflare 会在根域名上自动拉平 CNAME。如果你的 DNS 服务商在根域名上只能加 A 记录,就把 DNS 换到支持这些记录类型的服务商。

老应用的记录可能还指向 example-app.herokuapp.com 或 *.herokussl.com,ACM 无法验证这种配置,要改成 herokudns.com 的目标地址。另外不要加 AAAA 记录,ACM 不支持 IPv6。

第三步:检查 CAA 记录

域名设了 CAA 的话,加一条放行 Let's Encrypt:

example.com.  3600  IN  CAA  0 issue "letsencrypt.org"

否则 ACM 会失败,原因显示为 CAA record prevents issuance, CAA record does not match issuer。如果 DNS 服务商不支持 CAA,还可能出现 DNS provider doesn't support CAA。可以用 CAA 检测工具 确认。

第四步:启用 ACM 并查看状态

heroku certs:auto:enable 开启 ACM,heroku certs:auto 查看每个域名的签发状态:

heroku certs:auto:enable -a example-app
heroku certs:auto -a example-app

生成证书一般要 45 到 60 分钟,状态含义如下:

状态 含义
Cert Issued 证书已签发。
In Progress 正在验证域名的 DNS。
DNS Verified DNS 已验证,正在生成证书,还没结束。
Waiting 正在排队等待处理。
Failing 无法验证 DNS,会继续重试最多一小时。
Failed 无法验证 DNS,已停止重试。

通配符和自有证书

通配符域名可以加到应用上,DNS 用 * 的 CNAME 指向它的目标地址。但 Heroku 的 ACM 文档并没有说 ACM 会在通用运行时里签发通配符证书。关于 Private Space,文档说要自行上传通配符证书,Cedar 代的 Private Space 应用用 ACM 时不能使用通配符域名,而新一代的 Private Space 应用可以。

要用 EV 证书、别家 CA 的证书或通配符证书,就上传:

heroku certs:add server.crt server.key -a example-app
heroku certs -a example-app

server.crt 里要包含中间证书。上传后 ACM 自动关闭,以后想回到 ACM,运行 heroku certs:auto:enable。Heroku 不允许导出私钥,自己要留好备份。Private Space 应用想让通配符证书自动续期,Heroku 推荐 SSL FastTrack、ExpeditedSSL 这类插件。

从手动证书切换到 ACM

ACM 和 Heroku SSL(SNI)用的是同一套 DNS 配置,Private Space 应用启用 ACM 也不需要改 DNS。验证 DNS 期间,应用会继续使用你原来上传的证书,自定义域名一直可以访问。Heroku 文档针对 Private Space 应用给出的切换顺序是:

  1. 用 heroku certs 找到手动上传的证书名称;
  2. 运行 heroku certs:auto:enable 启用 ACM;
  3. 用 watch heroku certs:auto 盯着,等新证书签发完成,这一步没完成就动手删旧证书,应用可能会停机;
  4. 最后用 heroku certs:remove --name 证书名称 删除手动上传的证书。

顺序不要颠倒:先删旧证书再等 ACM,中间这段时间域名上就没有可用的证书了。

验证

证书签发后,自定义域名返回 Let's Encrypt 签发的证书。用 SSL 证书检查 检查,或运行:

curl ssl.sh/example.com

查看证书内容:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject -ext subjectAltName -dates

在 macOS 上做这项检查时不要用 curl -k:Heroku 提到很多版本的 macOS 上带 -k 的 curl 不发送 SNI。

自动续期

ACM 在证书到期前一个月续期,添加或删除自定义域名时也会自动生成新证书。如果 ACM 一直签不出证书,尝试三天后 Heroku 会发通知。上传的证书 Heroku 不会续期,要用 heroku certs:update 自己替换。Let's Encrypt 从 2025 年 6 月 4 日起不再发到期提醒邮件,默认有效期 2027 年 2 月 10 日起变成 64 天,关键域名建议加到 ssl.sh 监控(开发中)。

常见失败原因

不要为了加快速度反复关闭再开启 ACM,可能触发 Let's Encrypt 频率限制。先排除原因,再运行:

heroku certs:auto:refresh -a example-app

Heroku 文档列出的失败原因:

  • CN exceeding 64 character limit:域名超过 64 个字符。
  • Incorrect DNS settings:记录配错、域名 DNSSEC 验证失败,或 Private Space 应用没有运行中的 web dyno。
  • Unable to resolve DNS for domain:记录还没生效,ACM 用 Google Public DNS(8.8.8.8)检查。
  • CDN not returning HTTP challenge:域名指向了 CloudFront 等 CDN,验证文件返回 404。
  • DNS redirect not forwarding path:DNS 服务商的转发功能丢掉了验证文件的路径。
  • Incorrect CNAME target:CNAME 指向了 <app-name>-<random-identifier>.herokuapp.com,而不是 DNS 目标地址。
  • Rate limited:7 天内为这些域名申请证书次数太多,等限制解除后再 refresh,见 Let's Encrypt 频率限制。
  • DNS provider timed out:DNS 服务商超时,refresh 重试。
  • Strict TLS in CDN not supported:前面套了 Cloudflare 但配置不对;Heroku 不建议 ACM 和 Cloudflare 一起用,可以关掉 ACM。
  • DNS provider doesn't support CAA、CAA record prevents issuance, CAA record does not match issuer:见第三步和 CAA 记录阻止签发。
  • Domain record does not exist:Let's Encrypt 查到 NXDOMAIN,检查域名拼写和 CNAME。
  • Domain considered unsafe:域名被 Google 安全浏览标记为不安全。
  • Let's Encrypt domain blocklist:域名在 Let's Encrypt 的屏蔽名单上,去 Let's Encrypt 社区论坛求助。

常见问题

Heroku ACM 要额外收费吗?

不收。Heroku 文档写明所有应用都免费包含 ACM。它使用 Let's Encrypt 证书,并在到期前一个月自动续期。

为什么 Heroku 的根域名不能用 A 记录?

Heroku 使用动态 IP,A 记录指向的固定 IP 随时可能失效。要用 ALIAS、ANAME 或拉平的 CNAME,把根域名指向 heroku domains 显示的 herokudns.com 目标地址。DNS 服务商不支持这几种记录的,需要换一家。

ACM 能签通配符证书吗?

文档没有说 ACM 会签通配符证书。Heroku 的 ACM 文档要求 Private Space 应用自行上传通配符证书,并说明 Cedar 代的 Private Space 应用用 ACM 时不能使用通配符域名,而新一代的可以。其他情况下要通配符 HTTPS,就准备上传自己的通配符证书,这会关闭该应用的 ACM。

证书卡住了,能关掉 ACM 再打开吗?

不要这样做。Heroku 提醒反复开关 ACM 可能触发 Let's Encrypt 频率限制,Heroku 支持也无法绕过。先修好 DNS,再运行 heroku certs:auto:refresh。

资料来源

  1. Heroku Dev Center: Automated Certificate Management
  2. Heroku Dev Center: Custom Domain Names for Apps
  3. Heroku Dev Center: Heroku SSL
  4. Let's Encrypt: Certificate Authority Authorization (CAA)