Notarize your app from the command line to handle special distribution cases.
The easiest way to notarize your app is through the Xcode user interface, as described in Notarizing Your App Before Distribution. However, if you have a more complex scenario, you can use command line tools to manually notarize your app. This workflow can be useful in a number of cases, like when you need to:
Notarize software you’ve already shipped.
Notarize plug-ins for other software packages.
Create complex distributions, like disk images or installer packages.
Add the notarization process to a scripted build environment.
Export a Package for Notarization
To prepare an app for notarization, you must export the app from Xcode. Using the Xcode interface, you automatically export your app when you click Distribute App in the Organizer window. But in a scripted build environment, you must use the
xcodebuild utility to perform the export. Because export directly follows archiving, the archive’s post-action script is a convenient place from which to perform the export. You can edit the post-action from the scheme editor in Xcode.
The script begins by exporting the archive with
xcodebuild which archive to export using an environment variable automatically defined by Xcode, and provide a location for the output by defining the
EXPORT variable. Use the
export flag to indicate an options property list that configures the export operation. You typically obtain this file by exporting from Xcode just once. The export options file appears alongside the app itself in the export directory:
Alternatively, you can create a custom export options property list file with a text or property list editor. For a complete description of the available keys, use the
Because you can't upload the
.app bundle directly to the notary service, you’ll need to create a compressed archive containing the app:
Alternatively, you can put apps, kernel extensions, and other software in a container, like a disk image, and notarize the container. The notary service accepts disk images (UDIF format), signed flat installer packages, and ZIP archives. It processes nested containers as well, like packages inside a disk image.
Upload Your App to the Notarization Service
You upload your app for notarization using
altool. Xcode 10 or later supports notarization, so if you have more than one version of Xcode installed on your Mac, be sure to use the
xcode-select utility to choose the appropriate version:
You can then use
xcrun to invoke the
altool command with the
The notary service generates a ticket for the top-level file that you specify, as well as each nested file. For example, if you submit a disk image that contains a signed installer package with an app bundle inside, the notarization service generates tickets for the disk image, installer package, and app bundle.
primary-bundle-id flag—which is required—to specify an identifier that helps you keep track of automated correspondence from the notarization service. The value you give doesn’t need to match the bundle identifier of the submitted app or have any particular value. It only needs to make sense to you. The notarization service includes the value whenever it emails you regarding the given
password flags to supply your App Store Connect credentials. Because App Store Connect now requires two-factor authentication (2FA) on all accounts, you must create an app-specific password for
altool, as described in Using app-specific passwords.
To avoid including your password as cleartext in a script, you can provide a reference to a keychain item, as shown in the previous example. This assumes the keychain holds a keychain item named
AC with an account value matching the username
AC. Note that
altool can’t access your iCloud keychain for security reasons, so the item must be in your login keychain. You can add a new keychain item using the Keychain Access app, or from the command line using the
altool succeeds, it prints a request identifier:
Request to use later when checking the status of your request. For more information about
altool and its required flags, use the
Check the Status of Your Request
After uploading your app, the notarization process typically takes less than an hour. When the process completes, you receive an email indicating the outcome. Additionally, you can use
altool with the
notarization-history flag to inspect the status of all of your notarization requests:
Passing a page value of 0, as in the above example, returns the most recent requests, and prints a table of results:
To obtain detailed information about a particular submission, use
altool along with the
notarization-info flag and the UUID for the submission or from the history table above:
Among other details, the tool reports a log file URL that you can use to download a JSON-formatted log file:
The log file enumerates any issues that notarization found.
For information about how to deal with common problems, see Resolving Common Notarization Issues.
Staple the Ticket to Your Distribution
Notarization produces a ticket that tells Gatekeeper that your app is notarized. After notarization completes successfully, the next time any user attempts to run your app on macOS 10.14 or later, Gatekeeper finds the ticket online. This includes users who downloaded your app before notarization.
You should also attach the ticket to your software using the
stapler tool, so that future distributions include the ticket. This ensures that Gatekeeper can find the ticket even when a network connection isn’t available. To attach a ticket to your app, use the
While you can notarize a ZIP archive, you can’t staple to it directly. Instead, run
stapler against each individual item that you originally added to the archive. Then create a new ZIP file containing the stapled items for distribution. Although tickets are created for standalone binaries, it’s not currently possible to staple tickets to them.
Ensure Your Build Server Has Network Access
To incorporate notarization into a custom workflow, your build server needs access to certain network resources.
In particular, because
altool is a front end for the Transporter command line tool, it uses the same IP address ranges and ports as that tool. See System and network requirements in the Transporter User Guide for details.
stapler uses CloudKit to download tickets, which requires access to the following IP address ranges, all on port 443: