Distributing Scripts for macOS: Workspace ONE Operational Tutorial

VMware Workspace ONE UEM 9.4 and later



VMware provides this operational tutorial to help you with your VMware Workspace ONE® environment. In this tutorial, you leverage internal apps to deliver scripts as payload-free packages. This process includes creating, preparing, and deploying a payload-free package in Workspace ONE UEM.


This operational tutorial is intended for IT professionals and Workspace ONE administrators of existing production environments. 

Both current and new administrators can benefit from using this tutorial. Familiarity with macOS, XML, and basic scripting is assumed.

Knowledge of additional technologies such as VMware Workspace ONE® Intelligence and VMware Workspace ONE® UEM is also helpful.

Distributing Scripts as Internal Apps for macOS


Workspace ONE UEM offers two methods to distribute non-store software packages to macOS: internal apps (newer) and products (legacy). These two software delivery methods can be used to deliver and execute scripts for macOS. This tutorial focuses on leveraging internal apps to deliver scripts as payload-free packages. 


Before you can perform the procedures in this tutorial, you must satisfy the following requirements.

  • Apple device running macOS version 10.12.6 (Sierra) or later
  • VMware Workspace ONE Intelligent Hub for macOS version 3.0 or later
  • Workspace ONE UEM version 9.4 or later

Ensure you are logged in to the machine used to create the internal app using a payload-free package and install the following:

Note: Although a Developer ID Installer Certificate is not required to build a payload-free package, it is considered a best practice by the macOS community.

For more information, see the VMware Identity Manager Documentation and VMware Workspace ONE UEM Documentation.

Creating a Payload-Free Package

In a macOS installer package, a number of scripts and files are executed and installed by the installer process on macOS. The installer process within macOS also supports packages that do not contain a list of files to install (for example, payload-free). In these packages that contain no files to install to the filesystem, the package defines a format whereby scripts can be executed within macOS.  

1. Create Folder Structure

non-store payload-free software packages
  1. Select the Finder icon on the dock.
  2. Create a new folder with the script's intended function in the location of your choice.
    • In the example shown, the package folder structure is located in ~/Desktop/Install-Software-Updates
  3. Create the necessary folder structure for the payload-free package as shown in the screenshot.

Folder descriptions are as follows:

  • build — this folder contains the output (for example, the payload-free package) created by the pkgbuild commands
  • payload — this folder contains a blank set of folders (private > var > tmp) to force the package to leave a receipt
  • scripts — this folder contains the preinstall and postinstall script (for example, the script content you wish to execute on the device)

Note: Although a true payload-free package contains only the pre/post install script, the lack of a payload prevents the installer from generating a receipt file when the package is installed. Without a receipt file, the framework underlying Workspace ONE UEM's internal apps for macOS will continually execute the package (for example, re-run the script). As such, we can supply a basic set of filesystem folders so the resultant payload-free package leaves a receipt file when it completes successfully.

2. Create Preinstall/PostInstall File

non-store payload-free software packages
  1. Select Applications > Utilities > Terminal.app to open Terminal.app in Finder
  2. Create the postinstall script file and make it executable by running the following commands:
cd ~/Desktop/Install-Software-Updates/scripts/
touch postinstall
chmod a+x postinstall

Note: Flat Packages can contain two scripts: preinstall and postinstall. For a payload-free package used to execute a script, leverage the postinstall script.

The preinstall script runs before any files are modified (and must return zero or Installer will cancel the installation). Although less applicable for a payload-free package built only to execute a script, preinstall can be used in complex packages for software delivery (such as a bootstrap package) for pre-install checks.   The postinstall script runs after any files are installed/modified. The postinstall script must also return zero or Installer will cancel the installation.  

3. Open PostInstall File For Modification

non-store payload-free software packages
  1. Right-click the postinstall file.
  2. Click Open With.
  3. Select your script editor (such as Visual Studio Code).

4. Modify PostInstall File

non-store payload-free software packages
  1. Paste the following script sample into the postinstall file in your script editor.

/usr/sbin/softwareupdate -i -a -R
  1. Save the updated postinstall file in your script editor (File > Save in Visual Studio Code as shown in the screenshot).

Note: The parameters used for the softwareupdate command (installall updates, and restart) can be found by entering man softwareupdate in Terminal.app.

5. Determine Developer ID Installer Certificate Common Name

non-store payload-free software packages
  1. Select Applications > Utilities > Keychain Access.app to open the Keychain Access.app.
  2. Click the login keychain.
  3. Find the Developer ID Installer certificate.
  4. Copy the title of the Developer ID Installer certificate (this should match the Common Name).

6. Build Payload-Free Package

