Figment.so
Mac hostingWebsite hostingGuidesHow to usePricing

Manage Developer Certificates on a Remote Mac

When an Apple Distribution certificate expires, Xcode stops archiving and your CI pipeline stops signing. You do not need Keychain Access.app to fix that on a rented Mac. The security command and openssl handle the full rotation—generate the CSR, import the signed certificate, confirm the identity chain, and export an encrypted .p12—from a terminal session. Apple's overview of the signing flow is Preparing your app for distribution, and the authoritative notes on Developer ID expiry behavior live on the Developer ID support page.

The Certificate Chain You Are Maintaining

An Apple code-signing identity has three parts:

  1. Apple Root CA — pre-installed in the System keychain; you do not touch it.
  2. Apple Worldwide Developer Relations (WWDR) Intermediate — also in the System keychain. Xcode ships updated intermediates; download replacements from Apple's certificate authority list if a build host is missing the current one.
  3. Your Development or Distribution certificate — issued by Apple after you submit a CSR; lives in the login keychain alongside its private key.

A "valid identity" means all three are present and the certificate links to its private key. If the intermediate is absent or the private key is on a different machine, xcodebuild -allowProvisioningUpdates fails with a signing error.

Apple is rolling out G2 Developer ID authorities. Check the current state of your own certificates in the Apple Developer account portal rather than trusting a third-party deadline write-up.

Generate the CSR on the Remote Mac

Keep the private key on the machine that will sign builds. Generate it in the terminal on the remote Mac; do not create it locally and copy the private key across a network.

#!/usr/bin/env bash
set -euo pipefail
umask 077

CERT_NAME="acme_distribution_$(date -u +%Y%m%dT%H%M%SZ)"
CSR_FILE="${CERT_NAME}.certSigningRequest"
KEY_FILE="${CERT_NAME}.key"
EMAIL="releases@example.com"
COUNTRY="US"

# 2048-bit RSA key (minimum Apple accepts for code-signing CSRs)
openssl genrsa -out "$KEY_FILE" 2048

openssl req -new \
  -key "$KEY_FILE" \
  -out "$CSR_FILE" \
  -subj "/emailAddress=${EMAIL}/CN=${CERT_NAME}/C=${COUNTRY}"

echo "Upload ${CSR_FILE} at developer.apple.com → Certificates, Identifiers & Profiles."
echo "Keep ${KEY_FILE} on this Mac; it is required to use the issued certificate."

Upload $CSR_FILE and pick Apple Distribution for App Store/TestFlight signing or Developer ID Application for direct distribution and notarization.

Import the Signed Certificate

Download the .cer from the developer portal, transfer it to the remote Mac, and import it into the same login keychain that holds the private key.

#!/usr/bin/env bash
set -euo pipefail

CER_FILE="${1:?pass the downloaded .cer path}"
KEY_FILE="${2:?pass the matching .key path from the CSR step}"
KEYCHAIN="$HOME/Library/Keychains/login.keychain-db"

# Make sure the login keychain is unlocked for this shell
security unlock-keychain "$KEYCHAIN"

# Import the issued certificate; -T grants codesign access without a GUI prompt
security import "$CER_FILE" \
  -k "$KEYCHAIN" \
  -T /usr/bin/codesign \
  -T /usr/bin/productbuild

# Import the matching private key (same keychain so the identity is complete)
security import "$KEY_FILE" \
  -k "$KEYCHAIN" \
  -T /usr/bin/codesign

security find-identity -v -p codesigning "$KEYCHAIN"

The -T /usr/bin/codesign flag lets codesign use the key non-interactively; without it, a CI job can hang at a GUI password prompt. Pass the real file paths as arguments rather than globbing the key filename, so a stray .key file from a past rotation cannot be imported by accident.

Verify the Full Identity Chain

security find-identity -v -p codesigning

A healthy result:

