macOS Package Wizard Best Practice
Discover essential best practices for efficiently creating macOS packages with the Package Wizard, enhancing deployment and user experience.
Table of Contents
Overview
The Matrix42 Mac Package Wizard is a tool that allows Empirum administrators to create easy-to-distribute application packages for macOS quickly. Packages are created in a format that can be imported directly into the Empirum Management Console (EMC) via the Software Depot.
The Mac Package Wizard can be found on the Empirum server at:
\\EmpirumServer\Empirum$\AddOns\Mac Package WizardCopy it to a Mac with administrator privileges via Finder or by mounting:
smb://EmpriumServer/Empirum$Functional Scope
- Easy packaging of
.app,.pkg,.mpkg,.dmg, and.shfiles - Packages are produced in the Empirum import format, ready for the Software Depot
- Integrated install and uninstall mechanism
- Supports packaging of the Mac OS X Empirum Agent and Mac OS X Inventory
- Creation of macOS images from macOS installers (including macOS 10.13), importable and distributable via Empirum
- PKG creation support via integration with Packages.app
Notes and Restrictions
Successful packaging and distribution is only guaranteed with Empirum version 16.0.1 or higher, since Mac.inc.sh was modified in that release.
- Applications purchased from the Apple Mac App Store cannot be packaged. They must be installed via the Mac App Store with an Apple ID.
- Apple provides no standard uninstall procedure. When a package is uninstalled,
.appfiles are deleted based on the product name in the application directory. A sample uninstall script is provided in the Package Wizard for.mpkg,.pkg, and.shfiles. - For self-created DMG images, the names of included files must match the name of the application (e.g.,
Cyberduck.appmust be inCyberduck.dmg). - Before installing an
.appfile, the agent always attempts to delete any existing app with the same name in/Applications. - After an
.appis copied to/Applications, the quarantine flag is removed viaxattr -d -r com.apple.quarantine.
Examples of Use
Package a .app File (Example: Mozilla Firefox)
- Install and launch the Mac Package Wizard on an Apple Mac.
- Download the Firefox DMG from the official Mozilla website.
- Mount the DMG and copy
Firefox.appto any location (e.g.,~/Desktop). Unmount the DMG. - Drag and drop
Firefox.apponto the Mac Package Wizard. A success icon and Next button will appear. - Review and correct the scanned metadata: product manufacturer, product name, product version, and revision (default: 0).
- Click Next and select the supported operating systems.
- Click Create and choose a save location. The package is now ready for import into the EMC Software Depot.
Package a PKG, MPKG, or Shell Script
- Install and launch the Mac Package Wizard on an Apple Mac.
- Drag and drop the
.pkg,.mpkg, or.shfile onto the Mac Package Wizard. A success icon and Next button will appear. - Review and correct the scanned metadata (manufacturer, product name, version, revision).
- Click Next and select the supported operating systems.
- Unlike
.apppackaging, the wizard now presents an uninstall script editor where you can define a Bash-based uninstallation routine. - Complete the wizard to produce the importable package.
Package an App with a Custom Settings File (Example: Cyberduck)
This example demonstrates how to package an application together with a pre-configured preferences file, so all users receive predefined settings on installation.
Step 1: Create the Installation Script
Create a script named CyberduckScript.sh (the script name must differ from the app name to prevent conflicts):
#!/bin/sh
# CyberduckScript.sh
syslog -s -l warning "Emprium Agent installing Cyberduck with preferences"
syslog -s -l warning "Step 1"
syslog -s -l warning "Installing Cyberduck.app"
sudo /bin/cp -rf "/Volumes/CyberduckScript/Cyberduck.app" "/Applications/Cyberduck.app"
syslog -s -l warning "Step 2"
syslog -s -l warning "Copy config file .plist to all users ~/Library/Preferences/"
userlist=$(/usr/bin/dscl . list /Users | grep -v '_' | grep -v 'Guest' | grep -v 'daemon' | grep -v 'macports' | grep -v 'nobody' | grep -v 'root')
for user in $userlist
do
sudo /bin/cp "/Volumes/CyberduckScript/ch.sudo.cyberduck.plist" "/Users/$user/library/preferences/"
sudo /usr/sbin/chown "/Users/$user/library/preferences/"
doneStep 2: Create the Uninstall Script
#!/bin/sh
# uninstall.sh — Matrix42 AG Mac Package Wizard
syslog -s -l warning "Emprium Agent running uninstall.sh"
if [ -d "/Applications/Cyberduck.app/" ]
then
/bin/rm -fR "/Applications/Cyberduck.app"
syslog -s -l warning "/Applications/Cyberduck.app was removed"
else
syslog -s -l warning "/Applications/Cyberduck.app not found"
fi
userlist=$(/usr/bin/dscl . list /Users | grep -v '_' | grep -v 'Guest' | grep -v 'daemon' | grep -v 'macports' | grep -v 'nobody' | grep -v 'root')
for user in $userlist
do
if [ -f "/Users/$user/Library/Preferences/ch.sudo.cyberduck.plist" ]
then
/bin/rm -fR "/Users/$user/Library/Preferences/ch.sudo.cyberduck.plist"
syslog -s -l warning "/Users/$user/Library/Preferences/ch.sudo.cyberduck.plist was removed"
else
syslog -s -l warning "/Users/$user/Library/Preferences/ch.sudo.cyberduck.plist not found"
fi
doneStep 3: Build the Package
- Package
CyberduckScript.shwith the Mac Package Wizard and save to Desktop. - Delete the auto-generated
~/Desktop/{UUID}/Data/CyberduckScript.dmg. - Open Disk Utility and create a new read-write DMG named
CyberduckScript, saved to~/Desktop/{UUID}/Data/. Size the image slightly larger than the total content (e.g., 250 MB for a ~200 MB app). Ensure all name fields use the same name. - Copy the following into the new DMG:
Cyberduck.appCyberduckScript.shch.sudo.cyberduck.plistuninstall.sh
- Make the scripts executable:
sudo chmod a+x /Volumes/CyberduckScript/CyberduckScript.sh
sudo chmod a+x /Volumes/CyberduckScript/uninstall.sh- Unmount the DMG and import the package into the EMC.
After deployment, Cyberduck is installed in /Applications and all users on the system receive the pre-configured bookmarks via the copied preferences file.
Package an App with a License File (Example: Avira Antivirus)
- Download the latest
Avira_Antivirus.pkgfor Mac. - Drag and drop the PKG onto the Mac Package Wizard. Enter: Vendor: Avira GmbH, Name: Avira Antivirus, Version: 3.5.1, Revision: 0. Create the package.
- Open the package's
{UUID}/Data/folder and mount the DMG. - Rename
Avira_Antivirus.pkgtoAvira_Antivirus_Installer.pkginside the mounted image. (This allows the agent to find the.shscript by product name instead.) - Drag the license file (
hbedv.key) into the mounted image. - Create
Avira Antivirus.shwith the following content and save it into the image:
#!/bin/sh
# Avira Antivirus.sh — Matrix42 AG Mac Package Wizard
syslog -s -l warning "Emprium Agent running Avira Antivirus.sh"
# Copy the licence file
if [ -d "/Library/Application Support/Avira/" ]
then
sudo /bin/rm "/Library/Application Support/Avira/pro.key"
else
sudo /bin/mkdir "/Library/Application Support/Avira/"
fi
sudo /bin/cp "/Volumes/Avira Antivirus/hbedv.key" "/Library/Application Support/Avira/pro.key"
# Install AntiVirus
sudo /usr/sbin/installer -pkg "/Volumes/Avira Antivirus/Avira_Antivirus_Installer.pkg" -target /- Edit
uninstall.shwith the following content:
#!/bin/sh
# uninstall.sh — Matrix42 AG Mac Package Wizard
syslog -s -l warning "Emprium Agent running uninstall.sh"
if [ -d "/Applications/Utilities/Avira-Uninstall.app/" ]
then
sudo "/Applications/Utilities/Avira-Uninstall.app/Contents/MacOS/uninstall"
sudo /bin/rm "/Library/Application Support/Avira/pro.key"
syslog -s -l warning "/Applications/Avira Antivirus.app was removed"
else
syslog -s -l warning "/Applications/Avira Antivirus.app not found"
fi- Make the scripts executable:
sudo chmod a+x /Volumes/Avira\ Antivirus/Avira\ Antivirus.sh
sudo chmod a+x /Volumes/Avira\ Antivirus/uninstall.sh- Unmount the image and import the package into the EMC.
The Empirum Agent executes Avira Antivirus.sh because the metainformation in the package matches the script name. This is why the original PKG was renamed — it prevents the agent from executing the PKG directly.
The Matrix42 PKGs ShowInventory.pkg and EmpirumAgent.pkg are automatically recognized as Matrix42 products. In this case the uninstall window is skipped, and a prompt for a configuration file appears instead. A static computer name option is also available.
Package and Distribute Microsoft Office 365
- Assign the appropriate Office 365 license to the target user in your Microsoft admin portal.
- Download the latest Office 365 installer PKG from Microsoft.
- Use the Mac Package Wizard to package the PKG.
- Specify the following script as
uninstall.shduring packaging:
#!/bin/sh
# uninstall.sh — Matrix42 AG
syslog -s -l warning "Empirum Agent running uninstall.sh"
syslog -s -l warning "Step 1 — Removing Office Apps from /Applications"
/bin/rm -rf "/Applications/Microsoft Excel.app"
/bin/rm -rf "/Applications/Microsoft PowerPoint.app"
/bin/rm -rf "/Applications/Microsoft Word.app"
/bin/rm -rf "/Applications/Microsoft Outlook.app"
/bin/rm -rf "/Applications/Microsoft OneNote.app"
syslog -s -l warning "Step 2 & 3 — Removing user directories and Dock icons"
userlist=$(/usr/bin/dscl . list /Users | grep -v '_' | grep -v 'Guest' | grep -v 'daemon' | grep -v 'macports' | grep -v 'nobody' | grep -v 'root')
for user in $userlist
do
/bin/rm -rf "/Users/$user/Library/Containers/com.microsoft.errorreporting"
/bin/rm -rf "/Users/$user/Library/Containers/com.microsoft.Excel"
/bin/rm -rf "/Users/$user/Library/Containers/com.microsoft.Outlook"
/bin/rm -rf "/Users/$user/Library/Containers/com.microsoft.PowerPoint"
/bin/rm -rf "/Users/$user/Library/Containers/com.microsoft.Word"
/bin/rm -rf "/Users/$user/Library/Containers/com.microsoft.onenote.mac"
/bin/rm -rf "/Users/$user/Library/Containers/UBF8T346G9.ms"
/bin/rm -rf "/Users/$user/Library/Containers/UBF8T346G9.Office"
/bin/rm -rf "/Users/$user/Library/Group Containers/UBF8T346G9.ms"
/bin/rm -rf "/Users/$user/Library/Group Containers/UBF8T346G9.Office"
# Remove Dock icons
for app in "Microsoft Excel" "Microsoft Outlook" "Microsoft PowerPoint" "Microsoft Word" "Microsoft OneNote"
do
dloc=$(defaults read com.apple.dock persistent-apps | grep file-label | awk "/$app/ {printf NR}")
dloc=$[$dloc-1]
/usr/libexec/PlistBuddy -c "Delete persistent-apps:$dloc" "/Users/$user/Library/Preferences/com.apple.dock.plist"
done
sleep 3
/usr/bin/killall Dock
done- Distribute the package using the macOS Empirum Agent.
After successful installation, the user logs into Office 365 with their email address. The assigned license activates automatically and all installed Office apps become usable.
Package and Distribute Adobe Creative Cloud Suite
Adobe Creative Cloud packaging requires the Creative Cloud Packager application for Mac. Prerequisites:
- Adobe Creative Cloud license (Enterprise or Teams)
- Administrator account
- Creative Cloud Packager app for Mac
- Mac client
- Matrix42 Mac Package Wizard
Step 1: Create a Package with Creative Cloud Packager
- Install the Creative Cloud Packager and follow the setup wizard. Sign in with your Creative Cloud Administrator credentials.
- Choose Package or License Package as the package type.
- Enter a package name, save path, and your company/organisation name. Select Named License as the license type.
- Optionally allow end users to download additional software and updates from Adobe Creative Cloud.
- Select the Adobe products to include. The packager downloads all chosen applications — ensure sufficient disk space.
- Once complete, a
builddirectory is created containing two PKG files: one for installation, one for uninstallation.
Step 2: Package with Mac Package Wizard
Package the installation PKG using the Mac Package Wizard as usual. For uninstallation, choose one of two options:
-
Use Adobe's uninstall PKG (from the
builddirectory): package it separately with the Package Wizard and manage attachment/detachment manually in the EMC. -
Use the embedded uninstall routine (recommended): open the Package Wizard-created package, mount the DMG in the
/datafolder, drag Adobe's uninstall PKG into the mounted DMG, then edituninstall.shto include:
sudo installer -pkg /Volumes/<VolumeName>/NameDer_Uninstall.pkg -target /Step 3: Upload and Distribute
Import the package into the EMC Software Depot and attach it to the target clients. The Mac Agent recognizes and installs the software automatically.
Package McAfee Agent and Threat Prevention
- Download the latest McAfee Agent and McAfee Threat Prevention for Mac.
- Rename
McAfee Threat Prevention.pkgtoMcAfeeThreatPrevention.pkg. - Create a script named
McAfee Agent.sh:
#!/bin/bash
# McAfeeAgent.sh — (c)2000-2018 Matrix42 AG
echo "[McAfee Agent] - START INSTALLATION PROCESS"
/Volumes/McAfee\ Agent/install.sh -i
echo "[McAfee Agent] - FINISHED INSTALLATION PROCESS"
echo "[McAfee-Threat-Prevention] - START INSTALLATION PROCESS"
installer -pkg /Volumes/McAfee\ Agent/McAfeeThreatPrevention.pkg -target /
echo "[McAfee-Threat-Prevention] - FINISHED INSTALLATION PROCESS"- Make the script executable:
chmod a+x {path to McAfee Agent.sh}- Drag
McAfee Agent.shonto the Mac Package Wizard, fill in the metadata, and proceed to the uninstall script editor. Enter the following asuninstall.sh:
#!/bin/sh
# uninstall.sh — Matrix42 AG Mac Package Wizard
syslog -s -l warning "Emprium Agent running uninstall.sh"
echo "[McAfee Agent] - Start uninstallation process"
/Library/McAfee/cma/scripts/uninstall.sh
echo "[McAfee Agent] - Finished uninstallation process"
echo "[McAfee-Threat-Prevention] - Start uninstallation process"
/usr/local/McAfee/uninstall ThreatPrevention
echo "[McAfee-Threat-Prevention] - Finished uninstallation process"- Create the package and save it to Desktop. Mount the DMG and copy all contents to a separate staging directory. Unmount and delete
McAfee Agent.dmg. - Open Disk Utility and create a new read-write DMG named
McAfee Agent, saved to~/Desktop/{UUID}/Data/. Use a size of at least 250 MB. - Mount the new DMG and copy all staged content into it, including
McAfeeThreatPrevention.pkgandinstall.shfrom the McAfee download. - Unmount the DMG. The package is ready to import into the EMC.
Package and Distribute Configuration Profiles
For profile distribution, an MDM solution such as Matrix42 Silverback is the recommended approach. This package method installs profiles in the user context but does not support later profile updates without reinstallation.
This method uses a LaunchAgent to install a .mobileconfig profile for every user who logs in.
Step 1: Create the Profile and Scripts
- Create your profile using Apple Configurator and save it as
{ProfileName}.mobileconfig. - Create
{ProfileName}_Installation.sh— this installs the profile for the currently logged-in user:
#!/bin/bash
# {ProfileName}_Installation.sh — (c)2000-2018 Matrix42 AG
currentUser=`stat -f "%Su" /dev/console`
if su $currentUser -c "profiles -L" | grep "{ProfileIdentifier}"; then
syslog -s -l warning "[ProfileInstaller] Profile already installed for: $currentUser"
else
profiles -I -F "/Library/Profiles/{ProfileName}.mobileconfig"
syslog -s -l warning "[ProfileInstaller] Installed profile for: $currentUser"
fi- Create the LaunchAgent plist
com.apple.mdm.{CompanyName}.{ProfileName}.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.apple.mdm.{CompanyName}.{ProfileName}</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Profiles/{ProfileName}.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>- Create the main packaging script
{ProfileName}.sh— this is what the Package Wizard wraps:
#!/bin/bash
# {ProfileName}.sh — (c)2000-2018 Matrix42 AG
# Create Profiles directory if needed
if ! [ -d "/Library/Profiles" ]
then
mkdir "/Library/Profiles"
syslog -s -l warning "[ProfileInstaller] Created /Library/Profiles"
fi
# Copy files
cp "/Volumes/{ProfileName}/{ProfileName}.mobileconfig" "/Library/Profiles/{ProfileName}.mobileconfig"
cp "/Volumes/{ProfileName}/{ProfileName}_Installation.sh" "/Library/Profiles/{ProfileName}_Installation.sh"
cp "/Volumes/{ProfileName}/com.apple.mdm.{CompanyName}.{ProfileName}.plist" "/Library/LaunchAgents/com.apple.mdm.{CompanyName}.{ProfileName}.plist"
# Load LaunchAgent
launchctl load -w "/Library/LaunchAgents/com.apple.mdm.{CompanyName}.{ProfileName}.plist"
syslog -s -l warning "[ProfileInstaller] Started LaunchAgent"
# Wait for device portion to complete, then remove it
sleep 5
profiles -R -p {ProfileIdentifier}- Create
uninstall.sh:
#!/bin/sh
# uninstall.sh — (c)2000-2018 Matrix42 AG
syslog -s -l warning "[ProfileInstaller] Start uninstallation"
rm "/Library/Profiles/{ProfileName}.mobileconfig"
rm "/Library/Profiles/{ProfileName}_Installation.sh"
launchctl unload "/Library/LaunchAgents/com.apple.mdm.{CompanyName}.{ProfileName}.plist"
rm "/Library/LaunchAgents/com.apple.mdm.{CompanyName}.{ProfileName}.plist"
syslog -s -l warning "[ProfileInstaller] Finished uninstallation"Step 2: Build and Import the Package
- Drag
{ProfileName}.shonto the Package Wizard and package it as an ordinary shell script. - Mount the created DMG and copy the following files into it:
com.apple.mdm.{CompanyName}.{ProfileName}.plist{ProfileName}_Installation.sh{ProfileName}.mobileconfig
- Unmount and import the package into the EMC.
How it works: The shell script copies the profile and installation script to /Library/Profiles. A LaunchAgent is registered, which runs at every user login to check whether the profile is already installed for that user. If not, it installs it using Apple's profiles tool.
Distribute OS Updates
Create and package the following script to trigger macOS software update installation on target clients:
#!/bin/bash
# SoftwareUpdate.sh — (c)2000-2019 Matrix42 AG
# Installs all appropriate updates
softwareupdate -i -aOS update packages typically require a system reboot. The reboot behavior can be controlled via the setup.sh of the package (using #Reboot=1 or #Reboot=5).
PKG Creation Using the Package Wizard and Packages.app
The Package Wizard integrates with Packages.app (by Stéphane Sudre, BSD License) to support creation of more complex PKG installers — including PKGs that copy files to specific locations or run pre/post-install scripts.
The Package Wizard does not execute PKG creation itself; it launches Packages.app to handle the build.
Steps
- On the Package Wizard start page, click Start PKG Creation. If Packages.app is not yet installed, the wizard starts the appropriate installer — follow the prompts.
- A new window with step-by-step instructions opens.
- Follow the instructions and create your PKG using Packages.app.
For help with Packages.app, click Open Packages Online Help within the Package Wizard, or visit the Packages.app online documentation.
Using Variables from ComputerName.ini in setup.sh
Since Empirum Agent for macOS version 1711, variables from the ComputerName.ini file can be accessed during software installation. This is useful for making package-specific configurations based on computer context.
Use the GetVariable tool, located at:
/Library/Application Support/matrix42/EmpirumAgent/EmpirumAgent.app/Contents/Resources/GetVariableThe tool accepts two parameters:
| Parameter | Description |
|---|---|
-v |
For all standard (non-password) variables |
-p |
For SYNC-encrypted passwords |
Examples:
# Read the FQDN variable
/Library/Application\ Support/matrix42/EmpirumAgent/EmpirumAgent.app/Contents/Resources/GetVariable -v FQDN | tail -n1
# Read a SYNC-encrypted password
/Library/Application\ Support/matrix42/EmpirumAgent/EmpirumAgent.app/Contents/Resources/GetVariable -p SUBDEPOT.PASSWORD_1_SYNC | tail -n1GetVariable can only decrypt SYNC-encrypted passwords. AES256 encryption is not supported.
Troubleshooting
Application metadata (manufacturer, product name, version) is extracted automatically by analyzing the .app bundle. If the detected information is incorrect, it can be edited manually within the wizard before finalizing the package.
To diagnose how metadata is interpreted for a folder of applications, use the Package Wizard's debug scan mode from Terminal:
open -n ./Mac\ Package\ Wizard.app --args DEBUG -SRCFOLDER /Applications -DESTFOLDER /Users/administrator/Desktop/M42Debug.csv| Argument | Description |
|---|---|
-SRCFOLDER |
Path to the folder containing the applications to scan (e.g., /Applications) |
-DESTFOLDER |
Full path and filename for the output CSV file (e.g., /Users/administrator/Desktop/M42Debug.csv) |
The scan result CSV shows exactly how each application's metadata is interpreted and processed, making it easy to identify and correct any discrepancies before packaging.