运维 / CI·CD 2026年4月9日

无头租赁云 Mac 上的 iOS / macOS 公证:notarytoolstapler(2026)

MacXCode 技术团队 约 20 分钟阅读

香港、日本、韩国、新加坡、美国 租用的 裸金属 Apple Silicon 云 Mac 上,团队通常用 SSH 跑 CI/CD。若要把签过名的 macOS .app、命令行工具或 .dmg 在 App Store 之外分发,仍要走 Apple 的公证(Notarization)。本文给出 2026 可落地流程:用登录钥匙串保存 notarytool 凭据、非交互提交、保留 JSON 日志与 submission id、成功后 stapler staplestapler validate,以及在流水线里设硬门禁。可配合 远程 Archive 与导出远程签名优化仅 CLT 与完整 Xcode 一起阅读。

为什么在独立云 Mac 上做公证

  • 更接近 Apple API 路径:把构建机放在目标区域,可缩短提交与拉取日志的尾延迟。
  • 环境可复现:同一台 NVMe、同一 Xcode 补丁、同一套钥匙串布局,夜构建不会“因笔记本状态而漂移”。
  • 与开发机解耦:公证不跟 Zoom/Slack 抢 CPU,也不污染个人钥匙串。
原则:把公证当成普通 CI 步骤——固定 Xcode 版本归档 submission UUID + JSON 日志,若 stapler validate 失败则整 job 失败

无头环境常见痛点

  • 钥匙串弹窗不会出现:纯 SSH 无 GUI;需 security unlock-keychain 或使用已预授权 codesign/notarytool 的 专用 CI 用户
  • ZIP 结构错误:压扁 bundle、重复 MacOS、剥离扩展属性会导致日志里出现 “Invalid” 或难懂的签名错误。
  • 忘了装订:Apple 侧已 Accepted,但未对下载件执行 stapler staple新加坡/美国 用户仍可能遇到 Gatekeeper 告警。
  • 并行任务抢带宽:三条发布分支各丢 400 MB zip,1 Gbps 出口会被打满,看起来像 “Apple 挂了”。
  • 审计缺口:不保存 submission id 与 JSON,安全复盘无法对齐 2026-04-09 公证产物与对外发布物。

按产物类型选打包方式

macOS 分发不是 iOS TestFlight。为 .app / .dmg / .pkg 各写一条规则,避免值班同事在 港/日/韩 现场临时发明流程。

交付物 常见提交形态 装订对象 易错点
已签名 .app ditto -c -k --keepParent MyApp.app MyApp.zip 受理后的 bundle 目录 强化运行时与 entitlement 必须匹配 Developer ID 证书
.dmg 按工具链提交 DMG(或遵循 Apple 文档的容器流程) 用户实际挂载的 DMG 文件 卷内布局与内含 app 签名必须一致
扁平 .pkg productbuild 等安装包产物 磁盘上的 .pkg 组件包 ID / receipt 版本错误会直接变成工单量
容量与耗时(便于排期):中小型应用公证常见 2–8 分钟 墙钟(视队列),本地 NVMe 上装订+校验再加 30–90 秒。每条并行 lane 预留 5–15 GB 临时空间(zip、解压副本、日志)。在 M4 租赁机上 CPU 往往不是瓶颈,网络与磁盘尖峰才是。

云 Mac 前置条件

要求 说明
可用 notarytool 随新版 Xcode/CLT 提供;用 xcrun notarytool --version 自检
签名身份 Developer ID Application(macOS 分发)——与导出流水线一致
App Store Connect API Key Issuer ID、Key ID、.p8 —— 用钥匙串 profile 保存,勿明文进仓库
无人值守钥匙串 SSH 用户需加载登录钥匙串,或在受控密钥步骤执行 security unlock-keychain

为 notarytool 写入钥匙串配置

一次性(交互或安全引导)把凭据存成 profile,例如 ac-notary

xcrun notarytool store-credentials "ac-notary" --key ~/AuthKey_XXXXXX.p8 --issuer <issuer-uuid> --key-id <key-id>

建议在租赁机上使用专用 CI 用户,避免与人工 VNC 试验共用登录钥匙串。.p8 轮换周期与其他 ASC API Key 对齐。

提交 zip 并等待

压缩 .app(务必保留符号链接,常用 ditto -c -k --keepParent MyApp.app MyApp.zip):

