Using Munki to manage Mac preferences with .mobileconfig profiles

You may sometimes script preferences using defaults write commands (don't edit the .plist files with a text editor directly). For example, you might change Munki client preferences using a command like:

sudo defaults write /Library/Preferences/ManagedInstalls SoftwareRepoURL ""
That's fine to do, but if you're actually managing Munki client preferences (not just for Munki-related settings but for other third-party or macOS settings), why not use Munki's built-in support for .mobileconfig profiles?

There are several methods to get or generate .mobileconfig profiles. I'm listing them below in order of preference from top recs to not-to-top recs.

Just finding existing profiles

Chances are if you want to manage a setting, someone else has also wanted at some point to manage that setting. mobileconfig is a great Google search for finding those.

Using mcxToProfile to generate a profile

You can create .mobileconfig profiles from existing .plist preference files you already have on a sample client machine. Just download Tim Sutton's mcxToProfile.

Then you can run something like

./mcxToProfile --plist /Library/Preferences/ManagedInstalls.plist --identifier MunkiPrefs
and then you can hand-edit the resulting .mobileconfig file to get out anything extraneous (for example, if all you want to set is the SoftwareRepoURL).

Generating Profiles with Apple Configurator

Apple Configurator is another option.

Just click File and select New Profile.

Once you've selected everything you want to configure, click Save.

The code it produces is (like mcxToProfile's) clean and easy to edit. And, yes, you usually want to edit down .mobileconfig profiles to be only the things you actually want to manage. Omit (i.e., delete) anything that you want your users to be able to manage themselves.

Generating profiles with Profile Manager

If you're using, there's a built-in way to generate profiles.

I usually create a test device group with no actual devices in it.

Then, under Settings, select Edit.

Find the type of setting you want to edit (there are some generic settings and then others specific to iOS or macOS). and click Configure and check off all the stuff you want configured.

Then once you've closed out of the editing settings space, click Save for the whole device group. This will allow you to download the settings.

Click the Download button and select macOS.

Now we're getting to why I seldom use Profile Manager. It adds in a bunch of binary gobbledygook and shoves all of the tags together so it's not easy to read. So, yeah, you can use it... but not fun.

Update: Apparently, you can tidy up the XML fairly easily if you want. Thanks to Ian Vonesh for the tip.

Whichever method you use, though, you can just import the .mobileconfig directly into Munki and push it out to your clients (be sure to test for unexpected behavior first before moving to production).

Can’t change Safari homepage in Sierra, even with no profiles managing homepage

So I came across something weird that's affected only my 10.12.4 clients (none of my 10.11.6 clients seem to be affected by this). Even though I have only one Safari profile enabled, which is set-once and doesn't manage the homepage, my 10.12.4 clients are unable to change the homepage in Safari manually. Whatever the homepage was is stuck like that. If you enter a new homepage in the Safari preferences, it will just not take and revert back to the old homepage once you hit Enter or click out of the address entry field.

The only workaround I've found for this is to delete all profiles (again, even though I don't have any profiles managing the Safari homepage):

sudo profiles -D
Are you sure you want to delete all configuration profiles? [y/n]:y
reboot the computer, and then reinstall (via Munki) all the previously installed profiles (yes, including the set-once profile for Safari that was installed before)... and then I'm able to change the homepage on the client manually. Very bizarre.

Also, after testing on a couple of other clients, there do seem to be situations in which the Safari profile was never set at all, and you still can't modify the homepage, even after deleting any other profiles and rebooting, and it's not account-specific either (freshly created account experiences it, too). It's a real head-scratcher.

Using startosinstall to install a macOS upgrade with Munki

Update: The instructions below will be obsolete once Munki 3 is released. More details on the Munki 3 implementation can be found on the Munki wiki.

createOSXinstallPkg is a great project for making an Apple macOS installer into a .pkg you can deploy with Munki.

Apple did some things to break that process for 10.12.4. People are in the process of finding workarounds for it.

One option is to use the built-in startosinstall tool that comes with the installer bundle.

If you import the bundle into Munki, you'll want to have both a preinstall_script and a postinstall_script.

The preinstall_script checks to make sure there aren't other updates pending, since startosinstall will run its own reboot independent of Munki. The pending updates should be 1 (it's the only 1) or 0 (it was part of a set of updates that did complete and then the pending updates cleared, and you're trying again):


# Make sure there is only one pending update (this one)
pending_count=$(defaults read /Library/Preferences/ManagedInstalls PendingUpdateCount)

# If it's 1 or 0, we're good to go
if [ "$pending_count" == 1 ] || [ "$pending_count" == 0 ]; then

exit 0


# Otherwise, abort the installation
exit 1

The postinstall_script does the actual install:

sudo "/Applications/Install macOS" --applicationpath "/Applications/Install macOS" --agreetolicense --nointeraction
Just as you would with a normal OS upgrade item, you want the installs array to reflect the OS version (not the presence of the installer bundle in the /Applications folder), and you want to mark this as an Apple item. (Check the Munki wiki for more details about those two things.)

P.S. There is now a recommendation on the createOSXinstallPkg README to upgrade using 10.12.3 or investigate using startosinstall.

P.P.S It's possible, instead of my funky workaround with the preinstall_script, that you could use the --pidtosignal option instead with Munki. Here's an example using JAMF.

P.P.P.S. Looks as if Greg Neagle has started working on integrating startosinstall into Munki "natively"—yes!

Automating an AutoPkg Munki import when vendors don’t package installers properly

You may have, when using (or creating) a .munki AutoPkg recipe, come across a situation in which you run it:

autopkg run -v NAMEOFITEM.munki
and then get something back like this:
Item NAMEOFITEM already exists in the munki repo as OLDNAMEOFITEM.
even though you're sure the item is newer than the one in the Munki repo.

That has to do with the find_matching_item_in_repo() function the MunkiImporter processor uses to determine whether the item exists already or not.

It compares a number of things between the to-be-imported item and what's already in the Munki repo—installer item hash, installs, receipts, files and paths, etc. If any of those matches up, MunkiImporter considers it a match.

So, for example, if you have BADLYPACKAGEDBYVENDOR 3.7.3, which is an update for BADLYPACKAGEDBYVENDOR 3.7.2, but the receipts for both are just 1 (yes, 1 and not 3.7.2 or 3.7.3), the MunkiImporter processor will see the two as the same and not do "another" import of the same item. Likewise, if the version in the app bundle is 3.7 and not 3.7.2 or 3.7.3, the MunkiImporter processor will see them as the same. I've even run into situations in which a vendor artificially ups the number but the "new" package or .app bundle is exactly the same. In that case, the installer hash will be the same, and the MunkiImporter processor will see them as the same.

So what do you, apart from complain to the vendor and pray it fixes the problem?

There may not be anything you can do apart from force an import. You may find a convoluted workaround, though. For LockDown Browser, I had to create an installs array based on the executable and also essentially override the useless receipts array. You might have to do something similar, depending on how bad the vendor package is.

Using an Outset boot-every script to add default applications via Munki

In Bash script to add optional installs for Munki, I introduced a script that uses PlistBuddy to add optional install items to the client machine's SelfServeManifest.

I thought at first I could use that as a boot-once script for Outset, but it seemed the script ran too early (actual first boot) and then didn't actually write the values it should.

As a workaround, I've put the script in as an Outset boot-every with a check to see if one of the optional items is already in the Munki install log. Here's an example:


# See if this has ever run before... have to check the log, because Outset will delete the file once run. We don't want this to re-run if we update the pkg version
alreadyRun=$(cat /Library/Managed\ Installs/Logs/Install.log | grep "Firefox")

if [ -z "$alreadyRun" ]; then

# Self-serve manifest location
manifestLocation='/Library/Managed Installs/manifests/SelfServeManifest'

# PlistBuddy full path

# Add in "optional" default software

# Check to see if the file exists. If it doesn't, you may have to create it with an empty array; otherwise,
if [ ! -f "$manifestLocation" ]; then
sudo "$plistBuddy" -c "Add :managed_installs array" "$manifestLocation"

for packageName in "${optionalDefaults[@]}"
# Check it's not already in there
alreadyExists=$("$plistBuddy" -c "Print: managed_installs" "$manifestLocation" | grep "$packageName")

# Single quote expansion of variables gets messy in bash, so we're going to pre-double-quote the single-quotes on the package name

if [ -z "$alreadyExists" ]; then
sudo "$plistBuddy" -c "Add :managed_installs: string $alteredPackageName" "$manifestLocation"

So this basically checks for Firefox. If Firefox (one of the default optional installs) is in the install log, it won't run again.

When an AutoPkg recipe fails to import a .dmg

If you ever have an AutoPkg recipe that seems to be working fine for weeks or even months and then suddenly fails with a message like this one:

Error in local.munki.FileZilla: Processor: MunkiImporter: Error: creating pkginfo for
/Users/USERNAME/Library/AutoPkg/Cache/local.munki.FileZilla/FileZilla.dmg failed: Could not mount
(doesn't have to be FileZilla—could be anything), you may not see the .dmg is mounted in Disk Utility (or even diskutil list), but you can check to see if it's a phantom mount by seeing if it shows up in the output of
hdiutil info
If it does show up there, then run
hdiutil detach /dev/diskFILLINLOCATION
and then re-run the recipe. Should be fine after that.

Acknowledgements: Thanks to Eric Holtam for the tip—just documenting it here for anyone else who may benefit from it.

Using Munki to rename computers based on manifest display name, user, or notes

There may be some Mac admins who don't really care that much about computer names. After all, especially if the computer isn't joined to the domain (many of our machines are not), what does it matter? It's the name that will show up in Sharing or in the few users use. If you do care, though, I created a Munki nopkg that looks at one of three places for a name to rename the computer name to—display_name, user, or notes.

I based this on the three custom fields that MunkiAdmin has editable for manifests.

To use it, just modify the display name, user, or notes field in the manifest you want to rename, tweak in the nopkg (via commenting/uncommenting) the installcheck_script and postinstall_script to use the field you want, and then add this nopkg as a managed_installs item to the manifest(s) you want to manage computer names for. This nopkg will change the LocalHostName, HostName, and ComputerName.

As written, this nopkg will automatically ignore AD-bound computers.

P.S. If you have a database or spreadsheet of some kind of what the computer names should be, you can also bulk-fill-in those fields. I have a simple (no subdirs on my manifests) sample script you can tweak.

Capturing new FileMaker Pro updates for macOS

For older FileMaker Pro versions, there used to be downloadable updates on the FileMaker website, but starting with FileMaker Pro 15, they decided to have FileMaker updates on macOS go through FileMaker itself:

As you can see here, they expect your user to have admin privileges. If you're managing Macs (through Munki, for example), you may not give your users admin privileges or you may (even if your users have admin privileges) not want to bother with them running the updater themselves.

For some reason, Windows users get separate update installers. None for the macOS users, though, but we can be a bit tricky in capturing the installer.

First, find a Mac that you're not doing a silent install of FileMaker Pro on. Do a regular manual install on that one Mac and make sure you have AI_DISABLEUPDATENOTIFY=0 in your Assisted Install.txt file.

Then, on this test Mac, launch up FileMaker Pro.

Under Help, select Check for Updates....

Click Download Update

This is key here: do not click Install Update. Don't click Cancel either. Do not click anything. Just leave this dialogue up for now.

Open up /var/log/install.log and search for caches.

That should show you the location of the downloaded installer.

Go to that location and find the .pkg file. You can import that into Munki (or whatever you use to manage updates to your Mac fleet).

Skipping Apple updates in Managed Software Center manual checks

Why would you want to selectively disable Apple software updates?

Munki allows you to change a preference on client machines to check for and install Apple software updates.

This is pretty cool. It means I can bundle Apple software updates and third-party software updates together for my users.

But sometimes, it's a little frustrating when I'm helping a user to use Managed Software Center, and MSC checks for new updates but also decides to check for Apple updates... don't really need it to check for Apple updates then. Totally want Munki to check for Apple updates in the background and all the other times, just not when the user launches up MSC.

It's true if you've just checked very recently. you may see Skipping Apple Software update because sucatalog is unchanged, installed Apple packages are unchanged and we recently did a full check, but even if it's been a while since the last check, I just don't want any check happening if the user has manually launched up MSC.

Use a Preflight script

Munki allows you to run preflight and postflight scripts during each Munki run. As Munki is out of the box, you are supposed to have one preflight script named preflight (no extension). If you use MunkiReport, though, as I do, you'll notice MunkiReport has the preflight script run a bunch of scripts in the preflight.d directory, which allows a bit more flexibility to add in various scripts instead of lumping them into one combined preflight script.

Script logic

Preflight scripts can use the runtype to do different things based on whether the Munki run type is an auto, logoutinstall, checkandinstallatstartup, installwithnologout, manualcheck, or custom.

What the script does is just check to see if there's a manualcheck and then turn the InstallAppleSoftwareUpdates preference off. If it's any other type of run, the script turns the preference on.

The actual preflight script

Here is the preflight script, which you can deliver as a payload to /usr/local/munki/preflight.d/ (or as /usr/local/munki/preflight if you don't have a preflight directory). You can create the .pkg using Packages, The Luggage, munkipkg, or even just pkgbuild.

If you want to make it based on another runtype you can change the logic there or tweak the script to use a time-based or date-based logic to run Apple updates less frequently. The possibilities are endless!