1) A1B2C3D4E5F6... "Apple Distribution: Example Corp (TEAM123ABC)"
   1 valid identities found

If find-identity reports 0 valid identities found, one of these is missing:

  • WWDR intermediate — download the current intermediate from Apple's CA list and add it: sudo security add-trusted-cert -d -k /Library/Keychains/System.keychain <intermediate>.cer.
  • Private key — re-run security import for the .key file; the login keychain only forms an identity when key and cert are both present.
  • Certificate — re-import the .cer from the developer portal.

Confirm expiry and issuer with:

security find-certificate -a -c "Apple Distribution" -p \
  | openssl x509 -noout -subject -issuer -dates

Export an Encrypted .p12 for Backup

A .p12 bundles the certificate and its private key in a password-protected container. Use it to seed another signing host or to store a recovery copy in your secret manager—never in source control.

#!/usr/bin/env bash
set -euo pipefail
umask 077

P12_FILE="distribution_$(date -u +%Y%m%d).p12"
KEYCHAIN="$HOME/Library/Keychains/login.keychain-db"

# Omit -P so security prompts interactively; the passphrase never hits shell history
security export \
  -k "$KEYCHAIN" \
  -t identities \
  -f pkcs12 \
  -o "$P12_FILE"

echo "Encrypted p12 written to ${P12_FILE}"

Hand the passphrase to recipients out-of-band (a secret manager, not email). On the receiving Mac, run security import backup.p12 -k ~/Library/Keychains/login.keychain-db -P '<passphrase>' inside that user's shell. Provisioning profiles are separate files—place them in ~/Library/MobileDevice/Provisioning Profiles/; they do not belong in a keychain.

Certificate Rotation Calendar

CertificateTypical validityWhat expiry breaks
Apple Development~1 yearDebug builds on test devices
Apple Distribution~1 yearNew App Store / TestFlight archives
Developer ID Application~5 yearsSigning new Mac app updates (already-signed binaries keep running per Gatekeeper)
Developer ID Installer~5 yearsSigning new installer packages
WWDR IntermediateSet by AppleAny identity relying on the missing intermediate

Confirm each exact expiry on the Developer portal before you plan a rotation; Apple reissues intermediates and has shifted some Developer ID chains to G2 authorities. Set a calendar reminder about 30 days before any Distribution certificate expires—Xcode does not warn you before the first failing build.

Which Figment Plan Fits This Task

This runbook is terminal-only. No GUI, no GPU, no Apple silicon instruction set is needed to generate a CSR, import a certificate, or export a .p12.

  • $29/month virtual Intel macOS — a virtual Intel macOS environment accessed through the browser console. It runs real macOS, so security, openssl, codesign, and compatible Intel Xcode toolchains (Xcode 26 or earlier per Apple's porting guide) handle this certificate workflow. Your shell runs inside the VM.
  • M-series Mac from $95/month — choose this when you need arm64 execution, Xcode 27, visionOS tooling, or GPU-accelerated simulators. The specific chip, RAM, and disk are confirmed in the quote; physical plans collect requests until supply is confirmed.
  • Managed Build Mac at $249/month — one M-series Mac with CI setup, backups, monitoring, and 30 minutes of monthly support included. Useful if you want Figment to wire the signing keychain, CI runner, and secret-manager restore step into a working pipeline instead of writing it yourself.
  • Managed Mac Team at $999/month — two M-series Macs, two CI runners, team setup, backups, monitoring, and one hour of monthly support. Fits a small iOS team that signs and ships from shared infrastructure.

If the only moving part is certificate rotation on one host, the $29 virtual Intel macOS plan is enough. If an engineer is about to spend a week wiring CI, signing, and a secret-manager restore, the Managed Build Mac usually recovers its cost in that one onboarding.

Request a plan at Figment Mac Hosting →

Related guides:


Subscribe for Figma design and website publishing guides.


Figment.so

Contact

Twitter

Website pricing

Compute index

About

Privacy

Terms