Anthony’s Mac Labs Blog

📦 Deploying Adobe Software with JamfUploader

Posted 2022 November 08

This past weekend, Darren Wallace posted a Recommended workflow to deploy Adobe software with Jamf Pro. It nicely describes everything step-by-step and has appendices that deal with some common issues. If you haven’t read this yet, go do that now, as this post should be considered to be an adjunct to Darren’s. I’m going to describe how I replace some of the manual steps in Darren’s workflow by using AutoPkg and JamfUploader. Let me follow the same format as Darren’s post:

  1. Obtaining your Adobe Packages
  2. Uploading to Jamf Pro
  3. Deployment

Obtaining your Adobe Packages

My process is exactly the same as Darren’s: create a single-app “package” from the Adobe console, download the generated disk image, run the Adobe Package Downloader app from the mounted disk image, and manually uncompress the zipped payload that Adobe Package Downloader downloads. The only thing that is important to note is that I use the default location for downloading with Adobe Package Downloader, namely ~/Downloads.

Uploading to Jamf Pro

I used to do it the same way as Darren suggests — specifically, I uploaded the Install pkg using Jamf Admin, which automatically took care of zipping the pkg. Now I have AutoPkg automate this part of the process.[1] The automation does the following:

  1. Locates the Install.pkg on the local system.
  2. Determines the version of the app in the pkg.
  3. Renames the pkg filename by appending the version number to the name.
  4. Uploads the pkg using the JamfPackageUploader processor in AutoPkg.

The first two steps are handled nicely by using the AdobeAdminConsolePackagesPkgInfoCreator custom processor written by the folks at dataJAR. Even though they wrote that processor in the context of preparing Adobe packages for Munki, it works for this workflow as well. AdobeAdminConsolePackagesPkgInfoCreator has two dependencies:

For my automation, I used the Old School method of writing a single recipe that I would override with different Input values (for NAME) for each product.[2] That recipe is AdobeAdminConsole.pkg.recipe. Because AdobeAdminConsolePackagesPkgInfoCreator collects the version number, I can use that to rename my Adobe installer pkg. So my AutoPkg .pkg recipe has two processor steps:

  1. Processor: com.github.dataJAR-recipes.munki.Adobe Lightroom Classic/AdobeAdminConsolePackagesPkgInfoCreator
    Result: Values returned for aacp_install_pkg_path and version
  2. Processor: PkgCopier
    Result: pkg_path (renamed pkg) set to NAME-version.pkg

Since I run AutoPkg on an APFS system, duplicating the large installer pkg (so that I can change the name) does not take up any significant space. As an added bonus, using PkgCopier sets the variable pkg_path to the location of the renamed pkg installer, which is what other processors (JamfPackageUploader, in this case) expect.

The final part of automating the upload is using the JamfPackageUploader processor. Using standard AutoPkg authoring practices, I created a new .jamf recipe with that processor whose parent is my AdobeAdminConsole.pkg recipe.[3] JamfPackageUploader takes care of zipping the Adobe pkg installer, so you do not have to do that manually.


My context is that I am running a shared computer lab; Self Service is not in the picture. So for all the Adobe apps that I wish to deploy, I use a Jamf Pro policy that installs the Adobe app on enrolment (or on next check-in if scoped after enrolment) and, in case of failure, retries the installation up to 2 more times before giving up. Once successfully installed, I then use Adobe’s Remote Update Manager (RUM) to keep the apps up to date until I deploy the next major version. Let me break that down into the policies I use to make that happen:

Prior to using the JamfUploader processors, I used a single, manually-crafted policy to deploy all eight apps that we support. This was still more flexible than creating a multi-app Adobe package because if only one or two apps got an update, I could just substitute updated packages for those apps. But as Darren’s article mentioned, installation failures can and do happen. In that previous scenario, if one app failed to install, it tried to reinstall every app on the next attempt. The real beauty of automating the policy creation with AutoPkg and the JamfPolicyUploader processor is that I can create a separate policy for each app with very little effort. Then, any retries are efficient and it is easier to track what failed.

Thus, the rest of my .jamf recipe (after the JamfPackageUploader processor) follows a standard pattern:

  1. Processor: StopProcessingIf
    Result: Recipe stops if pkg_uploaded == False
  2. Processor: com.github.grahampugh.jamf-upload.processors/JamfPolicyUploader
    Result: Policy is created/replaced based on the template specified

I then override the .jamf recipe multiple times — once for each Adobe product I am deploying. For example, I would create an override for Photoshop 2023 like this:[4][5]

autopkg make-override AdobeAdminConsole-latest.jamf -n AdobePhotoshop2023-latest.jamf

I would then go in to the newly-created override and change the NAME Input variable value to match the name I gave the “package” in the Adobe Admin Console, which in my case looks something like SDL_Photoshop_2023. Once the overrides are created, all I need to do to update that app in Jamf Pro is to download the new version from the Adobe Admin Console, unzip it, and then run the override. The new pkg installer will be uploaded, versioned, and my policy will be updated with the new pkg.

Finally, I mentioned that I only use the Jamf Pro policies created through this process to do the initial install. I have one hand-crafted Jamf Pro policy that runs RUM once every week (I guess you could call it a RUM runner 😆). It is a policy that runs a single command using the Files and Processes payload. In the Execute Command field, I entered this:

/usr/local/bin/RemoteUpdateManager --action=install

That triggers RUM to install any available (minor version) updates. If you want to know more about RUM, Darren has an excellent blog post on it as well.


If this post was more detailed than you would like and you just want a list of steps to follow to make this happen, I have a ReadMe in my repo along side the AdobeAdminConsole.pkg and .jamf recipes I have discussed here that does just that (excluding the discussion of RUM). But I hope that this post both supplements what Darren had to say on this topic and gives you a little more insight into what I am doing so that you can decide which parts of my workflow might be useful in your context.

[1] In my case, I use the same Mac that runs AutoPkg to download installers from the Adobe Admin Console. That makes it work easily with the AdobeAdminConsolePackagesPkgInfoCreator processor. If you need to use separate computers for those two tasks, take note of the appendix in Darren’s post regarding Moving downloaded Adobe packages prior to upload. [Return to main text]

[2] In the dataJAR .munki recipes, they provide a recipe for each product that uses a documented naming convention. (These recipes are duplicates of each other with the NAME variable and Description changed.) What I determined when looking at their code is that you could use any value for NAME; Munki users could override the dataJAR recipes to use a different naming convention, as long as it matched the name used in the console when creating the “package.” So the fact that I didn’t use their naming convention (or that I didn’t use Munki) did not prevent me from using their processor because of the flexible way in which it was written. [Return to main text]

[3] Since I want my recipe to fail if the pkg_category I supply does not exist on my Jamf Pro instance, I use the JamfPackageUploader processor on its own, but you may choose to precede it with a JamfCategoryUploader processor if you would prefer that the category be created if it is not present. [Return to main text]

[4] You can also make the override in AutoPkgr by Control- or Right-clicking on the AdobeAdminConsole.pkg recipe from the list of recipes, selecting Create Override from the contextual menu, and then renaming the override when prompted. It uses the exact same AutoPkg command under the hood to create the override. [Return to main text]

[5] By convention, any .jamf recipe that doesn’t match the functionality of an old .jss recipe has an additional label added, in the form of RecipeName-label.jamf.recipe. In my case, a recipe whose goal is to create/update a Jamf Pro policy so that it has the latest version of the app installer as its payload gets the label latest. I discuss my naming convention in more detail in the presentation I did with Graham Pugh for the Mac Admins 2022 Campfire Sessions — see Slide 29. [Return to main text]