The archive builds, but GitHub Actions fails at signing or says it cannot find a certificate.
Check the Runner’s actual macOS account and its Keychain first; then verify the signing identity and matching provisioning profile. An SSH session that can sign does not prove the Runner process can.
iOS and macOS developers can use the checks below when local signing works but CI does not.
DevOps engineers can verify the account and execution context behind a self-hosted Mac Runner.
Release and credential administrators can separate certificate, private-key, Keychain, and profile issues without exposing signing assets unnecessarily.
[ SECTION_01 ] Start with the failing stage, not the certificate
“Xcode signing failed” describes a symptom, not a diagnosis. A failure can occur while Xcode resolves build settings, selects a signing identity, accesses a private key, matches a provisioning profile, or signs the archived product. Those stages have different owners and require different evidence.
Start with the failing Workflow run. Record the repository and commit, the job and Runner identifier, the scheme and target, the build action or command, and the first signing-related error in the log. Keep the surrounding build output: a later summary message may simply repeat an earlier failure.
Then compare the CI run with a local build of the same commit and signing target. If the local and CI builds use different schemes, configuration values, or export methods, the comparison cannot isolate a Runner problem. Xcode’s build settings reference is the authoritative place to check what a setting means; the build-and-run documentation explains how Xcode uses project configuration in its build workflow.
A useful handoff is a short evidence record: “Archive completed; signing identity resolution failed in the Runner job; local build of the same commit selected the expected identity.” That is more actionable than “the certificate is broken.”
Why does local signing work while GitHub Actions cannot find the certificate?
The two builds may be running under different macOS accounts. The local desktop session can see a login Keychain and its private key, while the Runner process may use another account or have a different Keychain search list. Compare the process context and the CI log before changing project signing settings.
[ SECTION_02 ] Developers own the project’s signing intent
The developer who owns the scheme and target should first establish what the project asks Xcode to sign. Inspect the scheme, target, build configuration, and archive or export command used in CI. Confirm that the workflow is building the intended application target, not a test target or another configuration with different signing values.
Pay particular attention to these build settings:
CODE_SIGN_STYLEindicates whether the project uses automatic or manual signing behavior.DEVELOPMENT_TEAMidentifies the team expected to sign the target.CODE_SIGN_IDENTITYspecifies the requested signing identity where applicable.PROVISIONING_PROFILE_SPECIFIERcan select a named profile in a manual-signing workflow.
These are project inputs, not proof that the Runner has the corresponding private key or profile. Check the resolved values in the build log and compare them with the project’s intended release configuration. Apple’s Xcode build settings reference documents the settings; use it to distinguish an unset or overridden value from a missing host credential.
Next compare the application identifiers and team information across the target, signing identity, and provisioning profile. A profile for a different app identifier or signing purpose is not repaired by unlocking another Keychain. Likewise, a valid certificate for the wrong team does not satisfy the project’s signing intent.
Why can a certificate identity exist while Xcode still fails to sign?
The identity listing alone does not establish that the relevant target can use the matching private key and profile. Check the selected identity, the account that owns the accessible Keychain, and the profile’s application identifier and team. Apple describes code-signing identities in its identity documentation and explains certificate structure in TN3161: Inside Code Signing Certificates.
The developer’s handoff to CI operations should state the expected scheme, configuration, team setting, application identifier, and signing method. Use placeholders such as <TEAM_ID> and <BUNDLE_ID> in shared tickets. Do not paste secrets or private-key material into logs.
[ SECTION_03 ] CI maintainers verify the Runner execution context
The CI maintainer owns the gap between an interactive test and the actual Workflow process. An SSH shell may belong to one account, while a Runner service starts under another. A desktop login may also have a different Keychain state from a background service. Treat those as separate environments until logs show they are the same.
Identify the account used by the Runner process, its service state, and the Runner identifier assigned to the failed job. If the Runner is managed as a service, inspect the service status and the Runner’s own diagnostic logs. GitHub’s self-hosted Runner troubleshooting guide documents the supported investigation path, and its Runner application configuration guidance covers Runner setup and service management.
Run Keychain and identity checks from the same execution context as the job whenever possible. An SSH check is useful only when it runs as the Runner account and reflects the same relevant Keychain configuration. Record the command output in a protected diagnostic log, but keep secrets, private keys, and credential contents out of Workflow output.
A maintainer can use macOS’s security utility to inspect the account’s signing identities and Keychain configuration. For example, security find-identity -v -p codesigning reports code-signing identities visible to that invocation. It does not prove that a particular Xcode target can complete signing; interpret it alongside the build log and profile selection. Where the actual job sees a different identity set from an interactive session, the discrepancy is evidence about the execution environment—not a reason to import the same certificate repeatedly.
How can the team tell which macOS account and Keychain GitHub Actions uses?
Check the process or service context and run diagnostics inside the Workflow under that context. Compare its account, visible identities, and Keychain list with the SSH or desktop test. GitHub’s Runner documentation provides the relevant service and log checks; do not infer the Runner account from the user who connected remotely.
A successful SSH signing test is only evidence for that SSH session. It becomes evidence for CI only after the account and Keychain context match the Runner job.
If the service account is unexpected, correct the Runner installation or service configuration through the documented process, then rerun a diagnostic job. Avoid solving an account mismatch by granting broad access to every user or making signing material generally available on a shared host.
[ SECTION_04 ] Signing administrators match the identity, private key, and profile
The signing administrator owns the credential set and its intended use. Begin by confirming that the required identity appears in the Runner account’s signing-identity check. Then establish that the identity is usable in that account’s context. A certificate file being present on disk is not equivalent to an accessible identity: signing also depends on its associated private key being available to the process.
Apple’s code-signing identity documentation helps distinguish identities from certificates alone. Its certificate technical note describes how certificates relate to signing. Use those distinctions when deciding whether the evidence points to a missing certificate, a missing or inaccessible private key, or an account/Keychain boundary.
Then inspect the profile selected for the target. Check that it matches the application identifier, team, and signing purpose expected for the build. For App Store distribution, Apple’s App Store provisioning profile instructions describe the profile creation context. A profile mismatch should be addressed as a profile or target-configuration issue, not mislabeled as a Keychain failure.
Before importing, renewing, or replacing signing material, record what is currently installed, which Workflow uses it, who approved the change, and how to restore the previous state. Keep the record free of secret values. If a credential change is necessary, test it in an appropriately restricted job before relying on it for production releases.
[ SECTION_05 ] Credential owners limit who can reach signing jobs
A release credential is only as protected as the workflows and people that can access it. The administrator responsible for repository and Runner permissions should identify which repositories can route jobs to the signing Runner, who can change those workflows, and which events can trigger jobs that receive signing credentials.
Do not expose production signing assets to untrusted pull-request code or unrelated jobs merely to make a signing error disappear. GitHub’s secure use guidance for Actions explains security risks around workflow inputs and untrusted code. Apply the smallest necessary access scope, constrain job routing to the intended Runner group or host, and keep credentials unavailable to jobs that do not sign release artifacts.
If the Runner is shared, determine whether other repositories or teams can execute code in the same environment. A dedicated signing node can make the boundary easier to reason about, but it still needs controlled access, maintenance, and a recovery plan. Record who authorized each permission change, what repositories and jobs it covers, and how to roll it back.
A permission change is not a signing fix unless the original evidence showed an access restriction was the cause. Otherwise, it increases exposure while leaving the project setting, account mismatch, or profile error unresolved.
[ SECTION_06 ] Release owners accept the actual signed archive
The release owner decides whether the repair is ready for production. A green Runner status means the process is available; a successful compile means code compiled. Neither proves that the intended release archive was signed with the correct identity and profile.
Verify the result using a clean Workflow run that exercises the real release target and export path. Review the build log for the selected signing settings and identity. Inspect the resulting archive or exported artifact using the project’s normal release checks, and confirm that the artifact corresponds to the intended commit and application identifier.
Keep the before-and-after evidence together: the original failure stage, the change made, the Runner account and Keychain context, the identity and profile selected, and the resulting archive validation. If another clean run cannot reproduce the successful result, do not treat the repair as accepted. First stabilize or isolate the signing execution context; then repeat the release validation.
[ SECTION_07 ] Use the evidence checklist before changing credentials
Use this checklist as a handoff between the development, CI, signing, and release owners. Each item should have an observable result, not just a statement that someone “checked it.”
- [ ] Record the failing Workflow run, commit, Runner identifier, target, scheme, and first signing-related log entry.
- [ ] Confirm that local and CI comparisons use the same commit, target, configuration, and intended release path.
- [ ] Capture the macOS account used by the Runner process; do not substitute the SSH login account without verification.
- [ ] Run identity and Keychain checks from the Runner job context, then compare them with any interactive test.
- [ ] Verify the resolved signing settings, including
CODE_SIGN_STYLE,DEVELOPMENT_TEAM,CODE_SIGN_IDENTITY, andPROVISIONING_PROFILE_SPECIFIERwhere used. - [ ] Confirm that the identity is usable with its private key and that the selected profile matches the target’s application identifier, team, and signing purpose.
- [ ] Review which repositories, workflows, and people can reach the signing job before changing permissions.
- [ ] Test the fix with a clean run that produces and validates the intended archive or export.
- [ ] Document the change owner, approval, affected scope, and rollback path without recording secret values.
The shortest path is not to re-import every certificate or broaden Keychain access. It is to identify the failing boundary, collect evidence from the process that actually runs the job, and hand each finding to the role that owns it.
[ SECTION_08 ] When a remote Mac is the better Runner boundary
A local or shared Mac can be the right choice when the team already maintains its hardware, controls physical access, and can keep its signing context stable. But that arrangement can also leave CI dependent on a particular office machine, make service-account drift harder to notice, and require the team to handle hardware availability and recovery itself. A Linux host cannot replace a real macOS environment for Xcode signing.
For intermittent release work or a team that needs a separately managed macOS execution environment, renting a remote Mac can avoid buying and operating another physical machine. NOVAKVM offers remote Mac access; review the available Mac options and choose a setup only after checking its access model against the team’s signing controls. A remote host is not automatically safer: the same account separation, restricted job routing, credential scope, and archive acceptance checks still apply.
A rented Mac may be a poor fit for continuous, predictable heavy use or workflows that require local physical-device connections. In those cases, a dedicated Mac owned and operated by the team may offer better control. When the need is temporary CI capacity or a testable signing environment, a remote Mac can be a practical alternative to an unavailable shared host or an immediate hardware purchase. For a stable macOS node, review the Mac mini access option, then validate it with a restricted diagnostic job before routing production signing work.