Skip to main content

How to Set Up iOS and macOS Code Signing on CircleCI

Set up iOS and macOS code signing on CircleCI by uploading Apple certificates and provisioning profiles via the API. Covers .p12 certificates, signing bundles, Developer ID, Apple Distribution, Mac Developer certificate types, and referencing signing conf

iOS and macOS Code Signing on CircleCI

CircleCI's code signing feature lets you securely store your Apple certificates and provisioning profiles in your organization's settings and reference them directly in your pipeline config. This article covers how to upload your credentials via the API, create signing bundles, and use them in your macOS jobs.

Note: This feature is currently API-only. A UI is in development.


Prerequisites

Before you begin, make sure you have the following:

  • Apple signing certificate — a .p12 file exported from Keychain Access, along with its password

  • Provisioning profiles.mobileprovision (iOS) or .provisionprofile (macOS), if required for your certificate type (see Provisioning profile requirements)

  • CircleCI API token — a personal API token; see Managing API tokens

  • CircleCI Organization ID — see How to find IDs


Step 1: Upload your certificate

Convert your .p12 file to a Base64-encoded string, then POST it to the certificates endpoint.

On macOS, encode your certificate:

base64 -i your-cert.p12 -o -

Upload the certificate:

curl -X POST https://circleci.com/api/v2/certificates \
-H "Circle-Token: <your-circleci-api-token>" \
-H "Content-Type: application/json" \
-d '{
"org_id": "<org-id>",
"cert_file_name": "<.p12-file>",
"cert_blob": "<.p12-base64-encoded-blob>",
"cert_password": "<your-cert-password>"
}'

Response:

{"id":"<cert-id>"}

Save the returned cert-id — you'll need it in the next step.


Step 2: Create a signing bundle

A signing bundle links your certificate to one or more provisioning profiles. Reference it by name in your CircleCI config.

Encode your provisioning profile (if required):

base64 -i your-profile.mobileprovision -o -

Create the signing bundle:

curl -X POST https://circleci.com/api/v2/signing-configs \
-H "Circle-Token: <your-circleci-api-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "<signing-bundle-name>",
"org_id": "<org-id>",
"cert_id": "<cert-id-from-step-1>",
"provisioning_profiles": [
{
"file_name": "<provisioning-profile-file>",
"blob": "<provisioning-profile-base64-blob>"
}
]
}'

Response:

{"id":"<signing-config-id>"}

Naming rules for <signing-bundle-name>: letters, numbers, and hyphens only; max 50 characters; must be unique within your organization.


Step 3: Update your CircleCI config

Reference your signing bundle by name in the code_signing block of your macOS job. The install_signing_bundle step handles installing the certificate and profiles onto the runner automatically.

version: 2.1

jobs:
deploy:
macos:
xcode: 15.2.0
code_signing:
- <signing-bundle-name>
# Add additional bundles if needed:
# - <other-signing-bundle-name>
steps:
- install_signing_bundle
- checkout
- run:
name: Build and Archive
command: xcodebuild archive -scheme <your-xcode-scheme> -configuration Release

Tip: Your Xcode scheme name can be found in Xcode under Product > Scheme, or by running xcodebuild -list in your project directory.

What happens during the job

  1. A temporary keychain is created on the runner.

  2. Certificates and provisioning profiles are installed into the correct system paths.

  3. After the job completes, all credentials are automatically removed from the runner.


Provisioning profile requirements

Whether your signing bundle needs provisioning profiles depends on your certificate type:

Certificate type

Provisioning profiles

Developer ID Application

Not required — do not include profiles

Developer ID Installer

Not required — do not include profiles

3rd Party Mac Developer Installer

Not required — do not include profiles

3rd Party Mac Developer Application

Required (.provisionprofile)

Mac Developer

Required (.provisionprofile)

Apple Distribution

Required (.mobileprovision for iOS, .provisionprofile for macOS)

Apple Development

Required (.mobileprovision for iOS, .provisionprofile for macOS)

Uploading profiles for certificate types that don't require them will cause the request to be rejected.


Supported certificate types

The certificate's Subject Common Name must begin with one of the following:

  • Developer ID Application / Developer ID Installer — notarized or direct distribution outside the Mac App Store

  • 3rd Party Mac Developer Application / 3rd Party Mac Developer Installer — Mac App Store distribution

  • Mac Developer — development

  • Apple Distribution / Apple Development — valid for both iOS and macOS


Managing your certificates and signing bundles

List certificates

curl -H "Circle-Token: <your-circleci-api-token>" \
"https://circleci.com/api/v2/certificates?org-id=<org-id>"

List signing bundles

curl -H "Circle-Token: <your-circleci-api-token>" \
"https://circleci.com/api/v2/signing-configs?org-id=<org-id>"

Delete a certificate

curl -X DELETE -H "Circle-Token: <your-circleci-api-token>" \
https://circleci.com/api/v2/certificates/<cert-id>

A certificate cannot be deleted while it is referenced by an active signing bundle. Remove the signing bundle first.

Delete a signing bundle

curl -X DELETE -H "Circle-Token: <your-circleci-api-token>" \
https://circleci.com/api/v2/signing-configs/<signing-config-id>

Constraints

Field

Constraint

Certificate filename

Max 40 characters

Signing bundle name

Max 50 characters; letters, numbers, hyphens only; unique per org

Provisioning profiles per bundle

Max 100

Provisioning profile filename

Max 40 characters


Known limitations

  • This feature is designed for standard Apple Developer accounts. Compatibility with the Apple Developer Enterprise Program (In-House distribution) is not guaranteed.

  • A UI for managing certificates and signing bundles is not yet available. All setup must be done via the API.

Did this answer your question?