non-store payload-free software packages
  1. Paste the following command line (modify as required) into Terminal and enter the administrative account password when prompted by sudo.
  2. Note the payload-free package in the build folder.
sudo pkgbuild --install-location / --identifier "com.vmware.install-software-updates" --version "1.0.0" --root ~/Desktop/Install-Software-Updates/payload --scripts ~/Desktop/Install-Software-Updates/scripts --sign "Developer ID Installer: ROBERT Terakedis (3F4YZT75BH)" ~/Desktop/Install-Software-Updates/build/Install-Software-Updates.pkg

Note: In the pkgbuild command line, supply modified values as appropriate (bolded in the previous command line):

  • identifier — generally in the format of com.<company>.<script purpose>
  • version — the version of the script being deployed
  • root — filesystem location of the payload folder
  • scripts — filesystem location of the scripts folder (containing preinstall and/or postinstall scripts)
  • sign — use the common name of the appropriate developer ID installer certificate
  • output package path and file name

Important: When modifying the content of the package, it is critical to increment the version number in the pkgbuild command line. Failure to increment the version with each rebuild may result in problems during testing, particularly for devices which have already installed a previous version of the package.

Preparing a Payload-Free Package for Deployment

Having created the script and packaged it into a payload-free package, the next step is to prepare the script for deployment as an internal app. This section covers generating the necessary metadata for the package and reviewing key pieces of the metadata which could be modified.

1. Launch VMware AirWatch Admin Assistant

  1. In Finder, click Applications.
  2. Double-click VMware AirWatch Admin Assistant.app.

2. Drag and Drop Payload-Free Package

  1. Locate the package you created with the pkgbuild command.
  2. Drag and drop the package onto the VMware AirWatch Admin Assistant.

3. Parse and Reveal Files

  1. Review the status as the package is processed and wait for the green checkmark to indicate completion.
  2. Click Reveal in Finder in the pop-up window.

4. Review Output from VMware AirWatch Admin Assistant

  1. In the Finder window, expand the folder named after your <Package Name>-<Version>. (Install-Software-Updates-1.0.0 in the example). Note the existence of the PKG and the corresponding plist.
  2. Right-click the plist file and point to Open With.
  3. Select your text editor (such as Visual Studio Code, Atomic, BBEdit, and so on).

5. Note Use of Receipts Key

  1. The receipts key determines if the script package has been executed. By adding a payload in the package (even though it is an empty folder structure), the package outputs a BOM and Plist file to the receipts folder.
  2. On a device that executed the script package, a new bom and plist file is created when the package completes successfully. The output in the screenshot is based on the example in this tutorial (install-software-updates). These are the files being searched using the receipts key in the plist output by VMware AirWatch Admin Assistant.

Note: Receipts are added to /private/var/db/receipts when a package with a payload (folder structure -- even if empty) is executed. If a payload structure is not included (or the --root parameter is excluded from the pkgbuild command), no receipts are left when the package is installed.

6. Alternatives to Receipts Key

In lieu or addition to the receipts key, administrators can also modify the generated plist file to include other methods for determining when the package should be installed. Commonly used keys include the Installs and installcheck_script keys. These keys can be useful in helping Workspace ONE UEM determine whether a new version of the script needs to take any action if a prior version of the script has already ran.

For more information on the differences between the receipts key and installs/installcheck_script keys, see  the munki documentation

Logging In to the Workspace ONE UEM Console

In this exercise, you log in to the Workspace ONE UEM Console as an administrator.

1. Open Safari Web Browser

On your macOS device, select the Safari icon on the dock.

3. Enter Your User Name

  1. Enter your Username, for example, administrator.
  2. Click Next. After you click Next, the Password text box is displayed.

4. Enter Your Password

  1. Enter your Password, for example, VMware1!
  2. Click Login.

Note: If you see a Captcha, be aware it is case sensitive.

Deploying a Payload-Free Package in Workspace ONE UEM

In this exercise, add the payload-free package as an internal app in the Workspace ONE UEM Console. This sends the package to the enrolled devices in the appropriate assignment groups, and executes your script with root privileges.

1. Navigate to Native Internal Application Settings

  1. Click Apps & Books.
  2. Expand Applications.
  3. Click Native.
  4. Click Internal.
  5. Click Add Application.

2. Initiate Application File Upload

Click Upload.

3. Choose File

Select Choose File.

4. Select the Application File

  1. Select the Documents folder.
  2. Select VMware AirWatch Admin Assistant.
  3. Expand your Payload-Free Package (Install-Software-Updates-1.0.0 in the example).
  4. Select the package file (Install-Software-Updates-1.0.0.pkg)/
  5. Click Choose.

5. Save the Application File

Click Save.

6. Review the Application File

