Creating Config Profiles instead of a First Boot Script

As a follow up to my first boot script blog, I wanted to spend a bit more time with configuration profiles to see if they could be used to replace some or all of it.
It has become increasingly apparent that Apple is in favour of managing settings via configuration profiles and the MDM system so we thought it was time to modernize the techniques we are using. In addition to this, while we have used a first boot script for quite a few of the recent OS versions which have worked great, with 10.9 and now 10.10 there were a few things that have been bugging us:

  • Having to work around preference caching.
  • Write lots of data into existing user homes and the system user template folder.

Preference Caching
Preference caching broke quite a few scripts people were using to configure OS X settings.  Traditionally, OS X and most applications use XML files stored in specific locations (Library/Preferences folders) in the root of the hard drive, the System folder and each users home folders.  You could use various methods to write data into these files, or even replace the files to affect the associated settings. 
Although introduced earlier, certainly since 10.9 the operating system started caching the information stored in these XML files.  If you edit the files directly, the change you made often gets replaced with the cached version.  Ben Toms has a great article on preference caching that explains it in more detail here.
There are commands like “defaults” that are preference caching aware which is good for one line key/value pair edits and entries. For more complex plists you can use Python, which is using CFPreferences, so would also work.  Some of the other commands like plistbuddy require you to kill cfprefsd before making changes, unless you’re editing files on a non-booted volume.
Configuration Profiles are also able to work with preference caching and apply as soon as they are deployed to the target device and so are the main focus for this blog.
Writing data into user homes and the system template
The second reason for wanting to use profiles is to avoid writing data into user home libraries and the System user template.  These methods generally avoid preference caching as they aren’t actually in use (although this isn’t guaranteed).  
The System folder has always been considered Apple’s domain so anything we put in there has the risk of being wiped out with an OS or other system related update.  To change the settings for existing user home folders, we had to use a loop in the script that contained the necessary commands to insert the key/value pairs.  This also worked, but is quite complex.
What Settings Could We Switch To Config Profiles?
The first boot script we use has quite a lot of different jobs to do so the first task was to list them out and investigate whether they could be switched to configuration profiles.  The below table lists each task and whether a config profile worked.

Task Profile? Notes
Creating a local admin account No Not possible with a profile, but can use the new 10.10 tool sysadminctl
Setting time zone and time server No The time zone and NTP server addresses are stored in /etc/localtime and /etc/ntp.conf respectively.  These are traditional UNIX Config files and can’t be manipulated with profiles.  Luckily the systemsetup command makes the process nice and simple.
Region, keyboard and language Yes Keys set in the and .GlobalPreferences.plist files.
Apple Remote Desktop No Similar to setting the time zone and server, there is a purpose built binary that can achieve this so no need to switch it to a profile
Enabling SSH access No Same as above, the purpose built command line binary works best
Setting up the Login Window Yes Keys set in
Disable iCloud Setup at login Yes Keys set in
Disable diagnostics at login No The plist file is stored in a non-standard location (/Library/Application Support) so profiles aren’t any use.
Disable Time Machine Popups Offering for New Disks Yes Keys set in
Turn off Gatekeeper Yes Available in the GUI configuration profile settings
Turn on right-click Yes Keys set in a bunch of mouse and trackpad plists (more details below)
Turn off restore windows Yes Key set in .GlobalPreferences
Stop writing .DS_Store files on the network Yes Key set in .GlobalPreferences
Set the Users Homepage Yes Key set in

Creating a config profile
There are two main options for creating configuration profiles, either in a graphical interface, or by creating custom XML files. Some of the tasks above require the use of custom config profiles. These are used to set XML keys that are not available in the standard GUI options.
The core part we are interested in can be shown in this example snippet from the profile:


The Easy Ones
There were a few preference settings that could be replaced with simple checkboxes and dropdown menus. These were:
Some of the login window options
Although there are custom settings we have been adding into the login window preference file, the majority of the options can be set in the GUI:
custom settings config profiles
custom settings config profiles options
Security & Privacy
We would normally set the Gatekeeper options using

