Настройка подписи iOS-приложения (Certificates, Provisioning Profiles)
Система подписи Apple — один из самых частых источников потерянного времени в iOS-разработке. Xcode умеет автоматически управлять подписью, но в CI/CD-среде, при работе в команде или при наличии нескольких entitlements это автоматическое управление ломается непредсказуемо. Сборка падает с No signing certificate found, а Xcode при этом молчит о реальной причине.
Что именно ломается и почему
Чаще всего проблемы возникают в трёх ситуациях.
Истёкший сертификат в keychain. Apple Developer Certificate действует год. Когда он истекает, старые Provisioning Profiles, привязанные к нему, становятся невалидными автоматически. Xcode иногда не сообщает об истечении явно — просто не находит нужную подпись. Проверить актуальный статус: Keychain Access → My Certificates → искать iPhone Distribution или Apple Distribution с корректной датой.
Mismatch между Bundle ID и Provisioning Profile. Profile создаётся под конкретный App ID. Wildcard-профиль (com.example.*) удобен для быстрой разработки, но не поддерживает большинство entitlements: Push Notifications, Associated Domains, App Groups, HealthKit — всё это требует explicit App ID. Проект с Push включённым, но wildcard-профилем — сборка пройдёт, но entitlements не применятся, и APNS не заработает.
CI/CD без доступа к keychain. На чистом CI-агенте нет ни сертификатов, ни профилей. Стандартный подход — match (Fastlane): зашифрованный репозиторий с сертификатами, которые match скачивает и импортирует перед сборкой. Альтернатива — Xcode Cloud с автоматическим управлением, но он не гибок для кастомных шагов.
Полный процесс настройки
Apple Developer Portal
- Создать
App ID(Identifiers → App IDs) с явным Bundle ID и нужными Capabilities - Создать
Certificate Signing Requestчерез Keychain Access: Certificate Assistant → Request a Certificate - Загрузить CSR в Apple Developer Portal, скачать сертификат, установить в Keychain
- Создать Provisioning Profile, привязав App ID + Certificate + нужные устройства (для Development) или без устройств (для Distribution)
Xcode настройка
В Signing & Capabilities выбрать Manual signing. Указать Team, Bundle Identifier, и выбрать профиль явно. Для нескольких таргетов (основное приложение + Extension) — каждый таргет требует свой Provisioning Profile.
<!-- Пример entitlements файла для приложения с Push + App Groups -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ...>
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.example.app</string>
</array>
</dict>
</plist>
Entitlements в .entitlements файле должны точно совпадать с тем, что включено в App ID на Portal. Расхождение → reject при архивировании с ошибкой Provisioning profile doesn't support the ... entitlement.
Fastlane match для команды
# Matchfile
git_url("https://github.com/your-org/ios-certificates")
storage_mode("git")
type("appstore") # или "development", "adhoc"
app_identifier(["com.example.app", "com.example.app.notification-extension"])
username("[email protected]")
fastlane match appstore --readonly # на CI, только чтение
fastlane match development # на локальной машине, обновление
--readonly на CI — важно: предотвращает случайный перегенерации профилей в середине сборки.
Несколько Extension-таргетов
Notification Service Extension, Share Extension, Widget — каждый требует отдельного App ID (например com.example.app.widget) и отдельного Provisioning Profile. App Groups позволяют им делить данные через UserDefaults(suiteName:) или общий файловый контейнер. App Group должен быть включён в App ID каждого таргета.
Типичные ошибки
- Скачать Provisioning Profile вручную и положить в
~/Library/MobileDevice/Provisioning Profiles— работает локально, ломается на CI и у других разработчиков - Забыть обновить профиль после добавления нового устройства в Portal (для Development)
- Один сертификат на всю команду вместо Certificate per developer — при отзыве одного сертификата сборки у всех падают
Процесс работы
Аудит текущего состояния: сертификаты в Keychain, профили в Portal, entitlements в проекте.
Приведение App ID, Capabilities и Provisioning Profiles в соответствие.
Настройка Fastlane match или Xcode Cloud для командной работы и CI/CD.
Тестовая сборка на симуляторе и реальном устройстве, архивирование и проверка через Altool или Transporter.
Ориентиры по срокам
Разовая настройка подписи для одного таргета — 2–4 часа. При наличии нескольких Extensions, App Groups и настройки CI/CD через Fastlane match — 1–2 дня.