Verify that you uploaded the correct Application File, and click Continue.

7. Initiate Metadata File Upload

Click Upload.

Note: If you forgot to generate the metadata file and are working from a computer where the VMware AirWatch Assistant is not installed, click the VMware AirWatch Assistant for macOS link to download it directly.

8. Choose File

Click Choose File.

9. Select the Metadata File

  1. Select the Documents folder.
  2. Select VMware AirWatch Admin Assistant.
  3. Expand your Payload-Free Package (Install-Software-Updates-1.0.0 in the example).
  4. Select the package file (Install-Software-Updates-1.0.0.plist).
  5. Click Choose.

10. Save the Metadata File

Click Save.

11. Review the Metadata File

  1. Verify you uploaded the correct Metadata File.
  2. Click Continue.

12. Review the Scripts Tab

  1. Select the Scripts tab.
  2. The Pre-Install Script runs before the Intelligent Hub executes the dmg/pkg/mpkg file that installs the application and can be used to set-up prerequisite items before the installer runs. The Pre-install Script must have an exit code of zero (0) for the install to proceed.
  3. The Post-Install Script runs after the Intelligent Hub executes the dmg/pkg/mpkg file. This can be useful for applying configurations after the software completes the installation.
  4. The Pre-Uninstall Script runs before the Intelligent Hub initiates the uninstall. The Pre-Uninstall script must have an exit code of zero (0) for the uninstall to proceed.
  5. The Uninstall Method defines how the Intelligent Hub uninstalls software. Typically, Remove Copied Items is used for a DMG installer, and Remove Packages is used for a PKG installer.  
  6. The Post-Uninstall Script provides a method to validate an uninstall was completed and potentially handle any cleanup for the uninstall.
  7. The Install Check script assists the Intelligent Hub to determine whether an install needs to happen.  This script can be useful for desired state purposes and ensuring that a software install remains intact on a user's machine. If the script has an exit code of zero (0), the agent assumes an Install is needed.
  8. The Uninstall Check Script validates whether an uninstall has occurred. If the script has an exit code of zero (0), the Intelligent Hub determines an uninstall is (or is still) required.

Note: Use the pre and post install scripts to avoid repackaging installers. By including scripts, you can automate tasks that would normally be prompted for the user to resolve before/after an install. For more information, see the munki Wiki.

Important: Scripts must include the shebang (#!) statement on the first line. Examples include the following:


13. Review the Deployment Tab

  1. Select the Deployment tab.
  2. Note the ability to add Blocking Applications. This allows you to specify if any applications need to be closed by the user before the install can proceed.
  3. Expand the Restart Action drop-down menu to view the available options.
  4. Use Conditions to further constrain the deployment. For more information, see the munki Wiki.  

14. Review Terms of Use and Save

  1. Select the Terms of Use tab.
  2. Review the ability to add terms of use to a software title.  
  3. Click Save & Assign.

15. Initiate Assignment

Click Add Assignment.

16. Configure Assignment Settings

  1. Select the assignment group that you want to target. In this example, we're targeting the entire Organization Group.
  2. For the App Delivery Method, select Auto .
  3. For Desired State Management, select Disabled.
  4. For Remove on Unenroll, select Disabled.
  5. Click Add.

17. Save and Publish

  1. Ensure your recently added Assignment shows in the list of Assignments.
  2. Click Save & Publish.

18. Publish the Application

Click Publish.

19. Verify the Application Published

On the Internal tab, verify the application published successfully by locating it in the list view.

Summary and Additional Resources


This operational tutorial provided steps to distribute scripts as internal apps for macOS.

Procedures included: 

  • Creating a payload-free package
  • Preparing a payload-free package for deployment
  • Deploying a payload-free package in Workspace ONE UEM

Additional Resources

For more information about Workspace ONE, explore the VMware Workspace ONE Activity Path. The activity path provides step-by-step guidance to help you level-up in your Workspace ONE knowledge. You will find everything from beginner to advanced curated assets in the form of articles, videos, and labs.

Additionally, you can check out the VMware Workspace ONE and VMware Horizon Reference Architecture which provides a framework and guidance for architecting an integrated digital workspace using VMware Workspace ONE and VMware Horizon. 

For more information on macOS, see Understanding macOS Management

About the Author

This tutorial was written by:

  • Robert Terakedis, Senior Technical Marketing Manager, End-User-Computing Technical Marketing, VMware


Your feedback is valuable. 

To comment on this tutorial, contact VMware End-User-Computing Technical Marketing at euc_tech_content_feedback@vmware.com.

Filter Tags

Workspace ONE Workspace ONE UEM Document Operational Tutorial Intermediate macOS Deploy Modern Management