xcrun notarytool submit MyApp.zip --keychain-profile "ac-notary" --wait

若在 CI 拆分等待与轮询,从 JSON 取 submission id,循环执行 xcrun notarytool log <id> --keychain-profile "ac-notary" 直到状态稳定,并把日志写入制品库。

解析建议:用 jq(或语言内置 JSON)断言每次绿构建都包含 idstatusmessage 摘要。Invalid 时日志常指向 zip 内具体路径——请保留原始 zip 与日志,便于和同一 Xcode 固定版本的“黄金包”做 diff。

限流:若出现 HTTP 429 或连续超时,可在单台上对公证阶段加互斥:例如 /tmp 文件锁,或每台 Mac 队列深度 1

装订与校验

Apple 受理成功后:

xcrun stapler staple MyApp.app

xcrun stapler validate MyApp.app

对磁盘映像请遵循当前 Apple 文档;务必以 validate 收尾,避免 新加坡/美国 用户侧 Gatekeeper 意外。

顺序:仅在 Apple 报告成功之后装订。若本地再次重签或重打包,必须重新提交——stapler 不能“修复”已漂移的签名。

常见失败与优先排查

现象 先查 常见修复
notarytool 报 Unable to authenticate profile 名称拼写;钥匙串是否解锁;CI 用户能否读 .p8 重跑 store-credentials;API Key 过期则轮换
日志提示二进制签名无效 zip 前对 app 做深度 codesign 验证;隔离属性(quarantine) 用正确 Developer ID 重新导出;用 ditto 打 zip,避免 Finder“压缩”
DMG 上 stapler validate 失败 是否装订错文件;装订时 DMG 仍挂载 卸载卷;对实际上传的 DMG 路径装订并再校验
轮询一直 In Progress 机器时钟漂移;出口防火墙拦截 Apple 端点 同步 NTP;放行 notary 相关域名/IP;退避上限建议 15 分钟

CI 门禁清单

  1. notarytool submit 非零退出则失败。
  2. 构建记录必须附带 submission id + 完整 JSON 日志(保留期 ≥ 合规要求)。
  3. 对即将发布的二进制执行 stapler validate,失败则失败。
  4. 在同一制品清单记录 Xcode build 字串notarytool 版本
  5. 上传 CDN/MDM 前对装订后产物做 shasum -a 256
  6. 可选:在干净切片上跑 spctl 评估,模拟终端用户环境。

常见问题(表格式)

问题 回答
这和 iOS App Store 上传是一回事吗? 不是——公证面向 Mac App Store 之外的 macOS 分发。iOS IPA 走不同路径;参见 Archive 实操
公证任务该选 1TB 还是 2TB? 大体积 .zip、日志、多份 Xcode 并存会吃满 NVMe;并行前扩容。见 套餐与节点
只要 CLT 还是要完整 Xcode? 新版 CLT 通常含 notarytool,但多数团队仍在同一台机做 Archive+导出——对比 CLT 与完整 Xcode
公证能否与 xcodebuild 同机? 可以,但应用工作区分隔 + 互斥,避免签名/打 zip 竞态;见 并行任务布局
不用 VNC 怎么排障? 先拉日志;确需 GUI 工具时短期开 VNC,再切回 SSH 自动化。

为何租赁 Mac mini M4 适合公证 CI

公证负载呈突发型:压缩数百 MB bundle、上传、轮询 API,再在快速盘上装订校验。Mac mini M4 提供原生 Apple Silicon 的 xcrun 行为、可预期的 NVMe 延迟,并可在 香港/日本/韩国/新加坡/美国 选址以贴合合规与 CDN 出口。按需租用避免一次性资本开支,同时保留与工位机一致的 SSH 与可选 VNC——适合 7×24 专线且不抢占笔记本登录钥匙串。

租用还便于镜像固定:每周同一 Xcode 与 notarytool 语义。Apple 调整策略时,先升一小撮节点验证绿构建,再全量推广。磁盘与节点规格见 定价;交互调试可偶尔用 VNC,生产仍以无头为主。

结语:只要把钥匙串与日志当作一等公民,无头租赁 Mac mini M4 就是按计划跑 notarytool + stapler 的合理位置。下一步:阅读 SSH 与部署帮助,或强化 并行构建隔离,避免公证与签名任务互相抢锁。

裸金属 Mac:公证 + Xcode

港 · 日 · 韩 · 新 · 美 · SSH / VNC