
Manual code signing works until another developer touches the project, leading to Apple certificate limits, silent revocations, and "it worked yesterday" errors. This post explores how Fastlane Match solves those problems with an encrypted repo, simple commands, and a secure workflow for teams and CI.
The Pain of Manual iOS Certificate Management
Manual iOS code signing requires developers to generate, download, and install provisioning profiles and certificates on each workstation. The process is straightforward when a single engineer builds the app, but it quickly becomes a coordination problem as soon as more than one person touches the project.
When a second developer attempts to sign the same bundle identifier, Apple’s per‑account limits on development and distribution certificates are enforced. An account can hold only a limited number of active certificates (e.g., two development and one distribution certificate). If the first developer has already consumed those slots, the second developer’s attempt to create a new certificate fails with an error such as “Maximum number of certificates reached”. The failure is silent in the sense that the Xcode UI often reports a generic “code signing failed” without indicating that a quota has been exceeded.
Silent revocations add another layer of instability. Apple may revoke a certificate without explicit notification when it detects misuse or when the certificate approaches its expiration date. The revocation surfaces only when the build process contacts Apple’s signing service, resulting in a sudden “it worked yesterday” error that forces the team to investigate the cause retroactively.
- Second‑developer conflict: Competing attempts to create or download certificates cause quota errors.
- Certificate limits: Fixed maximum numbers per Apple Developer account restrict parallel workflows.
- Silent revocation: Unexpected invalidation of a certificate leads to build failures without clear diagnostics.
- “It worked yesterday” errors: Intermittent failures arise from expired or revoked assets that were previously valid.
Practical example: Developer A creates a development certificate and adds it to the project. Developer B, on a separate machine, runs xcodebuild and receives the error Code signing is required for product type ‘Application’ in SDK ‘iOS’. After checking the Apple Developer portal, they discover that the account already has two active development certificates, the maximum allowed. The immediate fix is to revoke one of the existing certificates, but doing so invalidates any builds that still rely on the revoked credential, causing downstream CI pipelines to break.
These challenges illustrate why manual management does not scale in a multi‑engineer environment. The root causes—quota enforcement, lack of centralized state, and opaque revocation signals—must be addressed before a team can reliably automate iOS releases.
Why Teams Need a Better Solution
When a team relies on ad‑hoc, manual processes to distribute signing certificates, API keys, or other build‑time secrets, the workflow quickly becomes a source of nondeterministic failures. Each developer must locate the latest version of a file, copy it to a local machine, and ensure the same artifact is available on every CI runner. The moment a second engineer checks out the project, the following problems typically emerge:
- **Version drift** – developers may be using different certificate revisions, causing mismatched bundle identifiers or expired provisioning profiles.
- **Quota exhaustion** – platforms such as Apple enforce limits on the number of active certificates; manual creation can exceed those limits without a central view.
- **Silent revocation** – a revoked certificate is not obvious until a build fails, producing “it worked yesterday” errors that are hard to trace.
- **Race conditions** – simultaneous updates to a shared file can overwrite each other, leaving the repository in an inconsistent state.
- **Compliance gaps** – storing secrets in plain text on developer machines or in unencrypted repositories violates controls required by SOC 2, ISO 27001, NIST SP 800‑53, and OWASP recommendations for secret management.
Consider a typical iOS code‑signing scenario: a developer manually copies a .p12 certificate and its provisioning profile into the project directory. When a CI job runs, it must locate the same files, often by pulling them from a separate storage bucket or by prompting a team member to upload them. If the certificate has been regenerated or the profile updated, the CI build fails with cryptic errors, and the fix requires a manual sync across all environments.
To eliminate these failure modes, teams need a consistent, shared approach that:
- Stores secrets in an encrypted, version‑controlled repository accessible to both developers and CI agents.
- Provides deterministic commands (e.g.,
fastlane matchfor iOS) that fetch the exact required artifacts. - Enforces access controls and audit logging to satisfy security standards.
- Automates rotation and revocation handling, reducing human error.
By moving from manual copy‑paste steps to an automated, centrally managed secret distribution mechanism, teams achieve reproducible builds, reduce operational overhead, and maintain compliance with industry‑standard security frameworks.
Introducing Fastlane Match
Fastlane Match addresses the inherent fragility of manual code signing, which often fails when multiple developers introduce conflicting certificates or exceed Apple’s strict certificate limits. The core mechanism of Match is the centralized synchronization of iOS signing assets—specifically development and distribution certificates and their corresponding provisioning profiles—by utilizing a single, encrypted Git repository.
By moving signing assets out of individual local ~/Library/MobileDevice/Provisioning Profiles directories and into a version-controlled, encrypted repository, teams ensure that every developer and continuous integration (CI) environment operates with an identical set of credentials. This eliminates the "it worked on my machine" class of errors caused by drifting state or silent revocations.
The workflow relies on four primary operational commands to manage the lifecycle of these assets:
match development: Provisions certificates and profiles for internal testing environments.match appstore: Provisions assets specifically for App Store release builds.match adhoc: Provisions assets for distribution to registered beta devices outside of TestFlight.match nuke: Destroys all existing certificates and profiles from the Apple Developer Portal and the Git repository, effectively resetting the project’s signing state when credentials become compromised or mismanaged.
Security is maintained by encrypting the repository contents, ensuring that sensitive private keys are not exposed in plaintext. When a developer or CI runner executes a match command, the tool decrypts the assets into the local environment only for the duration of the build process. This architecture ensures that the repository serves as the single source of truth for the entire team, allowing for reproducible builds across any environment without the overhead of manual certificate exportation or individual workstation maintenance. By automating this synchronization, teams avoid the common pitfalls associated with manual developer account management, such as accidental certificate revocation and provisioning profile desynchronization.
Key Commands and Workflow with Match
Fastlane Match centralizes code signing by storing certificates and provisioning profiles in a private, encrypted Git repository. This approach eliminates the common "it worked yesterday" errors caused by manual certificate management, where individual developer machines often drift out of sync with Apple’s portal. By decoupling signing assets from local Xcode state, the entire engineering team and CI/CD pipelines function from a single, consistent source of truth.
The core match command set maps directly to specific distribution requirements. Executing these commands forces the synchronization of local environments with the encrypted remote repository:
match development: Retrieves or creates a development certificate and associated provisioning profiles, allowing all authorized team members to deploy builds to registered test devices.match appstore: Manages credentials required for App Store distribution, ensuring that releases are signed with the appropriate distribution identity.match adhoc: Generates credentials for ad-hoc distribution, enabling testers to install builds on specific, non-App Store devices.match nuke: Performs a destructive reset. This command deletes all certificates and provisioning profiles from both the Apple Developer Portal and the storage repository, effectively wiping the slate to resolve persistent corruption or unauthorized access issues.
To integrate these into a streamlined workflow, engineers typically invoke match via their Fastfile. This ensures that every time a build is triggered—locally or in a pipeline—the environment is verified against the repository. For example, a standard deployment sequence for a production release would utilize bundle exec fastlane match appstore before invoking the build command. By automating the retrieval and installation of certificates, teams bypass the Apple Developer Portal's manual interface, mitigating the risk of silent revocations and ensuring that signing identity management remains strictly version-controlled and audit-ready.
Addressing Security Concerns: Storing Certs in a Repo
Certificates and provisioning profiles are secret artefacts that must be protected from unauthorized disclosure and tampering. The primary risk is not the fact that they reside in a version‑controlled repository, but rather how the repository is secured and who can retrieve the encrypted payload. When the repository is encrypted at rest and access is gated by strong authentication (e.g., SSH keys, SAML‑backed SSO) and audit logging, the same controls that protect source code also protect the certificates.
Fastlane Match demonstrates this approach: a single encrypted Git repository stores all iOS signing assets, and every developer or CI runner clones the repo, decrypts the bundle locally, and uses the certificates for code signing. The encryption key is never committed; it is supplied at build time via a secret‑management system (e.g., HashiCorp Vault, AWS Secrets Manager) or an environment variable protected by the CI platform.
Secure setup walkthrough
- Create an encrypted archive. Use
openssl aes-256-cbc(or the built‑in Fastlane encryption) to bundle.p12certificates and provisioning profiles into a single file. - Store the archive in a private Git repo. The repo must be:
- Hosted on a platform that enforces TLS for transport.
- Restricted to authenticated users/groups only.
- Monitored for read/write events (audit logs).
- Protect the decryption key. Place the key in a secrets store that complies with standards such as NIST SP 800‑57 (key management) and ISO 27001 (information security). Grant read‑only access to the CI service account.
- Integrate with CI/CD. In the pipeline:
- Fetch the encrypted repo via SSH.
- Inject the decryption key from the secret store.
- Run
fastlane match development(orappstore,adhoc) to decrypt and install the certs.
- Rotate regularly. Periodically regenerate certificates and re‑encrypt the archive. Update the decryption key in the secret store and revoke old keys, satisfying SOC 2 and NIST requirements for change management.
By treating the encrypted repository as a controlled artifact store—subject to the same access policies, encryption standards, and audit mechanisms as source code—organizations eliminate the perceived “risk” of storing certificates in version control while gaining reproducible, auditable builds.
Editorial Policy & Research Methodology
Our findings are based on rigorous internal research, verified industry benchmarks, and direct technical implementation experience from our enterprise client projects. All statistics and technical claims are reviewed by senior engineers before publication to ensure accuracy, transparency, and helpfulness for our readers.
