Automatic vs Manual code signing
Signing iOS apps requires a signing certificate
(App Store development or distribution certificate in .p12
format) and a provisioning profile
. In manual code signing you save these files as Codemagic environment variables
and manually reference them in the appropriate build steps.
In Automatic code signing, Codemagic takes care of Certificate and Provisioning profile management for you. Based on the Certificate private key
that you provide, Codemagic will automatically fetch the correct certificate from the App Store or create a new one if necessary.
Automatic code signing
When automatic code signing is used, then most up-to-date signing files are obtained directly from Apple during the build time. This requires that Codemagic has access to your Apple Developer portal account, which is achieved by using App Store Connect API key.
Creating the App Store Connect API key
It is recommended to create a dedicated App Store Connect API key for Codemagic in App Store Connect. To do so:
- Log in to App Store Connect and navigate to Users and Access > Integrations » App Store Connect API.
- Click on the + sign to generate a new API key.
- Enter the name for the key and select an access level. We recommend choosing
App Manager
access rights, read more about Apple Developer Program role permissions here. - Click Generate.
- As soon as the key is generated, you can see it added to the list of active keys. Click Download API Key to save the private key for later. Note that the key can only be downloaded once.
Obtaining the Certificate private key
To sign iOS apps, you can use the private key of an iOS Distribution certificate that has already been created in your Apple Developer Program account.
Alternatively, you can create a new private key on your Mac and the Codemagic CLI will create a new iOS Distribution certificate in your Apple Developer Program account for you.
You can create a new 2048 bit RSA key by running the command below in your terminal:
ssh-keygen -t rsa -b 2048 -m PEM -f ~/Desktop/ios_distribution_private_key -q -N ""
This new private key will be used to create a new iOS Distribution certificate in your Apple Developer Program account if there isn’t one that already matches this private key.
- On the Mac which created the iOS distribution certificate, open the Keychain Access, located in the Applications and Utilities folder.
- Select the certificate entry which should be listed as
iPhone Distribution: company_name (team_id)
. - Right-click on it to select “Export.”
- In the export prompt window that appears, make sure the file format is set to Personal Information Exchange (.p12)"**.
- Give the file a name such as “IOS_DISTRIBUTION”, choose a location and click Save.
- On the next prompt, leave the password empty and click OK.
- Use the following
openssl
command to export the private key:
openssl pkcs12 -in IOS_DISTRIBUTION.p12 -nodes -nocerts | openssl rsa -out ios_distribution_private_key
- When prompted for the import password, just press enter. The private key will be written to a file called ios_distribution_private_key in the directory where you ran the command.
Configuring environment variables
Provisioning profiles and code signing certificates are obtained from Apple Developer portal with the command app-store-connect fetch-signing-files
. App Store Connect API key information can be passed to it via environment variables APP_STORE_CONNECT_KEY_IDENTIFIER
, APP_STORE_CONNECT_ISSUER_ID
, APP_STORE_CONNECT_PRIVATE_KEY
.
The Apple Developer Portal integration can be enabled in Teams > Personal Account > Integrations for personal projects and in Teams > Your Team Name > Team integrations for projects shared in the team (if you’re a team admin). This allows you to conveniently use the same access credentials for automatic code signing and publishing across different apps and workflows.
- In the list of available integrations, click the Connect button for Developer Portal.
- In the App Store Connect API key name, provide a name for the key you are going to set up the integration with. This is for identifying the key in Codemagic.
- Enter the Issuer ID related to your Apple Developer account. You can find it above the table of active keys on the Integrations tab of the Users and Access page.
- Enter the Key ID of the key to be used for code signing.
- In the API key field, upload the private API key downloaded from App Store Connect.
- Click Save to finish the setup.
If you work with multiple Apple Developer teams, you can add additional keys by clicking Add another key right after adding the first key and repeating the steps described above. You can delete existing keys or add new ones when you click Manage keys next to the Developer Portal integration in user or team settings.
Integration will take care of the App Store Connect API authentication part, but additionally the certificate private key has to be exported too. For this additional environment variable CERTIFICATE_PRIVATE_KEY
has to be defined.
- Open your Codemagic app settings, and go to the Environment variables tab.
- Enter
CERTIFICATE_PRIVATE_KEY
as the Variable name. - Open the file
ios_distribution_private_key
with a text editor and copy the entire contents of the file, including the-----BEGIN RSA PRIVATE KEY-----
and-----END RSA PRIVATE KEY-----
tags. Alternatively, you can run the following command on the file:
cat ios_distribution_private_key | pbcopy
- Paste into the Variable value field.
- Enter a variable group name, e.g. code-signing. Click the button to create the group.
- Make sure the Secure option is selected so that the variable can be protected by encryption.
- Click the Add button to add the variable.
In your workflow you can now simply use the following to ensure that all variables are readily available during build:
workflows:
ios-workflow:
environment:
groups:
- code-signing
integrations:
app_store_connect: <App Store Connect API key name>
This will expose necessary environment variables during the build.
- Open your Codemagic app settings, and go to the Environment variables tab.
- Enter
CERTIFICATE_PRIVATE_KEY
as the Variable name. - Open the file
ios_distribution_private_key
with a text editor and copy the entire contents of the file, including the-----BEGIN RSA PRIVATE KEY-----
and-----END RSA PRIVATE KEY-----
tags. Alternatively, you can run the following command on the file:
cat ios_distribution_private_key | pbcopy
- Paste into the Variable value field.
- Enter a variable group name, e.g. appstore_credentials. Click the button to create the group.
- Make sure the Secure option is selected so that the variable can be protected by encryption.
- Click the Add button to add the variable.
- Run the following command on the App Store Connect API key file that you downloaded earlier (in our example saved as
codemagic_api_key.p8
) to copy its content to clipboard:
cat codemagic_api_key.p8 | pbcopy
- Create a new Environment variable
APP_STORE_CONNECT_PRIVATE_KEY
and paste the value from clipboard.
- Create variable
APP_STORE_CONNECT_KEY_IDENTIFIER
. The value is the Key ID field from App Store Connect > Users and Access > Keys. - Create variable
APP_STORE_CONNECT_ISSUER_ID
. The value is the Issuer ID field from App Store Connect > Users and Access > Keys.
Environment variables have to be added to the workflow either individually or as a group. Modify your codemagic.yaml
file by adding the following:
workflows:
ios-workflow:
name: iOS Workflow
# ....
environment:
groups:
- appstore_credentials
Finally, to code sign the app, add the following commands in the scripts
section of the configuration file, after all the dependencies are installed, right before the build commands.
scripts:
- name: Set up keychain to be used for code signing using Codemagic CLI 'keychain' command
script: keychain initialize
- name: Fetch signing files
script: |
app-store-connect fetch-signing-files "$BUNDLE_ID" \
--type IOS_APP_STORE \
--create
- name: Set up signing certificate
script: keychain add-certificates
- name: Set up code signing settings on Xcode project
script: xcode-project use-profiles
Instead of specifying the exact bundle-id, you can use "$(xcode-project detect-bundle-id)"
.
Based on the specified bundle ID and provisioning profile type set with the --type
argument, Codemagic will fetch or create the relevant provisioning profile and certificate to code sign the build.
If you are publishing to the App Store or you are using TestFlight to distribute your app to test users, set the --type
argument to IOS_APP_STORE
.
When using a third party app distribution service such as Firebase App Distribution, set the --type
argument to IOS_APP_ADHOC
Manual code signing
In order to use manual code signing, you need the following:
- Signing certificate: Your development or distribution certificate in .P12 format.
- Certificate password: The certificate password if the certificate is password-protected.
- Provisioning profile: You can get it from Apple Developer Center > Certificates, Identifiers & Profiles > Profiles and select the provisioning profile you would like to export and download.
- Open your Codemagic app settings, and go to the Environment variables tab.
- Enter
CM_CERTIFICATE
as the Variable name. - Run the following command on the certificate file to
base64
encode it and copy to clipboard:cat ios_distribution_certificate.p12 | base64 | pbcopy
- Paste into the Variable value field.
- Enter a variable group name, e.g. appstore_credentials.
- Make sure the Secure option is selected so that the variable can be protected by encryption.
- Click the Add button to add the variable.
- Repeat steps 2 -7 to create the variable
CM_PROVISIONING_PROFILE
and paste thebase64
encoded value of the provisioning profile file. - Add the
CM_CERTIFICATE_PASSWORD
variable, make it Secure and add it to the same variable group.
Then, add the code signing configuration and the commands to code sign the build in the scripts section, after all the dependencies are installed, right before the build commands.
scripts:
- name: Set up keychain to be used for code signing using Codemagic CLI 'keychain' command
script: keychain initialize
- name: Set up provisioning profiles from environment variables
script: |
PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
mkdir -p "$PROFILES_HOME"
PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)"
echo ${CM_PROVISIONING_PROFILE} | base64 --decode > "$PROFILE_PATH"
echo "Saved provisioning profile $PROFILE_PATH"
- name: Set up signing certificate
script: |
echo $CM_CERTIFICATE | base64 --decode > /tmp/certificate.p12
if [ -z ${CM_CERTIFICATE_PASSWORD+x} ]; then
# when using a certificate that is not password-protected
keychain add-certificates --certificate /tmp/certificate.p12
else
# when using a password-protected certificate
keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $CM_CERTIFICATE_PASSWORD
fi
- name: Set up code signing settings on Xcode project
script: xcode-project use-profiles
Using multiple provisioning profiles
To set up multiple provisioning profiles, for example, to use app extensions such as Notification Service, the easiest option is to add the provisioning profiles to your environment variables with a similar naming convention.
For example, create a provisioning_profiles
environment variable group and add variables such as:
- CM_PROVISIONING_PROFILE_BASE
- CM_PROVISIONING_PROFILE_NOTIFICATIONSERVICE
Then, include this group in your workflow and set up provisioning profiles with a script:
environment:
groups:
- provisioning_profiles
# ...
scripts:
- name: Set up Provisioning profiles from environment variables
script: |
PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles"
mkdir -p "$PROFILES_HOME"
for profile in "${!CM_PROVISIONING_PROFILE_@}"; do
PROFILE_PATH="$(mktemp "$HOME/Library/MobileDevice/Provisioning Profiles"/ios_$(uuidgen).mobileprovision)"
echo ${!profile} | base64 --decode > "$PROFILE_PATH"
echo "Saved provisioning profile $PROFILE_PATH"
done