Skip to content

Sign and notarize macOS releases with Apple Developer ID #83

Description

@glenn-jocher

Search

  • I searched existing Lite issues.

Problem

First-time macOS users cannot open Lite through the normal Gatekeeper confirmation. They must instead open System Settings > Privacy & Security and manually allow the app.

Lite currently configures Tauri with bundle.macOS.signingIdentity: "-", which creates an ad-hoc signature. The published v0.0.22 application confirmed this:

Signature=adhoc
TeamIdentifier=not set
Lite.app: rejected

TAURI_SIGNING_PRIVATE_KEY signs Tauri updater artifacts. It is separate from Apple Developer ID signing and does not establish Gatekeeper trust.

Required Apple setup

Using the Ultralytics paid Apple Developer account:

  1. The Account Holder creates a Developer ID Application certificate using a CSR generated on a controlled Mac.
  2. Install the certificate in Keychain Access and export the certificate plus private key as a password-protected .p12.
  3. Create a team App Store Connect API key with Developer access for notarization and download its .p8 private key. Do not use an individual API key because it cannot authenticate notarytool.

A Developer ID Installer certificate is not needed because Lite distributes a DMG rather than a PKG.

Add these GitHub Actions secrets, preferably in a protected release environment:

Secret Value
APPLE_CERTIFICATE Base64-encoded .p12
APPLE_CERTIFICATE_PASSWORD Password used to export the .p12
APPLE_SIGNING_IDENTITY Full Developer ID Application: ... (TEAMID) identity
APPLE_API_ISSUER App Store Connect issuer UUID
APPLE_API_KEY App Store Connect key ID
APPLE_API_PRIVATE_KEY Complete contents of the downloaded .p8

Implementation

Extend the existing macOS entry in .github/workflows/publish.yml; do not create another release path:

  1. Remove the ad-hoc bundle.macOS.signingIdentity: "-" setting from src-tauri/tauri.conf.json.
  2. On the macOS runner only, import APPLE_CERTIFICATE into a temporary keychain and make it available to codesign.
  3. Write APPLE_API_PRIVATE_KEY to a permission-restricted file under $RUNNER_TEMP and expose its path as APPLE_API_KEY_PATH.
  4. Pass APPLE_SIGNING_IDENTITY, APPLE_API_ISSUER, APPLE_API_KEY, and APPLE_API_KEY_PATH to the existing Tauri build. Tauri should own signing, notarization, and stapling.
  5. Keep the existing Tauri updater signing variables and latest.json flow unchanged.
  6. Fail the macOS build before publishing the draft release if signing, notarization, stapling, or verification fails. Never fall back to ad-hoc signing when Apple credentials are absent.

No additional macOS entitlements are expected initially. Add only an entitlement required by an observed signing/notarization failure or a capability Lite actually uses.

Release verification

Run these checks against the generated application and DMG before the release is published:

codesign --verify --deep --strict --verbose=2 Lite.app
codesign --display --verbose=4 Lite.app
spctl --assess --type execute --verbose=4 Lite.app
xcrun stapler validate Lite.app
xcrun stapler validate Lite.dmg
spctl --assess --type open --context context:primary-signature --verbose=4 Lite.dmg

Then download the release DMG through a browser on a clean Mac, install Lite, and confirm:

  • codesign reports the Ultralytics Developer ID authority and a Team ID, not Signature=adhoc.
  • spctl accepts the application as a notarized Developer ID build.
  • The browser-downloaded app opens through the ordinary macOS confirmation with an Open button; it does not require Open Anyway in System Settings.
  • Updating from the preceding Lite release still succeeds through the existing signed Tauri updater.
  • The README's unsigned-app workaround is removed only after the published artifact passes the clean-machine check.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or requestpriority: highImportant and time-sensitive; should be prioritized in the next planning cycle

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions