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
.p12file exported from Keychain Access, along with its passwordProvisioning 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
A temporary keychain is created on the runner.
Certificates and provisioning profiles are installed into the correct system paths.
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 ( |
Mac Developer | Required ( |
Apple Distribution | Required ( |
Apple Development | Required ( |
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 Store3rd Party Mac Developer Application/3rd Party Mac Developer Installer— Mac App Store distributionMac Developer— developmentApple 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.