spctl --master-disable

but this can be set in the GUI as below:
security and privacy config profiles
Custom Settings
There are a few ways you can create custom configuration profiles.
Upload the plist file directly
Depending on the MDM system, in some cases you can simply upload the configured preference file. To get the preference file setup, I would normally recommend using a cleanly installed version of OS X and removing any keys that you don’t want. So if I wanted to set a few keys in the file, I would use the terminal to add the necessary keys such as:

/usr/bin/defaults write /Library/Preferences/ DoNotOfferNewDisksForBackup -bool true

Then I would take a copy of the preference file so I can amend it:

mv /Library/Preferences/ /Users/dave/Desktop/

Then we need to convert it from binary to xml so we can edit it:

plutil -convert xml1 /Users/dave/Desktop/

Once you have an xml version of the file you can open it in a text editor and remove any keys you don’t need in your profile.
This edited preference file can then be uploaded into your MDM.
Convert to a Configuration Profile first

The second option is to convert the preference file into a configuration profile. This will allow you to deploy the setting using a large range of tools including an MDM server, Munki (since version 2.2) or using the profiles command in the Terminal.
It is possible to create a mobileconfig file directly in a text editor. There are a bunch of profile specific xml keys such as:


Note – not a full list of mobileconfig keys
and the core


that contains the management settings.
Luckily, Tim Sutton has created a very handy script called (available here). This script allows you to (amongst other things) specify a plist file as the input and have it create the mobileconfig file for you. Here’s an example command: --plist --identifier DoNotOfferNewDisksForBackup

By default, configuration profiles lock the settings they are managing. In lots of cases, this works fine but in some cases, particularly when you start dealing with custom profiles and third party applications, locking the settings will either cause the managed setting to be ignored, or make the application crash.
To get around this, you need to change the default profile behavior so the setting is set, but unlocked so the corresponding application can change it if it needs to. You can do this per preference file in the profile with one of the following keys:
Always –


– This will lock the setting (default behavior)
Often –


– This will set the key initially and then reset it each time a user logs in (if they change it)
Once – Combining the




set to the current NSdate will allow the setting just to be set once. This is useful if you want to set up the users environment a certain way for their first login, but allow them to change it afterwards.
Always: --plist --identifier DoNotOfferNewDisksForBackup --manage Always

Often: --plist --identifier DoNotOfferNewDisksForBackup --manage Often

Once: --plist --identifier DoNotOfferNewDisksForBackup --manage Once

Final First Boot Script
As I mentioned at the start, there are a few settings that couldn’t be set with config profiles, or were so easy to do with a terminal command it wasn’t worth switching across.
In these cases, we kept the first boot script code. You could turn these into a series of payload free packages, or if you are using Casper, add them to individual policies to be triggered as required.
Below is the script we ended up with:

# Requires 10.10 or higher.
# Create a local admin user account
sysadminctl -addUser localadmin -fullName "Local Admin" -UID 499 -password "apassword" -home /var/localadmin -admin
# Set the time zone to London
/usr/sbin/systemsetup -settimezone "Europe/London"
# Enable network time servers
/usr/sbin/systemsetup -setusingnetworktime on
# Configure a specific NTP server
/usr/sbin/systemsetup -setnetworktimeserver ""
# Switch on Apple Remote Desktop
$ARD -configure -activate
# Configure ARD access for the localadmin user
$ARD -configure -access -on
$ARD -configure -allowAccessFor -specifiedUsers
$ARD -configure -access -on -users localadmin -privs -all
# Enable SSH
systemsetup -setremotelogin on
exit 0


So now we have the config profiles in our MDM. When a device enrolls it falls into the necessary groups and configures its settings based on the XML information.
If anyone wants to grab a copy of our completed mobileconfig files and the amended first boot script, you can get them on our github page here.
Apple is clearly pushing profiles as the primary settings management method so its worth spending some time with config profiles and seeing what you can switch over to them.