The Package. Mac OS
Note: This post may be a little out of date as it was originally written in 2015. But I’m posting it here as the fundamentals have not really changed much.
- MacOS Big Sur Installation Failed: 'An Error Occurred ...
- Create Install Package Mac
- Cached
- Mac Os Package Manager
Whenever you need to create an installation package or distribution for Mac OS X 10.5 or later, Packages is the powerful and flexible solution you're looking for. With Packages, you can define which applications, bundles, documents or folders should be part of the payload of your installation packages and where they should be installed. The Missing Package Manager for macOS (or Linux). It’s all Git and Ruby underneath, so hack away with the knowledge that you can easily revert your modifications and merge upstream updates.
Credits: Thanks to Gary Larizza for his post on AFP548.com where most of this documents content was sourced ( https://www.afp548.com/2010/06/03/the-commandments-of-packaging-in-os-x )
When managing Mac OS X devices, you will enviably have to deploy files or applications to many devices. There are many ways to achieve this, however the most effective and best practice method is to use Packages.
While packaging is quite simple, it can very quickly become quite complex. This document serves to provide some guidelines to help you avoid some simple mistakes and prevent confusion when creating packages.
There are many tools out there used to create Packages, Apple offer their own built in command line tools like pkgbuild. This guide will not go into detail about how to use any of these tools, it is up to the system admin’s own personal preference on which tools they wish to use in order to create their packages.
However version control is very important, as is the ability to quickly and accurately create and recreate packages. The ability for packages to be peer reviewed and package versions to easily be diff’d is also important and the admin’s choice of tools should take this into account. It is also highly recommend that a version control system such as git is used in combination with package creation.
Below is a list of tools that are recommended for creating packages:
Packages by Whitebox
A great GUI driven tool to create flat and distribution packages and provides an easy to learn GUI. It is still quite powerful and allows a great deal of control over how your packages are created. A build file is created which saves information on how the package should be created such as the payload, pre/post flight scripts, additional resources etc etc.
Cost: $0 – FREE
The Luggage
A completely text driven package building system perfect for use with version control systems such as Git. Files can easily be reviewed to see what will be in the package without any extra work.
The big benefit to using The Luggage is that because the packages are created with make files, these make files can easily be diff’d to see changes as well as talking other users through the creation process. No GUI panes to navigate.
Cost: $0 – FREE
Munki PKG
Munki PKG is a simple tool very similar to The Luggage which builds packages in a consistent, repeatable manner from source files and scripts in a project directory.
Files, scripts and metadata are stored in a way that is easy to track and manage using a version control system like git.
Cost: $0 – FREE
MacOS Big Sur Installation Failed: 'An Error Occurred ...
Installation method
Your installer should not require any input from the end user.
DO NOT:
- Assume that your package will be installed interactively via the GUI or to the currently booted volume. More often than not packages will be deployed to machines via management systems such as Munki or Casper. Because of this you should ensure that your package can be installed to machines that are unattended (at the login window without a console user logged in)
DO:
- Ensure that your package can be installed via the command line and by any management framework with and without a user logged in.
Installation target
DO NOT:
- Assume that your package will be installed to the currently booted volume. Your package might not necessarily be installed to the currently booted volume, so ensure that any scripts in your package use the correct variables passed to it from the installer application. For example, reference the target volume in your scripts by using the variable $3 (in bash) rather than using absolute file references.
- Use tools such as sw_vers in order to get the Operating System version. These tools will only report the OS of the currently booted volume.
DO:
- Check the SystemVersion.plist on the target volume ($3)
- Check if the boot volume (/) is the same as the target volume ($3) if any of your scripts require it.
Unnecessary actions.
DO NOT:
- Perform ‘helpful’ things like using osascript to open a Finder window showing your newly installed application. Similarly do not do things like opening a browser window to the installed software’s homepage.
- The problem with these things is if you are installing the software in an unattended mode where the computer is at the LoginWindow, these types of things will simply cause errors in your installation process.
- Require unnecessary reboots if you can accomplish the same thing by loading/unloading LaunchDaemons/LaunchAgents – If you go down this path, remember that it is even more important to check if you are installing to the boot volume or not.
- Automatically add files to the Dock, Desktop or anywhere outside of /Applications or other required directories. If you wish to add Dock items, use another package/script/profile/tool to achieve that.
- Ask for admin/elevated privileges if they are not needed for installation, i.e. installing into
/Users/Shared - Create separate installers for different architectures/OS versions. If you have separate payloads for separate architectures/OS versions, perform your architecture/OS check on the target volume, not the currently booted operating system see rule 2.
DO:
- Use a distribution meta-package to provide a single package that will correctly determine OS/Architecture of the destination volume and install the appropriate payload.
Licensing
Licensing should be managed by Systems Administrators. Wherever possible licensing files should be packaged separately to the application being deployed. This allows for a single application package to be deployed to multiple sites with different licensing files applied later depending upon the licence that is appropriate for that site.
Licensing information might be supplied via a global plist/config profile/KMS or other.
This also prevents unauthorised installation of software should your application package be obtained by a unauthorised third party.
DO NOT:
- Place licensing and registration files in the user’s home directory wherever possible. Use a global location such as /Library
- Building licensing/registration mechanisms into the installer GUI.
DO:
- Allow a scriptable licensing interface to your software
Pre/Post install scripts
Use pre and post install scripts only when necessary, and follow all other rules with your scripts.
For example, it would be silly to use a package to install some files on disk and then use a post install script to set the permissions of those files. Instead correctly set the permissions of the files in the payload.
This also allows for reviewing of package contents via lsbom
DO NOT:
Create Install Package Mac
- Use postinstall scripts to create or modify files – do this in the package payload.
- If you must use post-install scripts, do not use osascript to move and copy files. Use CLI tools such as cp and mv in bash
- Use any kind of GUI scripting, see Rule 1.
- Use sudo in your scripts, your script is already running as root.
DO:
- Exit your script with 0 on success, or non-zero on failure.
- Trap error codes in your scripts
- Use globbing in your scripts, because no one likes repetition and computers are built to do the work for us so let them.
- Ensure your scripts handle paths with spaces in them.
Naming Conventions and Version Numbers
Naming conventions are necessary and helpful. For example VPN.pkg is NOT helpful.
Give your packages meaningful names and version numbers. Providing vendor and product name, along with important version numbers and vendor identification codes.
DO:
- List your vendor and product name in your package name
- Give packages meaningful names with version numbers. Remember 1.15 is greater than 1.2 in most situations.
Supporting Operating System Versions
If you are going to supporting running your application or payload on operating systems back to say version 10.8, then it should go without saying that you need to TEST your package on every version from 10.8 to the most current.
DO NOT:
- Change the ownership and permissions of core Operating System folders and files
DO:
- Keep your config data and cache data separate
- Follow the directory structure mandated by the target platforms software deployment guidelines
- Provide an uninstaller or uninstall script
- Use the documented OS X .pkg format and not just a .pkg wrapper for a 3rd party solution that installs the software for you – obvious exception for Adobe software.
Be Descriptive
Even if you are not planning on having your package installed via the GUI you should still make it GUI-friendly.
DO:
- Provide a welcome message, read-me, description of whats happening and whats being installed.
- Comment your pre/post install scripts thoroughly.
Snapshotting and Re-Packaging
Try to avoid using Snapshot methods to create packages – a common tool used to create snapshot packages is JAMF’s composer.
Snapshotting is generally considered bad juju and the result of a lazy (not in a good way) sysadmin
Packages created from snapshots lack the nuances and intent of the original package. They can often miss critical files or modifications to the file system.
If you are unable to use a vendor package, consider the following:
DO:
- Attempt to unpack and reverse engineer the package – Use tools such as Pacifist (https://www.charlessoft.com/) and pkgutil –expand to determine what the package is attempting to achieve.
- Try to modify the existing vendor package using things like providing a custom Choices.XML to select certain packages in a meta/distribution package for installation.
Product Signing
Gatekeeper was introduced in 10.8 as a way to alert users to unsigned packages. For this reason, it is best practice to sign your installer packages with a developer ID certificate that lets your users know your packages can be trusted. It also allows packages to be installed in the GUI when Gatekeeper is configured to allow apps downloaded from the App Store and identified developers
Unsigned packages are not an issue when not using the GUI installer however.
DO:
- Use productsign to sign your packages with an Apple Developer ID certificate
The default layout for installed Haskell components follows the conventions of most unix-like systems. On Mac OS X, this layout isn't optimal, and a different layout is used. The layout presented here has several advantages:
- Follows Apple's Guidelines for file system layout
- Makes it easy for a user to locate all the Haskell components, especially user installed packages
- Enables easy removal of a user installed package, whether they have installed it --user or --global.
- Facilitate creation of unified, hyper-linked Haddock documentation, optionally with source
Haskell Platform 2011.2.0.0 (March 2011) and later uses this layout and sets up cabal to use it for built packages. On new installs, if you didn't already have a ~/.cabal/config file, then it is set up by default. Otherwise, the config file for this layout is placed in ~/.cabal/config.platform and you can manually move it over, or incorporate it into your existing config file.
Implementations
Haskell implementations are generally installed for use by all accounts on thesystem. They consist of large collections of executables, libraries, and otherfiles. These are packaged using Apple's framework, versioning, and bundlingtechniques and installed in:
For example, GHC 7.0.2 is installed in:
Executables intended for use from the command line, are be symlink'd into:
[Q: Would /usr/local/bin be more appropriate? ]
Packages that come with the implementation, are be located within the Frameworkbundle.
If the implementation has any GUI applications, these are installed in:
NB: These guidelines allow for multiple implementations and multipleversions to co-exist. (With the exception of multiple versions of GUI applicationswhich can only be done by distinct naming, and the symlinks in /usr/binwhich can achieved in the normal way: Append the version number to the executableand then symlink the 'bare' name to the most recent.
If implementations want to be able to be installed 'per user', then the abovepaths should be:
Not all software for Mac OS X offers a 'per user' option on installation, and whilenice, it is by no means universal.
User Installed Packages
User installed packages are placed under a 'prefix' that depends on if the userchoose to install for all users (--global) for just their own use (--user):
Package Component Layout
Cabal offers a large amount of flexibility in where the various pieces of a packageare installed. The GHC package system is rather agnostic about where these pieces are,and insulates the implementation from such differences. These combine to enable thechoice of package layout to be largely to serve the user.
For both --global and --user installs, this is the recommended package layout on Mac OS X:
This can be achieved with the following cabal configuration defaults:
N.B.:
- Cabal configuration files don't actually support ~. You must replace that with /Users/xxx where xxx is your account name.
- All packages for a given compiler are under a single directory. When an old compiler is removed, all the packages compiled for it can be easily removed too.
- All components for a package are under a single directory. This facilitates easy location and removal of a single package, for either a single compiler, or all installed versions.
- If a package generates different doc for different compilers (it may have different APIs available), then this structure preserves each.
- Executables are also per compilation, which is sometimes important (for Haddock, for example).
Executables
Packages that build executables to be run from the command line present a difficultly. They are built into a per-package bin directory, and then should be symlink'd somewhere on the user's PATH. For global installs, the logical place is one of:
Cached
For user installs, since ~/bin is not on the PATH by default on Mac OS X and may not exist, binaries are symlink'd into:
Alas, cabal only supports one location for both kinds of build, and so it is set to be the later.