How to Build Your Own Universal Installer for Mac Apps

Posted on July 29, 2022

Written by

Noah Anderson

Systems Engineer at Kandji

The job of installing apps on your organization’s Mac computers—one of the most fundamental responsibilities for any Apple admin—is complicated by the fact that there are still two different Mac processor types in use: Intel and Apple silicon. The continued coexistence of those two architectures means admins must often manage and deploy two different versions of any given app. 

Sometimes app developers make that easier by distributing Universal apps—combined binaries that will run on either architecture. Apple has been urging developers to convert their apps to Universal, but for a number of reasons, many vendors still haven’t heeded that advice. (Universal apps take more time and bandwidth to build and deliver; they are necessarily larger than single-architecture binaries.) 

So how do you efficiently deploy apps that don’t yet have Universal versions to the Mac computers you manage? 

One common strategy is to maintain two separate installers. This requires you to maintain logic in your software distribution solution to ensure the right package (PKG) goes to the right Mac. This can mean twice as much work for you.

Another strategy is to build a Universal installer of your own, in the form of a PKG that has the intelligence to detect what kind of computer it’s installing on and then deliver the right version. Here’s how to build such an installer yourself.

Building Your Own Universal Installer

If you download an app from the internet as an end user, it’ll commonly be either a DMG or a ZIP file containing an app bundle that you then move into the /Applications folder. If it’s a Universal app, you just fetch the one download. Some vendors let you download Universal installers, which check your system and install only the version of the app that’s correct for your particular Mac’s architecture.

But what if the app you want to install doesn’t have a Universal version or installer and, instead, has separate downloads for the two Mac architectures? And what if, as an admin, you want to deliver architecture-appropriate software to the /Applications folder of multiple Mac computers you manage, without packaging up two different apps and handling the complex scoping of how they'll be delivered?

If you use a device management solution such as Kandji, the delivery part isn’t that hard. But delivering the correct versions is still a sticky problem.

Our solution: We built a script—based on work we’ve done to make our Auto Apps—that creates a Universal macOS installer PKG. You can download that script from our GitHub repository. Here’s how it works.

Configuring the Script

First, you download the script, either by copying the code contents and pasting them into a new file on your Mac, or by cloning our support repo. More technical details about the code can be found in the project README.

You can then either edit it ahead of time, inserting some required bits of information (see below). Or you can run the script and enter those values when you're prompted; in this scenario, the script acts like an interactive template to generate new scripts for each application.

The advantage of this latter approach is that you can automatically save the values you've entered as a brand new script tied to that particular application. When the vendor releases a new update to one or both versions of that app, you can run the script again to create another Universal installer PKG.

Whether you’re editing ahead of time or using the prompts, you’ll need to supply the following specifics:

  • The name of the app. This is used to name the installer PKG file as well as the script (if you choose not to enter the values in this list ahead of time).
  • The download URLs for the app’s Apple silicon and Intel versions. These can be either DMG or ZIP files; it won’t work if the developer distributes separate installer PKGs for the two architectures. You need to do your own due diligence to assure yourself that the URLs are valid sources of trustworthy code. This is the trickiest part of the whole endeavor; we’ve got some advice on it below.
  • The developer ID. This is checked against the downloaded apps, to be sure they’re valid. 
  • The team identifier. Again, the script checks the identifier you supply against the identifier of the downloaded apps, to guarantee that whoever signed the app is a registered developer in good standing with Apple.

If any of those details are missing, the script will issue an error.

For that second item, if you're unable to find links directly from the software manufacturer, there are some curated open-source app repositories that you can explore to locate the app's download URLs.

Armin Briegel's Installomator project has some 450 titles on GitHub. Many of them include download links for both arm64 (Apple silicon) and i386 (Intel) apps. The package-management system Homebrew has a number of Casks—installers for GUI apps—on GitHub that can be inspected to see where they get their downloads.

In both examples, downloads are typically sourced directly from the vendor, but from a hidden address that can be difficult to locate. Building the download URLs may require you to replace variables with values that are defined elsewhere in code (or populated when run). Even if it takes a little parsing, this can oftentimes be much faster than inspecting web traffic or searching elsewhere for a reliable download if you can't find one directly from the vendor.

The developer ID and team identifier are used to check that the downloads are valid and secure. Among other things, the script confirms that the URL actually downloads an app that can run on the platform you want (Intel or Apple silicon). More specifically, they confirm that the developer ID and team identifier you originally trusted when you first ran the script match the newly downloaded apps that the script will package for distribution. You can also optionally use those details to confirm that the Intel and Apple silicon versions are the same. (You’ll have to disable that last option if you’re working with an app that—maddeningly—has different versions of the app for the two architectures.)

Running the Script

When you run the script, it builds the PKG. If the downloads fail any of the integrity or security checks, the script will display an error with more information about why it failed.

You then deliver your newly-built PKG to your managed Mac computers using the software distribution framework of your choice. When your software distribution framework runs that PKG, it actually uses the installer command. That command first runs the preinstall script embedded in the PKG to check the architecture of the Mac it’s running on, and then installer puts the appropriate version of the app in the /Applications folder.

There are dedicated programs that can assemble PKGs like this, but they can be complex to set up and orchestrate. Our script actually leverages tools that are built into macOS. 

Using those tools from the command line is cumbersome; you have to supply myriad details. Our script just takes care of those details for you, all while helping you trust the security of the software you're deploying.

If you’ve been around Mac management for a while, you’ll no doubt notice some similarities between this script and tools like AutoPkg and Installomator. We think ours builds on the shared knowledge and experience expressed in projects like those and offers some distinctive functionality. We hope it is worth sharing with the Mac admin community and that you find it instructive and useful.

About Kandji

The Kandji team is constantly working on solutions to streamline your workflow and secure all of your Apple devices. With powerful and time-saving features such as zero-touch deployment, one-click compliance templates, and plenty more, Kandji has everything you need to bring your Apple fleet into the modern workplace.

Request access to Kandji today.

Share post

Written by

Noah Anderson

Systems Engineer at Kandji

The Latest in Apple Enterprise Management