Key takeaways
- Create a dedicated keychain file for CI, import distribution identities there, and unlock with a short-lived password from your secret store—never rely on the default login keychain across reboots.
- Sign with explicit
--keychain/CODE_SIGN_KEYCHAINand verifysecurity find-identity -v -p codesigningin the same shell context the build uses. - After
xcodebuildarchive/export, run notarytool submit → poll → stapler staple on the outer bundle or disk image users actually download; stapling an inner binary alone is a frequent miss. - Runner sizing and queue behavior overlap with hosted versus dedicated Mac decisions—see the linked Bitrise comparison when you plan parallel lanes.

codesign -dv, notary log excerpts, and ticket presence on the shipped artifact.1. Keychain boundaries on unattended hosts
Cloud Mac CI users are rarely at the console, so anything that assumes UI approval or login-session keychain defaults will flake after image refresh. Standardize on a file keychain (for example ~/Library/Keychains/ci-signing.keychain-db), import the Apple Distribution certificate and private key, set a known password, and unlock at job start with security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH". Set KEYCHAIN_PATH as the single source of truth and pass it to xcodebuild via OTHER_CODE_SIGN_FLAGS=--keychain "$KEYCHAIN_PATH" or the equivalent project setting. Avoid mixing Developer ID and Apple Distribution identities in the same chain unless your export options plist already encodes the correct team and profile. For a broader view of dedicated versus shared runners and queue tail latency, compare notes with 2026 Bitrise cloud iOS versus self-hosted cloud Mac runners: private CocoaPods, parallel workflows, per-minute burn versus queue P95—decision matrix and FAQ.
2. codesign layers: entitlements, hardened runtime, and nested bundles
Reproducible signing means the same entitlements plist and provisioning profile hashes every build. After export, run codesign --verify --deep --strict on the app bundle and, for helper tools inside PlugIns or Frameworks, confirm each nested target carries consistent team IDs and hardened-runtime flags. Mismatches often surface as errSecInternalComponent or errSecMissingEntitlement only at productbuild or notarytool time, long after the main app appeared to sign cleanly. When you package a .pkg, sign components bottom-up, then the package with the installer certificate documented in your runbook.
3. Notarization and stapler: strict ordering
Use notarytool with an App Store Connect API key (issuer, key ID, private key path) stored outside the repo—prefer environment-injected paths over committing .p8 files, and treat Transporter-only flows as legacy unless you have a hard vendor constraint. Submit the exact binary Gatekeeper will evaluate—typically the zip, app bundle, or notarized-ready .dmg—then wait for Accepted before stapling. Run xcrun stapler staple <path> and verify with stapler validate. If you staple before Apple returns success, or staple only an inner .app while shipping a recompressed outer archive, customers see different hashes than the notary service recorded. Keep API key rotation and submission IDs in change logs so you can correlate App Store Connect history with CI logs; when Apple rejects an upload, pull the JSON log with notarytool log <submission-id> and attach the first failing rule ID to your ticket.
4. Pipeline checklist (minimal)
- Unlock CI keychain; confirm identities via
security find-identity. - Clean derived data when diagnosing stale profiles; otherwise prefer incremental builds with locked dependency versions.
- Archive and export with a pinned
ExportOptions.plist; archive dSYM upload separately from notarization. - Submit to Apple; poll to
Accepted; staple; validate; publish checksums alongside artifacts.
Containerized build helpers on the same host still need correct volume mounts and disk headroom—pair this checklist with Production Docker on Apple Silicon cloud Mac: arm64/amd64 images, bind mounts & build cache troubleshooting handbook (with plan resource boundaries) when Docker and Xcode share one machine.
5. Symptom–cause–action (signing & notarization)
| Symptom / log snippet | Likely root cause | Preferred action |
|---|---|---|
errSecInternalComponent during sign |
Private key not usable in CI keychain; ACL or password mismatch | Re-import key+cert; unlock keychain in-job; pass explicit --keychain |
No signing certificate found |
Wrong keychain search list or missing provisioning profile | Set CODE_SIGN_KEYCHAIN; verify profile UUID in ~/Library/MobileDevice/Provisioning Profiles |
Notarization Invalid with hardened runtime |
Entitlement not allowed for distribution; unsigned nested helper | Diff entitlements against Apple docs; deep-verify nested bundles |
| Gatekeeper still quarantines after CI “success” | Stapler not run on shipped artifact; recompressed zip breaks ticket | Staple outermost deliverable; validate; avoid repackaging post-staple |
notarytool auth errors |
Wrong issuer / key ID; clock skew; revoked API key | Rotate key; sync time (NTP); store JSON key outside repo |
6. Closing
Treat signing, notarization, and stapling as one state machine: each step’s inputs are the previous step’s outputs. Document the keychain path, profile UUIDs, and notary submission IDs in the same runbook entry so the next on-call engineer does not guess which identity was live. After you stabilize the chain, run a cold start build on a fresh runner image to prove the process survives reboots and credential rotation.
Why cloud Mac mini fits signing-heavy CI
Apple Silicon gives you native arm64 toolchains without cross-emulation surprises, and unified memory keeps Xcode, simulators, and lightweight agents in one predictable pool. macOS integrates Gatekeeper, SIP, and FileVault-style protections that reduce tampering risk versus ad-hoc Windows build VMs, while idle power on M-series Mac mini hardware stays low for 24/7 runners. Dedicated cloud Macs avoid noisy-neighbor contention on signing throughput and disk I/O—exactly where shared SaaS queues sting—and the compact form factor keeps total cost of ownership sensible compared to refreshing fleets of laptops as ad-hoc CI.
If you want stable, Apple-native hardware for reproducible signing pipelines, kvmboot cloud Mac mini M4 is a practical starting point—see plans and pricing and align keychain layout with the tiers you provision.