iOS code signing without a Mac
Understand Apple distribution certificates, provisioning profiles, bundle IDs, and API keys, and set up signing on a cloud Mac without owning one.
· 9 min read
Need a Mac for this? NoMac gives your agent full macOS with Xcode for $0.80 an hour, billed per minute. Start now →
You can sign an iOS app without owning a Mac, but signing still has to happen in an Apple build environment. A cloud Mac can hold the distribution identity, provision the app, sign the archive, and send it to TestFlight while your project remains on Windows or Linux.
The safest workflow does not copy certificate files between personal machines or paste an Apple private key into an AI prompt. Connect the Apple account once, keep the App Store Connect key on the server, and let the coding agent sign on the Mac with tools that never hand it the raw key.
An App Store Connect API key does not itself sign the app. It authenticates App Store Connect operations. The distribution certificate and provisioning profile establish the cryptographic signing identity and the app's permitted capabilities.
The five pieces of iOS signing
| Piece | What it proves | Typical mistake |
|---|---|---|
| Bundle ID / App ID | Which app this binary represents | Project and App Store record differ |
| Distribution certificate | A known Apple developer team signed it | Expired, revoked, or wrong team |
| Certificate private key | The signer controls that certificate | Missing from the signing environment |
| Provisioning profile | App ID, certificate, and permitted services agree | Stale after capability changes |
| Entitlements | Capabilities requested by the built app | Not enabled for the App ID or profile |
Apple's certificate overview explains that Apple Distribution certificates are used for testing distribution and App Store submission. Apple's provisioning guide explains that an App Store Connect profile contains an explicit App ID and a distribution certificate.
Why signing feels harder without a Mac
Xcode normally hides much of this behind “Automatically manage signing.” It talks to the developer account, creates or refreshes profiles, stores private keys in the macOS keychain, and selects a matching identity during archive.
On Windows or Linux, manually reproducing that state means managing certificate requests, private keys, exports, profiles, entitlements, upload tools, and rotations across two operating systems. It is possible to assemble, but it creates more secret-handling and more ways for a profile to stop matching the project.
The easier model: sign on a cloud Mac
| You own | NoMac and the Mac handle |
|---|---|
| Apple Developer membership and account policy | A macOS VM per session, deleted at stop |
| App record and the capabilities the app needs | Bundle ID registration, profiles, and the certificate in a keychain |
| Truthful privacy and compliance answers | The TestFlight upload and processing status |
| Approval of the release | Exact build commands and the next build number |
In NoMac, you connect an App Store Connect team key once at nomac.app/apple. The key stays on NoMac's server; it never reaches the Mac or the chat. On the Mac, the agent calls set_up_signing (CLI: nomac sign). It reads the project and its extensions, registers missing bundle IDs, switches on capabilities, makes the App Store profiles, and installs them with the account's distribution certificate in a keychain. It returns a build settings file, export options, and the exact xcodebuild commands. The project itself is not changed.
One-time setup
1. Create the app identity
Choose a stable reverse-domain bundle identifier such as com.company.product. Use exactly the same value in the Xcode project, App ID, and App Store Connect app record. Do not change it to fix an unrelated build error.
2. Enable only required capabilities
Push notifications, Sign in with Apple, associated domains, iCloud, App Groups, HealthKit, and other services affect entitlements and provisioning. Enable a capability intentionally in the project. set_up_signing switches on what Apple's API allows for the App ID; an App Group or iCloud container comes back as a step for a person, with a link. Remove unused entitlements rather than provisioning powers the app does not need.
3. Connect App Store Connect
Create an API key with the narrowest role that can perform the release workflow. Download the .p8 file once and connect it at nomac.app/apple. Never commit it. Read the API key guide for issuer ID, key ID, role selection, and rotation.
4. Authenticate the development machine
npm install -g @nomac/cli nomac login
This gives the local CLI or agent a NoMac credential. It does not place the Apple private key in the repository or prompt.
Build and sign from Windows or Linux
First start a Mac, put the complete project in ~/drive/src, and build it for the Simulator without signing. That compile check needs no Apple account, and it keeps source mistakes out of signed attempts.
When it passes, run set_up_signing, then archive and export with the commands it returns. send_to_testflight (CLI: nomac testflight) sends the signed .ipa: NoMac creates the upload at Apple for the matching App Store Connect record, and the Mac sends only the file.
Inspect the bundle ID, team, entitlements, and deployment target. Start a NoMac Mac, sync the current project and build it for the Simulator. If it passes, stop for approval. After approval, run set_up_signing, archive and export with the commands it returns, send the .ipa to TestFlight, and report the signing identity, app record, build number, upload state, and any warning, without exposing secrets.
How to read common signing failures
| Failure | Meaning | Check first |
|---|---|---|
| No profiles found | No profile matches the target identity and type | Bundle ID, team, distribution method |
| Profile does not include certificate | Certificate and profile were created from different signing state | Regenerate or select matching assets |
| Entitlement is not supported | Project asks for a capability the App ID/profile does not grant | Capability configuration |
| Certificate expired or revoked | Signing identity is no longer valid | Connection health and certificate rotation |
| App record not found | Bundle ID has no matching App Store Connect record | Create/select the exact record |
| Build number already used | Apple requires a unique increasing build value | Increment the build number |
Use the deeper iOS code-signing error guide when the build already has a diagnostic. Fix the identity layer that failed; do not regenerate every certificate or change the bundle ID as a first response.
Signing security rules
- ·Never commit
.p8,.p12, certificate private keys, or passwords. - ·Do not paste credentials into a model conversation or build log.
- ·Use separate, scoped service credentials and revoke unused keys.
- ·Limit who can create distribution certificates and authorize submissions.
- ·Monitor expiration and connection health before a deadline release.
- ·Keep the final App Store submission behind explicit human confirmation.
Certificate rotation should be deliberate. Revoking a working team certificate can break other build systems using it. Confirm which pipeline owns an asset before changing shared Apple account state.
Development signing versus distribution signing
A local Xcode device build normally uses an Apple Development certificate and a profile that includes the test device. TestFlight and App Store uploads use distribution signing and do not require you to register every tester's device. TestFlight is therefore the practical real-device path for a developer who has no local Mac.
Internal TestFlight distribution still requires an Apple Developer membership, correct app record, signed upload, and eligible tester. It skips the USB pairing and per-device development profile that a local Xcode install would manage.
From a signed build to the store
Signing proves identity and integrity; it does not prove App Review readiness. Install the processed TestFlight build, test it, run review_lint on the App Store record, prepare accurate screenshots and metadata, and answer privacy and compliance questions. Then stage it with publish and approve submission.
Follow the easiest 2026 publishing guide for the complete sequence. Signing on a cloud Mac removes certificate handling from your Windows or Linux machine without removing your ownership of the release.