← Blog

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

PieceWhat it provesTypical mistake
Bundle ID / App IDWhich app this binary representsProject and App Store record differ
Distribution certificateA known Apple developer team signed itExpired, revoked, or wrong team
Certificate private keyThe signer controls that certificateMissing from the signing environment
Provisioning profileApp ID, certificate, and permitted services agreeStale after capability changes
EntitlementsCapabilities requested by the built appNot 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 ownNoMac and the Mac handle
Apple Developer membership and account policyA macOS VM per session, deleted at stop
App record and the capabilities the app needsBundle ID registration, profiles, and the certificate in a keychain
Truthful privacy and compliance answersThe TestFlight upload and processing status
Approval of the releaseExact 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

FailureMeaningCheck first
No profiles foundNo profile matches the target identity and typeBundle ID, team, distribution method
Profile does not include certificateCertificate and profile were created from different signing stateRegenerate or select matching assets
Entitlement is not supportedProject asks for a capability the App ID/profile does not grantCapability configuration
Certificate expired or revokedSigning identity is no longer validConnection health and certificate rotation
App record not foundBundle ID has no matching App Store Connect recordCreate/select the exact record
Build number already usedApple requires a unique increasing build valueIncrement 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.

Give your agent a Mac in a minute.

Full macOS with Xcode and root, over MCP, CLI, API or SSH. $0.80 an hour, billed per minute. The Mac is deleted at stop; your 20 GB drive is kept for the next one. No Apple account needed to start.

Get started from $10

7-day money-back guarantee on your first purchase. Credit never expires.

Connect your agent →