Збірка та підписання десктоп-додатку для macOS
Ситуація: додаток зібрано, але на сучасних версіях macOS (14+) Gatekeeper блокує запуск. Користувачі повідомляють: «не може бути відкрито, оскільки Apple не може перевірити його». Корінь — відсутність підпису коду та нотаризації. Без них Gatekeeper блокує запуск, а обхід через «Системні налаштування» вимагає нестандартних дій, які більшість користувачів не виконають.
Вирішити це можна за 3–4 дні, якщо правильно налаштувати ланцюжок: сертифікат Developer ID → entitlements → підпис → нотаризація → stapling. Ми робимо це під ключ для Electron, Qt, SwiftUI та інших фреймворків. За 5+ років досвіду ми провели понад 50 релізів для macOS — жоден не було заблоковано. Apple Notarization Guide
Плата за вхід: сертифікат Developer ID Application можна отримати лише за наявності підписки Apple Developer Program (вартість $99/рік). Сама нотаризація для розробників безкоштовна.
Чому підпис коду критичний?
Підпис коду — це цифровий підпис розробника, що гарантує цілісність додатку. macOS перевіряє його при кожному запуску. Без нього Gatekeeper блокує додаток, користувач змушений вручну дозволяти запуск через «Системні налаштування» або термінал. Для корпоративних середовищ це неприйнятно: MDM-політики забороняють запуск непідписаних додатків. Нотаризація додає перевірку Apple на шкідливий код. Обидві процедури обов'язкові для поширення поза Mac App Store.
Як підписати та нотаризувати додаток для macOS?
Процес включає 2 обов'язкові етапи: Code Signing та Notarization. Спочатку отримуєте сертифікат Developer ID Application (потрібен Apple Developer Account). Потім конфігуруєте збірку з правильними entitlements. Нижче — мінімальний конфіг для Electron.
// electron-builder.yml
mac:
target:
- target: dmg
- target: zip
icon: build/icon.icns
category: public.app-category.productivity
hardenedRuntime: true
gatekeeperAssess: false
entitlements: build/entitlements.mac.plist
entitlementsInherit: build/entitlements.mac.plist
identity: "Developer ID Application: Company Name (TEAM_ID)"
<!-- build/entitlements.mac.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key><true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key><true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key><true/>
<key>com.apple.security.network.client</key><true/>
</dict>
</plist>
Які entitlements потрібні для Electron-додатків?
Electron вимагає 4 ключі: allow-jit (для V8), allow-unsigned-executable-memory (для JIT-компіляції), allow-dyld-environment-variables (для Node.js) та network.client (для HTTP-запитів). Без них додаток вилетить при старті або не зможе виконувати мережеві запити. Порівняйте з entitlements для нативних SwiftUI-додатків: там зазвичай достатньо com.apple.security.app-sandbox та com.apple.security.files.user-selected.read-write.
| Entitlement | Electron | SwiftUI | Qt |
|---|---|---|---|
| com.apple.security.cs.allow-jit | Так | Ні | Так |
| com.apple.security.cs.allow-unsigned-executable-memory | Так | Ні | Так |
| com.apple.security.cs.allow-dyld-environment-variables | Так | Ні | Так |
| com.apple.security.network.client | Так | Так | Так |
| com.apple.security.app-sandbox | Опціонально | Так | Опціонально |
Нотаризація та stapling
Після підпису надсилаємо .dmg на нотаризацію через notarytool. Apple сканує бінарники на віруси та шкідливий код. Результат — нотаризаційний квиток, який вбудовується у файл командою stapler.
# Через notarytool (Xcode 13+)
xcrun notarytool submit AppName.dmg \
--apple-id "[email protected]" \
--password "@keychain:AC_PASSWORD" \
--team-id "TEAM_ID" \
--wait
# Stapling (вбудовування нотаризаційного квитка у файл)
xcrun stapler staple AppName.dmg
Notarytool працює в 3 рази швидше старого altool та має кращий рівень підтримки, оскільки активно розвивається Apple.
Покрокове налаштування підпису в CI/CD
- Отримайте сертифікат Developer ID Application в Apple Developer Portal (сертифікат типу Developer ID Application, не Development).
- Експортуйте сертифікат у .p12 та збережіть у секретах CI (наприклад, GitHub Secrets).
- Налаштуйте
electron-builderабо аналог із потрібними entitlements (див. вище). - Додайте крок імпорту сертифіката в CI-пайплайн.
- Налаштуйте етап нотаризації з
notarytoolта stapling. - Протестуйте збірку на локальній машині та в CI.
GitHub Actions для macOS
- uses: actions/checkout@v3
- name: Import Certificate
run: |
echo "$MACOS_CERTIFICATE" | base64 --decode > certificate.p12
security import certificate.p12 -P "$MACOS_CERTIFICATE_PWD" \
-A -t cert -f pkcs12 -k ~/Library/Keychains/login.keychain
- name: Build and Sign
run: npm run build:mac
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASS: ${{ secrets.APPLE_ID_PASS }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
CSC_LINK: ${{ secrets.MACOS_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
Universal Binary (Intel + Apple Silicon)
Universal binary — це збірка, що містить обидві архітектури (x86_64 та arm64). Вона працює нативно на M1/M2/M3 без Rosetta 2. Це обов'язкова вимога для App Store та багатьох корпоративних середовищ. Економія продуктивності: без universal binary ви втрачаєте до 30% на Apple Silicon.
# electron-builder автоматично створює universal binary
npx electron-builder --mac --universal
Що входить у налаштування під ключ
| Етап | Тривалість | Результат |
|---|---|---|
| Аналіз проєкту | 1 день | Список необхідних entitlements, сертифікатів, інфраструктура CI |
| Налаштування збірки та підпису | 1–2 дні | Робочий CI-пайплайн із підписом коду |
| Нотаризація та тестування | 1 день | Нотаризований .dmg, stapled |
| Документація та навчання | 0.5 дня | README, опис процесу, інструкція для команди |
Додатково: налаштування автоматичного оновлення (Sparkle, Electron auto-updater), white-label підпис, робота з Apple Developer Enterprise Program.
Типові помилки
- Використання сертифіката Apple Development замість Developer ID — підпис лише для налагодження.
- Пропуск
hardenedRuntime: true— нотаризація не пройде. - Неправильні entitlements для Electron — падіння при старті.
- Відсутність stapling — користувачі побачать попередження, якщо немає інтернету.
- Забули про universal binary — втрата продуктивності на Apple Silicon.
- Сертифікат Developer ID Application не підходить, якщо ви помилилися типом (потрібен саме Developer ID, а не Development).
- Нотаризація не проходить, якщо не включено
hardenedRuntime. - Додаток падає при старті — перевірте entitlements: для Electron обов'язкові
allow-jitтаallow-unsigned-executable-memory. - Stapling не спрацьовує, якщо файл пошкоджений — виконайте
staplerодразу післяnotarytool.
Спираючись на наш досвід, ми рекомендуємо тестувати нотаризацію на кожному релізі. Навіть заміна версії Electron може зламати entitlements.
Терміни та гарантія
Базове налаштування займає 3–4 робочих дні. Ми гарантуємо, що додаток пройде нотаризацію та буде запускатися на macOS 10.14 і новіше. Зв'яжіться з нами, щоб налаштувати підпис за 3-4 дні та уникнути блокувань Gatekeeper. Отримайте консультацію щодо вашого проєкту — ми допоможемо уникнути типових помилок та заощадити час.







