Create a Mac OS X with InstaDMG and InstaUp2Date

From AFP548 Wiki
Jump to navigation Jump to search

This is an introduction to InstaDMG, which is a powerful command line tool used to produce OS X images. These images can include OSX incremental upgrades as well as 3rd party software and scripts. This document will act as a guide and a reference that will show you how to get started and produce an up to date OSX 10.7 image only with incremental upgrades included. But it will also provide explanations on other work flows and best practices including many examples of common scenarios that users will run into. While the emphasis on this guide will be on OS X 10.7, InstaDMG does work with OS X 10.5, 10.6, 10.7, and 10.8.

Requirements for Guide

  • A Mac computer running OS X Lion 10.7 with an admin account
  • Internet access (no proxies)
  • A copy of OS X Lion (installESD.dmg)
  • Text editor like TextEdit or TextWrangler
  • Terminal
  • IceBerg

Tips for using Terminal

Terminal (located in Applications/Utilities/Terminal.app) is where you will be running all the commands to run InstaDMG. So here are a few things to keep in mind about Terminal that will make your life easier:

  1. Whenever you see ~ it is referring to the home directory. Rather than typing out:
    /Macintosh/Users/myAccount/InstaDMG
    You can simply type:
    ~/InstaDMG
  2. Get used to using “sudo” for most files in InstaDMG. Otherwise you will not be able to run the file. Just type:
    sudo /the/path/to/the/file/I/want/to/call.py
  3. You can drag and drop files into the Terminal window and it will give you the full path of file. This is VERY handy if you want to avoid having to type out every path.
    1. Don’t like using the GUI? Well learn how to use command-line completion: http://en.wikipedia.org/wiki/Command-line_completion
  4. To stop a task from running in Terminal, simply press CTRL + C.
  5. You can highlight with the mouse and use Command + C and Command + V to copy and paste files. Additionally you can drag text from Terminal into a text editor (and from a text editor into Terminal).
  6. CTRL + A will take you to beginning of line (much easier than waiting on left arrow)
  7. CTRL + E will take you to end of line (much easier than waiting on right arrow)
  8. Up or Down arrows on keyboard will show you the commands you’ve used previously.
  9. You can hold OPTION and click a position in the current line to move your cursor to that position.
  10. If you have a file or folder with a space in between, you will need to use a \ before the space. For example:
    /Macintosh\ HD/Users/My\ Account\ Folder/
  11. The man command in Terminal will be helpful in learning Terminal commands. Want to learn how to use installer in Terminal? Type man installer. It’s a great thing to know.

A few more here: http://apple.stackexchange.com/questions/5435/got-any-tips-or-tricks-for-terminal-in-os-x

What is InstaDMG?

It is an open source project. Website: http://code.google.com/p/instadmg/

It is a great tool that allows for the creation of “never-booted” OS X images. This is very different than the older method of creating an image off one Mac using something like SuperDuper, Carbon Copy Cloner, or Disk Utility. This older method (the Golden Master image) would unfortunately copy over settings over to each Mac and may result in inconsistencies. As an example, trying to deploy a GM image created an iMac unto a Macbook Air would result in odd network interfaces showing up (as the iMac has an Ethernet port and the MacBook Air does not). There are also other issues, but needless to say InstaDMG will not run into them.

InstaDMG has a great community which is willing to help and answer questions at:

Downloading InstaDMG

The first task is to download the InstaDMG code which is stored on Google. You can view those files here http://instadmg.googlecode.com/svn/trunk/. But the installation is done via Terminal.

This all works through the command line interface as there is no GUI layer for InstaDMG yet. Launch Terminal from Applications > Utilities > Terminal and change into your home directory and download the InstaDMG code using the svn checkout command.

svn is Subversion and is an Open Source version control system for managing evolving code and its built into OSX. The command below will download the code and create a folder in your home directory called InstaDMG, you can name this folder anything you like and note that it is presented as an option after the main command if you do not add the option the files will be located in a directory called ‘trunk’ (which can be renamed). Enter this command into Terminal:
svn checkout http://instadmg.googlecode.com/svn/trunk InstaDMG

Running the command will download and install the required files, the last of the file downloads will have output from the Terminal similar to below:

A trunk/Documentation/InstallerChoices/README
A trunk/Documentation/InstallerChoices/10.6_InstallerChoices.xml
A trunk/Documentation/README
U trunk
Checked out revision 426.

Updating InstaDMG

InstaDMG is constantly updated to deal with the OS X updates from Apple. To download the latest version of InstaDMG all that is needed is to move into the installation directory where InstaDMG lives and run a ‘svn’ update. If the install directory is “InstaDMG” and in your home directory you would run:

[~]: cd ~/InstaDMG/
[~/InstaDMG]: svn update
At revision 426.

Here there are no updated files. The revision is stated at 426, any updated files downloaded would be named and a higher revision number will be declared.

Note: Because you never know how the latest InstaDMG code will change things, it is generally will make a backup of the InstaDMG folder. The point being here that you should create a backup to revert to the old version you had in case the latest svn has broken something that previously worked. It’s a bit of precaution only.

Please note that in OS X Mountain Lion 10.8, Apple has stopped including the svn tool. You can still install the Command Line Tools for Mountain Lion available as a separate download from the Apple Developer site for free: https://developer.apple.com/downloads/index.action

Import OS X disk into InstaDMG

After InstaDMG is downloaded, the next step is to import the OS X disc into InstaDMG. Please keep in mind that to build an OS X Lion (10.7) image you SHOULD be running a Mac running OS X Lion (10.7 client or server). In other words, make sure you are running the same OS version as the OS image you wish to create. And avoid using InstaDMG on OS X Server on versions prior to 10.7 as you could run into problems.

In the past, Apple supplied discs with OS X, but since OSX 10.7 Lion is diskless it poses a slight problem for importing it into InstaDMG. Luckily there are a few solutions, all of which require you have the InstallESD.dmg file from the Lion installer.

Extract the InstallESD.dmg from the “Install OS X Lion.app” after it is downloaded from the App Store and before it is installed (when it is installed the app is deleted). To extract InstallESD.dmg:

  1. Locate the “Install OS X Lion.app” installer and right-click on it (or CTRL and mouse click). Select 'Show Package Contents'.
  2. Inside the 'Contents' folder, there is a 'SharedSupport' folder. Inside that is the Lion Installer. It's called 'InstallESD.dmg". This is the file you will want.

Click here to learn how to reveal the InstallESD.dmg and also a guide to burn a generic copy of 10.7 to disc.

Once you have the InstallESD.dmg there are a few solutions to import it into InstaDMG:

  1. If you have the InstallESD.dmg from Lion just copy it in the path below and move onto the next section:
    InstaDMG/InstallerFiles/InstallerDiscs/InstallESD.dmg
  2. The traditional way (works with 10.5, 10.6, and 10.7): If for some reason you have a disc and want to import it the traditional way in InstaDMG, pop in the disk, and let it mount in Finder. Or if you don’t have the disc, but have the InstallESD.dmg, then all you need to do is open it so that it mounts in Finder. Make sure nothing else is mounted to avoid problems. Then type in Terminal:
    sudo
    Drag the file /InstaDMG/AddOns/InstaUp2Date/importDisk.py into Terminal and then type:
    -automatic
    The final result should look something like (notice the spaces):
    sudo ~/InstaDMG/AddOns/InstaUp2Date/importDisk.py –automatic

Alternatively, you can always use the command line only in Terminal. cd into your InstaDMG folder and run the import command below with sudo. It needs to be imported because burning images straight from hard disk is a lot faster than from an optical disk.

[~]: cd ~/InstaDMG/AddOns/InstaUp2Date/
[~]: sudo ./importDisk.py –automatic

This step will take a bit of time (estimate ~45 minutes). Make sure no other disks or external drives are mounted as this may produce an error. What you should end up with when finished is a “MacOS X Client 10.7 11A511.dmg” filed in this path:
InstaDMG/InstallerFiles/InstallerDiscs/MacOS X Client 10.7 11A511.dmg

Creating a basic generic OS X image with InstaUp2Date

The final step is to download the OS X incremental updates and produce a fresh generic up-to-date, fully patched, vanilla OS X 10.7 Image. This is done through the catalog file which is stored in:
InstaDMG/AddOns/InstaUp2Date/CatalogFiles/10.7_vanilla.catalog

The command to run is back in the InstaUp2Date folder, change directory to there and run the command:

[~]: cd ~/InstaDMG/AddOns/InstaUp2Date/
[~]: sudo ./instaUp2Date.py -p 10.7_vanilla

Or

sudo

Drag the file /InstaDMG/AddOns/InstaUp2Date/instaUp2Date.py into Terminal
-p 10.7_vanilla

The final result should look like (notice the spaces):

sudo ~/InstaDMG/AddOns/InstaUp2Date/instaUp2Date.py -p 10.7_vanilla

The initial output in the terminal when the above command is run looks like this:

[~/InstaDMG/AddOns/InstaUp2Date]: sudo ./instaUp2Date.py -p 10.7_vanilla
Password:

Parsing the catalog files for 10.7_vanilla
OS X Lion Update 10.7.1
Java For Mac OS X 10.7
Remote Desktop Client 3.5.1
iTunes 10.4

Finding and validating the sources for 10.7_vanilla
OS X Lion Update 10.7.1 - found based on checksum and verified in 2 seconds
Java For Mac OS X 10.7 - found based on checksum and verified in 2 seconds
Remote Desktop Client 3.5.1 - found based on checksum and verified in less than one second
iTunes 10.4 - found based on checksum and verified in 8 seconds
The final output at the tail of the command will be like this:
19:55:14 ###### Correcting some generic installer errors ######
	Correcting symlinks that point off the disk
	Closing programs that have opened files on the disk
	Deleting Extensions.mkext cache file
	Deleting cache files created during installations
21:38:18 ###### Creating the deployment DMG and scanning for ASR ######
	Rename the deployment volume: Macintosh HD
	Create a read-only image
	Scanning image for ASR: /instadmg/OutputFiles/10.7 Vanilla.dmg
	ASR image scan complete
21:50:17 ###### InstaDMG Complete ######
21:50:17 ###### Cleaning up ######
	Ejecting images
	Deleting scratch DMG

Done

The OS X incremental updates are downloaded (based on the catalog) and stored on your local drive so it will not have to download them again in the future. Future builds will only pull down new updates so long as you have the latest catalogs. After the updates are downloaded they are applied to the original mounted MacOS X Client 10.7 11A511.dmg image and in turn an up-to-date image is created in the directory – ~/InstaDMG/OutputFiles named 10.7 Vanilla.dmg which is the all-encompassing new master image. Make sure to move the output files (or rename them accordingly) if you are going run InstaDMG again. Failure to do so will result in the file getting overwritten (unless you’ve modified the catalog file).

And there you have it: one OSX 10.7 image ready for deployment, which can be used through any deployment method including ASR, DeployStudio or as a NetBoot image.

The important thing here to notice is the -p (or, -process) option, which triggers the transition from the InstaUp2Date functionality (which pulls down the updates specified in the 10.7_vanilla.catalog file) to the running of our key player, the instadmg bash script. The end result (after over an hour) will be a ready-to-restore dmg in the ./instadmg/OutputFiles folder.

Dealing with Different Versions of OS Hardware

The actual catalog file you run depends on what type of hardware you have – there are a couple of flavors – you need to run the one that most appropriately suits your hardware. In this guide, a generic 10.7 build is being used. The .catalog extension does not need to be added in running the command.

Apple will often release new hardware where the OS is running a on a different build than other hardware. Yes, it could be the same OS X version (example: v10.7.0), but due to differences in hardware you will need the specific OS X version for that build. This means that there will also be some updates that will be specific to certain OS builds.

At the time of this writing, currently Apple has 3 installers: the build that comes with the mid-2011 Mac Mini, the build that comes with mid-2011 MacBook Air, and the generic one found in the Mac App Store (which is not compatible with either the 2011 Mac Mini/MacBook Air). Plus, it has an installer that comes on a USB Thumb Drive. That means that if you build an image using the 10.7_vanilla catalog and attempt to put it on a 2011 Mac Mini or MacBook Air, the computer will never boot into the OS.

Right now the four builds include:

  • 11A511 (original release for use on anything prior to 2011 Mac Mini/MacBook Air)
  • 11A511s (comes on the Lion USB Thumb Drive sold by Apple)
  • 11A2061 (for 2011 Mac Mini)
  • 11A2063 (for 2011 MacBook Air)

Apple generally will release a Combo update that unifies all the hardware together into one update. When that happens, it means you no longer have to maintain 3 different images. You could use the 11A511 build installer and apply the combo fix that will unify all the hardware. But it does mean that sometimes you will have to wait on Apple to release these Combo updates.

InstaUp2Date flags

There are several other command line options that InstaUp2Date will accept:

Flag/Option Information
-h or --help Print the usage information and exit.
-v or --version Print version information and quit.
-p or --process As described above, runs InstaDMG after successfully setting things up, along with any of the following options
-a FILE_PATH or --add-catalog=FILE_PATH Add the items in this catalog file to all catalog files processed. Can be called multiple times
--instadmg-scratch-folder=FOLDER_PATH Tell InstaDMG to use FOLDER_PATH as the scratch folder
--instadmg-output-folder=FOLDER_PATH Tell InstaDMG to place the output image in FOLDER_PATH
--add-catalog-folder=FILE_PATH Set the folders searched for catalog files
--set-cache-folder=FILE_PATH Set the folder used to store downloaded files
--add-source-folder=FILE_PATH Set the folders searched for items to install
--restore-onto-volume=VOLUME After creating the image, restore onto volume. WARNING: this will destroy all data on the volume

Catalogs

Catalogs are plain text files located in:

~/InstaDMG/AddOns/InstaUp2Date/CatalogFiles

These were introduced in a separate component called InstaUp2Date that enriches the InstaDMG experience. It makes using a work flow much easier as you will see. If you want a better explanation on how InstaUp2Date differs from InstaDMG, go to the section titled where /Volumes/ScratchDriveName is second drive you wish to use as the scratch disk.

Using InstaDMG only, not InstaUp2Date.

You can open catalog files with a text editor. There are a bunch of them, some are for specific hardware builds and different OSX version builds. These catalog files are responsible for building the image and can call on each other to customize the image build.

In this guide we are using the generic OSX 10.7 which is the “10.7_vanilla.catalog” but we need to add 2 new packages to their own catalog which in turn then calls the 10.7_vanilla.catalog. In this instance the additional catalog is called BaseSettings.catalog

You can call the catalog whatever you like. Just add the .catalog extension and file it in the path as above with the other catalogs. There is a template catalog included in that path and other sample catalogs to give you an idea of how to create your own. As an example, the format needs to be like this:

# This is the catalog for BaseSettings
include-file:	10.7_vanilla.catalog
Third Party Software:
	clearReg	clearReg.pkg	sha1:b0ba0f6bfd26956562e286bbcdfa8f78dd3722eb
	CreateAdminUser	CreateAdminUser.pkg	sha1:83b4357037d82a254c5ef068c384e3fb2c1

The first line is just a comment (good to use for documentation purposes) as indicated by the hash #. The second line calls for the 10.7_vanilla.catalog to be run before this catalog. The last 2 lines label the description of the package/the package name/checksum of the package – it is very important that these are tab separated, not space separated (in particular notice how there is an indention before the first letter rather than 6 spaces): Tab separated:

	clearReg	clearReg.pkg	sha1:b0ba0f6bfd26956562e286bbcdfa8f78dd3722eb

Space separated:

       clearReg clearReg.pkg sha1:b0ba0f6bfd26956562e286bbcdfa8f78dd3722eb

Checksums

The checksum is a guarantee that the package is valid from its initial creation, and typically needs to be applied to the packages stored in the InstaUp2DatePackages directory:

~/InstaDMG/InstallerFiles/InstaUp2DatePackages/

The easiest way to do this in bulk is to run the checksum.py command on all the packages in InstaUp2DatePackages – the checksum.py command lives in ~/InstaDMG/Addons/InstaUp2Date/ – so:

cd ~/InstaDMG/Addons/InstaUp2Date/

./checksum.py ~/InstaDMG/InstallerFiles/InstaUp2DatePackages/* > checksums.txt

This will pipe the output of the checksum command to a file checksums.txt in the InstaUp2DatePackages directory - open that in your text editor. The contents of the file need to be pasted into the new catalog.

You can also choose to run the checksum.py command without piping the output to a file, this way it will display verbosely in the terminal window. This can be handy for doing single checksums for later added packages. The checksum format will look like:

	CreateAdminUser	CreateAdminUser.pkg	sha1:83b4357037d82a254c5ef068c384e3fb2c1

You can copy that entire line from the Terminal window into the catalog. Just make sure it is tab-separated (including the tab prior to CreateAdminUser...).

  1. The first part: CreateAdminUser refers to the package name. You can actually name this something else. For example, “Create Admin Account”.
  2. The second part: CreateAdminUser.pkg refers to the package file name. By default the catalog will look for packages with that file name in the directory

    ~/InstaDMG/InstallerFiles/InstaUp2DatePackages/

    However if you run the checksum on a file that is located in another folder, you will get a spit out like this:

    CreateAdminUser /Macintosh HD/Users/MyAccount/Desktop/CreateAdminUser.pkg sha1:83b4357037d82a254c5ef068c384e3fb2c1

    If you do decide to keep packages outside of the default folder, just make sure all your packages are in one location so that the catalogs aren’t broken.
  3. The third part: refers to the hash checksum. It will also include sha1: followed by the actual checksum. Read more about sha1 at: http://en.wikipedia.org/wiki/SHA-1

Packages (DMG or .pkg or .mpkg)

InstaUp2Date will allow you to use DMG installers (the kind that require you to drag the .app into the Applications folder) along with .pkg (package) and .mpkg (meta-package) installers. Some companies make custom installers which will not work with InstaDMG/InstaUp2Date (for example Adobe software). In this case you may have to re-package the software (out of the scope of this guide). There are also some applications that do not come in a DMG or package. For example, CoRD (http://cord.sourceforge.net/) comes in a zip file which then reveals CoRD.app file. In a case like this, you will need to take this file and include it into a .DMG file using a program like Disk Utility (located in /Applications/Utilities). Some applications are .pkg/.mpkg files included in the DMG file. InstaUp2Date will automatically handle this for you.

Packages on a Web Server

You can also reference packages located on a web server. As an example, look at the 10.7_vanilla.catalog file. It references updates as follows:

	OS X Lion Update 10.7.1	http://support.apple.com/downloads/DL1437/en_US/MacOSXUpd10.7.1.dmg	sha1:67c94a3b654007c42f55170029d057d3287806c7

You can replace the http link with your own http link.

Bypass Registration Screen, Create a User Account, and configure First Boot options

Clear Setup Registration

To bypass the OS X setup registration process, you just need to have two files in place:

/Library/Receipts/.SetupRegComplete
/private/var/db/.AppleSetupDone

This will show you how to package up a script that will work in InstaDMG and other software deployment solutions.

  1. Open Iceberg (if you don't have it you can download it from http://s.sudre.free.fr/Software/Iceberg.html ).
  2. Click on File and then New Project.
  3. We’ll need to run this installer with root privileges. Select the project type Darwin: Package.
  4. Name the project appropriately and make sure to save the project to a location that's easy for you to find (~/Desktop). In this case, I’m naming the project Clear Registration.
  5. On the left side window of Iceberg, click on Scripts.
  6. Open up Text Wrangler or your text editor of choice and create the following postflight script and save it simply as postflight (no file extension):

    #!/bin/sh

    touch /Library/Receipts/.SetupRegComplete
    touch /private/var/db/.AppleSetupDone

    exit 0

    Once you’ve got the postflight script built, you need to make it executable so that it will run.
  7. Open Terminal from /Applications/Utilities
  8. Run the following command to make the script executable:
    sudo chmod a+x /path/to/postflight
  9. Going back to IceBerg, click on the Scripts section in the left side of the window.
  10. Check postflight.
  11. Drag the newly created postflight script to that same line.
  12. Click on Build menu and select Build.
  13. You should now have a package that should be located in ~/Desktop/Clear Registration./build/

Create User

To create a new user, InstaDMG comes bundled with an application called CreateUserPkg.dmg in your InstaDMG installation directory:

~/InstaDMG/AddOns/createUser/CreateUserPkg.dmg

  1. Open this DMG file and run the application contained within.
  2. Fill out the information:
    Full Name: Admin (avoid using the name Administrator as this will create problems when you try to authenticate on a Mac that is on the domain; the domain account called Administrator in most environments is disabled which will cause the Mac to sometimes not let you log on)
    Account name: admin
    Password: Enter most recent password
    Verify: Re-enter password
    User ID: 499 (this will hide the user account the list in System Preferences -> User Accounts)
    Account type: Administrator
    Home directory: /Users/admin
    UUID: leave as is
    Do not check Automatic login
    Package ID: com.company.create_admin_.pkg
    Version: 1.0
  3. Click Save Package.

First Boot scripts package

The point of a first boot package is to configure certain OS settings when the computer first boots up. This is best done through the use of a launch daemon that will call a script which configures your OS. The script will run only once and delete itself after running.

To create a first boot package we will need create three files first (in no particular order):

  1. a launch daemon plist file
  2. a postflight script
  3. a first boot script containing the configuration changes we want to set

postflight script

  1. Open up Text Wrangler or your text editor of choice and create the following postflight script and save it simply as postflight (no file extension). Keep in mind that this postflight should be edited so as not to contain changes that do not work in your environment:
#!/bin/sh
 
# Standard settings for images.
# Script is meant to be run as a postflight script in a .pkg file. Also installs startup settings script as a Launchd item which is inside the package /Contents/Resources directory.
 
##### Begin Declare Variables Used by Script #####
 
# Declare 'defaults'and 'PlistBuddy'.
 
defaults="/usr/bin/defaults"
PlistBuddy="/usr/libexec/PlistBuddy"
 
# Declare directory variables.
 
PKG_DIR="$1/Contents/Resources"
SCRIPTS_DIR="$3/Library/Scripts/CompanyName"
LAUNCHD_DIR="$3/Library/LaunchDaemons"
PRIVETC_DIR="$3/private/etc"
PREFS_DIR="$3/Library/Preferences"
USERPREFS_DIR="$3/System/Library/User Template/English.lproj/Library/Preferences"
NONLOC_USERPREFS_DIR="$3/System/Library/User Template/Non_localized/Library/Preferences"
ROOT="$3/"
UPDATE_DYLD="$3/usr/bin/update_dyld_shared_cache" # Set variable to location of update_dyld_shared_cache command on target volume.
 
##### End Declare Variables Used by Script #####
 
##### Begin Preference Setting #####
 
# These settings can be set on the target volume before startup.
 
# Run update_dyld_shared_cache
$UPDATE_DYLD -universal_boot -root $ROOT
 
# Display login window as Name and Password.
$defaults write "${PREFS_DIR}/com.apple.loginwindow" SHOWFULLNAME -bool YES
 
#Starts the Flurry screensaver over the login window when idle for 60 seconds
$defaults write "${PREFS_DIR}/com.apple.screensaver" loginWindowIdleTime -int 60
$defaults write "${PREFS_DIR}/com.apple.screensaver" loginWindowModulePath "/System/Library/Screen Savers/Flurry.saver"
 
# Sets autologout to 60 minutes and enables it
#$defaults write "${PREFS_DIR}/.GlobalPreferences" com.apple.autologout.AutoLogOutDelay -int 3600
 
# Use encrypted virtual memory.
$defaults write "${PREFS_DIR}/com.apple.virtualMemory" UseEncryptedSwap -bool Yes
 
# Set Safari Preferences.
$defaults write "${USERPREFS_DIR}/com.apple.Safari" HomePage "http://www.companyname.com"
$defaults write "${USERPREFS_DIR}/com.apple.Safari" ShowStatusBar -bool YES
 
# Set Finder Prefereces.
$defaults write "${USERPREFS_DIR}/com.apple.finder" ShowMountedServersOnDesktop -bool YES
 
# Enables Double Click Title bar to Minimize Window
$defaults write "${NONLOC_USERPREFS_DIR}/.GlobalPreferences" AppleMiniaturizeOnDoubleClick -bool TRUE
 
# No .ds-store files on Network Shares
$defaults write "${PREFS_DIR}/com.apple.desktopservices" DSDontWriteNetworkStores true
 
# Globally Set Expanded Print Dialouge Box.
$defaults write "${PREFS_DIR}/.GlobalPreferences" PMPrintingExpandedStateForPrint -bool TRUE
 
# Use short-name for logging into Network Shares
$defaults write "${PREFS_DIR}/com.apple.NetworkAuthorization" UseDefaultName -bool NO
$defaults write "${PREFS_DIR}/com.apple.NetworkAuthorization" UseShortName -bool YES
 
# Set Apple Mouse button 1 to Primary click and button 2 to Secondary click.
$defaults write "${USERPREFS_DIR}/com.apple.driver.AppleHIDMouse" Button1 -integer 1
$defaults write "${USERPREFS_DIR}/com.apple.driver.AppleHIDMouse" Button2 -integer 2
 
# Set Apple Magic Mouse button 1 to Primary click and button 2 to Secondary click.
$defaults write "${USERPREFS_DIR}/com.apple.driver.AppleBluetoothMultitouch.mouse" MouseButtonMode -string TwoButton
 
# Set Apple Magic Mouse inertia scroll mode.
$defaults write "${USERPREFS_DIR}/com.apple.driver.AppleBluetoothMultitouch.mouse" MouseMomentumScroll -bool YES

# Disable Mouse reverse scrolling.
$defaults write "${USERPREFS_DIR}/.GlobalPreferences" com.apple.swipescrolldirection -bool false
 
# Disable Time Machine Offers.
$defaults write "${PREFS_DIR}/com.apple.TimeMachine" DoNotOfferNewDisksForBackup -bool YES
 
# Disable Time Machine AutoBackup
$defaults write "${PREFS_DIR}/com.apple.TimeMachine" AutoBackup 0
 
# Enables SSH
#$PlistBuddy -c "Delete Disabled" $3/System/Library/LaunchDaemons/ssh.plist
 
# Allows any user to set dvd region
#$PlistBuddy -c "Set :rights:system.device.dvd.setregion.initial:class allow" "$3"/etc/authorization
 
# Firewall Settings | 0 = Off | 1 = On For Specific Services | 2 = On For Essential Services
$defaults write "${PREFS_DIR}/com.apple.alf" globalstate -int 0
 
# Activate "Require a password to unlock each System Preferences pane"
$PlistBuddy -c "Set :rights:system.preferences:shared false" /private/etc/authorization
 
##### End Preferences Setting #####
 
exit 0
  1. When the postflight script is saved, run the following command on it via Terminal:
    sudo chmod a+x /path/to/postflight

launch daemon plist

  1. Open up a new page in Text Wrangler or your text editor of choice and create the following launch daemon and save it simply as com.company.firstboot.plist (where com.company can be replaced by your reverse domain name):
<?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.company.firstboot</string>
	<key>ProgramArguments</key>
	<array>
		<string>/Library/Scripts/CompanyName/firstboot.sh</string>
	</array>
	<key>QueueDirectories</key>
	<array/>
	<key>RunAtLoad</key>
	<true/>
	<key>WatchPaths</key>
	<array/>
</dict>
</plist>
  1. Please change the line <string>'com.company.firstboot</string> to your organization name (e.g. com.afp548.firstboot).
  2. Please change the path in this line '<string>/Library/Scripts/CompanyName/firstboot.sh</string> so that it matches the actual name of the folder you will be using (e.g. /Library/Scripts/AFP548/firstboot.sh).

firstboot script

  1. Open up a new page in Text Wrangler or your text editor of choice and create the following firstboot script and save it simply as firstboot.sh. Keep in mind that this script should be edited so as not to contain changes that do not work in your environment:
#!/bin/sh
 
###
# First Boot script that is used along with a launchd item.  Deletes both itself and the launchd item after completion.
###
 
# Define 'kickstart' and'systemsetup' variables, built in OS X script that activates and sets options for ARD.
# Define 'networksetup'.
# Defines the location of the generic.ppd in OS X 10.6
 
kickstart="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart"
systemsetup="/usr/sbin/systemsetup"
networksetup="/usr/sbin/networksetup"
genericppd="/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/Resources/Generic.ppd"
scutil="/usr/sbin/scutil"
diskutil="/usr/sbin/diskutil"
 
# determine the disk size
MYDISK=`df -H | awk '{print $2}' | sed -n '2p'`
# Set the name for the boot volume accordingly
$diskutil renameVolume / "Mac"$MYDISK"B"
 
# Delete iMovie (Previous Version) Directory if it exists, because we don't need it.  Use when installing iLife using the original installers with InstaDMG.
rm -R /Applications/iMovie\ \(previous\ version\).localized/
 
# Check for network interfaces (on some models you might end up with no network connection otherwise)
$networksetup -detectnewhardware
 
# ARD Configuration
#Enable ARD for localadmin
$kickstart -configure -allowAccessFor -specifiedUsers
$kickstart -activate -configure -access -on -users "localadmin" -privs -all -restart -agent
 
# Set time zone and time server.
$systemsetup -setusingnetworktime on
$systemsetup -settimezone America/New_York -setnetworktimeserver time.apple.com
 
# Allow user to set DVD region once upon first insertion of disc
"$3"/usr/libexec/PlistBuddy -c "Set :rights:system.device.dvd.setregion.initial:class allow" "$3"/etc/authorization
 
#Update NTP
ntpdate -bvs time.apple.com
 
# turn ipv6 off for both Ethernet and Airport - if MacPro, service names are different(since that is required form of option for -setipv6off flag)
$networksetup -setv6off Ethernet
$networksetup -setv6off Ethernet\ 1
$networksetup -setv6off Ethernet\ 2
$networksetup -setv6off Airport# ensure AirPort is turned off - if this is a MacBookAir or (non-CTO) MacPro, this will have no effect, since its specifying 'hardware port' or BSD device (not service name) en1
$networksetup -setairportpower en1 off
 
#Disable Airport, another version
 $networksetup -setnetworkserviceenabled AirPort off
#OR disable airport only in a specific model. In this case on any iMac
if [ "`/usr/sbin/ioreg | grep iMac`" != "" ]; then
 	$networksetup -setnetworkserviceenabled AirPort off
fi
 
# make FireWire networking inactive
$networksetup -setnetworkserviceenabled FireWire off
 
 
# Activate WakeOnLAN.
$systemsetup -setwakeonnetworkaccess on
 
#Kerberos-Enabled SSH Authentication.  Also specifies which specific groups are allowed to ssh.
echo KerberosAuthentication yes >> /etc/sshd_config
echo KerberosOrLocalPasswd yes >> /etc/sshd_config
echo AllowGroups domaingroup admin >> /etc/sshd_config
 
#Firewall Settings | 0 = Off | 1 = On For Specific Services | 2 = On For Essential Services
defaults write /Library/Preferences/com.apple.alf globalstate -int 0
 
#Set System Sleep Preferences | 0 = Off | 15 = 15 Min | 20 = 20 Min | etc | 
pmset sleep 30
 
# set bonjour, host and sharing names based on patch level and en0 (ethernet) mac address
LAST6_ENETADDY=`ifconfig en0 | grep ether | awk '{print $2}' | sed 's/://g' | cut -c 7-12 | tr [:lower:] [:upper:]`
PATCHLVL=`/usr/bin/defaults read "/System/Library/CoreServices/SystemVersion" ProductVersion | sed 's/[.]/-/g'`
$scutil --set LocalHostName "Imaged-$PATCHLVL-$LAST6_ENETADDY.local"
$scutil --set ComputerName "Imaged-$PATCHLVL-$LAST6_ENETADDY"
$scutil --set HostName "Imaged-$PATCHLVL-$LAST6_ENETADDY"
 
# IF DeployStudio Sets HostName+LocalHostName, all you need is:
$scutil --set HostName $(scutil --get LocalHostName)
 
# Adds Printers
lpadmin -p "Printer Name" -L "Printer Location" -D "Printer Description" -E -v lpd://server/printqueue -P $genericppd -o printer-is-shared=false
 
# Removes Time Machine from the menu
defaults write com.apple.TimeMachine DoNotOfferNewDisksForBackup 1
 
# Creating a new local account with guest properties but different name. 
 The user gets a warning that his data will be deleted on log out
dscl . -create /Users/visitor
dscl . -create /Users/visitor UserShell /bin/bash
dscl . -create /Users/visitor RealName "Visitor"
dscl . -create /Users/visitor UniqueID 201
dscl . -create /Users/visitor PrimaryGroupID 201
dscl . -create /Users/visitor NFSHomeDirectory /Users/Visitor
dscl . -create /Users/visitor RecordType dsRecTypeStandard:Users
dscl . -create /Users/visitor dsAttrTypeNative:_defaultLanguage en
dscl . -create /Users/visitor dsAttrTypeNative:_guest true
dscl . -create /Users/visitor dsAttrTypeNative:_writers__defaultLanguage visitor
dscl . -create /Users/visitor dsAttrTypeNative:_writers_jpegphoto visitor
dscl . -create /Users/visitor dsAttrTypeNative:_writers_LinkedIdentity visitor
dscl . -create /Users/visitor dsAttrTypeNative:_writers_picture visitor
dscl . -create /Users/visitor dsAttrTypeNative:_writers_UserCertificate visitor
dscl . -passwd /Users/visitor 

# Hide users with a UID below 500 from User Accounts under System Preferences.
defaults write /Library/Preferences/com.apple.loginwindow Hide500Users -bool TRUE

# Disables iCloud pop-up on first login for Macs running 10.7.2 or higher. 
defaults write /System/Library/User\ Template/Non_localized/Library/Preferences/com.apple.SetupAssistant DidSeeCloudSetup -bool TRUE
defaults write /System/Library/User\ Template/Non_localized/Library/Preferences/com.apple.SetupAssistant GestureMovieSeen none

# Disables Apple ID / iCloud prompt on first login for Macs running 10.8.0 or higher
defaults write /System/Library/User\ Template/English.lproj/Library/Preferences/com.apple.loginwindow -dict "
defaults write /System/Library/User\ Template/English.lproj/Library/Preferences/loginwindow -dict "
defaults write /System/Library/User\ Template/English.lproj/Library/Preferences/com.apple.SetupAssistant DidSeeCloudSetup -int 1
defaults write /System/Library/User\ Template/English.lproj/Library/Preferences/com.apple.SetupAssistant LastSeenCloudProductVersion 10.8
defaults write /System/Library/User\ Template/Non_localized/Library/Preferences/com.apple.loginwindow -dict "
defaults write /System/Library/User\ Template/Non_localized/Library/Preferences/loginwindow -dict "
defaults write /System/Library/User\ Template/Non_localized/Library/Preferences/com.apple.SetupAssistant DidSeeCloudSetup -int 1
defaults write /System/Library/User\ Template/Non_localized/Library/Preferences/com.apple.SetupAssistant LastSeenCloudProductVersion 10.8

# Disables Gatekeeper
spctl --master-disable


# Reboot in 1 minute
sleep 60
reboot
 
# Delete the script and the launchd item.
srm /Library/LaunchDaemons/com.company.firstboot.plist
srm "$0"

Be sure to edit the second to last line in the script so that it matches the name of the launch daemon plist file you created earlier.

Let's get started:

  1. Open Iceberg (if you don't have it you can download it from http://s.sudre.free.fr/Software/Iceberg.html ).
  2. Click on File and then New Project.
  3. We’ll need to run this installer with root privileges. Select the project type Darwin: Package.
  4. Name the project appropriately and make sure to save the project to a location that's easy for you to find (~/Desktop). In this case, I’m naming the project Firstboot.
  5. On the left side window of Iceberg, click on Scripts.
  6. Check postflight.
  7. Drag the newly created postflight script to that same line.
  8. Click on the Files section on the left side menu.
  9. Right-click the Library folder and select Add Files....
  10. Browse to path /Library/LaunchDaemons and click Add twice.
  11. Right-click the LaunchDaemons folder and select Add Files....
  12. Browse to the launch daemon plist file you created earlier and click Add twice.
  13. Right-click the Library folder and select Add Files....
  14. Browse to path /Library/Scripts and click Add twice.
  15. Right-click the Scripts folder and select New Folder.
  16. Name the new folder COMPANYNAME (e.g. AFP548). This has to be exactly the same as is referenced in the launch daemon plist file.
  17. Right-click the COMPANYNAME folder and select Add Files....
  18. Browse to path firstboot.sh script you created earlier and click Add twice.
  19. Right-click firstboot.sh and select Show Info.
  20. Set Owner: root and Group: wheel. Make sure permissions are 754 which means Owner: R W X, Group: R — X, Others: R — —. Close the Information window when done.
  21. Click on Build menu and select Build.
  22. You should now have a package that should be located in ~/Desktop/Firstboot/build/

Recovery Partition

As of r458, InstaDMG by default creates a Recovery Partition. You can turn off this feature if you want by editing line 738 in the instadmg.bash file which reads as follows: https://code.google.com/p/instadmg/source/detail?r=458

Before:

/usr/bin/hdiutil create -size $DMG_SIZE -volname "$ASR_FILESYSTEM_NAME" -layout "$LAYOUT_TYPE" -type SPARSE -fs "HFS+" "$SHADOW_FILE_LOCATION" | (while read INPUT; do log "$INPUT " detail; done)

After:

/usr/bin/hdiutil create -size $DMG_SIZE -volname "$ASR_FILESYSTEM_NAME" -layout "$LAYOUT_TYPE" -type SPARSE -fs "HFS+J" "$SHADOW_FILE_LOCATION" | (while read INPUT; do log "$INPUT " detail; done)

Best Practices

It is important that before we start making an image, we think about what settings we will want to set on the image itself as well as which settings we could set using Open Directory via Workgroup Manager. If you have Open Directory available in your environment, it is best to manage your settings using OD as much as is possible, although you might still want to do the initial settings on the image. The easiest way to go about figuring out which settings you want to modify is by starting with a plain vanilla install of OS X and looking at what you want to be set by default. Make a checklist or whatever works for you to keep track of all the settings that you want to change.

Creating a Work Flow

With all this knowledge you can think of catalogs as a way to create work flows. You will most likely not want to have all your packages in one big catalog file as this will clearly require you to constantly keep updating the catalog file. That can get messy quickly if you want to have different images for different groups of computers. For example, in a university, you might have to maintain one image for a lab, another for staff computers, and a third for student laptops. The list can grow pretty quickly. If you’re working off that one catalog file, it would require you to continually edit it.

The best practice here is to create multiple catalog files each with specific purposes. As an example, here is a work flow utilizing multiple catalog files:

  • 10.7_vanilla (base OS updates, comes with InstaUp2Date)
  • iLife 09 (includes installer for iLife 09)
  • iLife 09 updates (includes updates for iLife 09, comes with InstaUp2Date)
  • University software (includes software that is used in all university computers)
  • Office 2011 (includes installer and updates for Office 2011)
  • Custom settings (includes some custom settings for software used in the University catalog)
  • Base Settings (includes some Base OS settings such as CreateAdminUser and ClearReg)

Let’s say you have two sets of users to make an image for: staff and students. The staff image will contain all the catalogs, but the student image will contain ALL EXCEPT Custom Settings and Base Settings. In this situation, you have to create two additional catalog files to call the previous catalogs mentioned above specific to the staff and student image you wish to create.

Here is where the following line will come in handy in the catalog file (has to be tab-separated):

include-file: <file-name or path>

As examples, the two catalog files would look like this:

Staff Image.catalog

# Image for Staff computers.

Output Volume Name:	Macintosh HD
Output File Name:	10.7.1 Staff Image

include-file:	10.7_vanilla
include-file:	iLife 09
include-file:	iLife 09 updates
include-file:	University software
include-file:	Office 2011
include-file:	Custom Settings
include-file:	Base Settings

Student Image.catalog

# Image for Student computers.

Output Volume Name:	Macintosh HD
Output File Name:	10.7.1 Student Image

include-file:	10.7_vanilla
include-file:	iLife 09
include-file:	iLife 09 updates
include-file:	University software
include-file:	Office 2011

Now all you have to do in terminal is call the one catalog which will call all other catalog files. If you wanted to, you could break down the University software catalog and get more granular. Adapt according to your own environment needs.

Just make sure that the catalogs are being called in the right order otherwise you could run into problems (i.e. you don’t want iLife 09 updates running before iLife 09 and so on).

Also note that you will have to comment out or remove some lines in the catalogs being referenced such as:

Output Volume Name:	Macintosh HD
Output File Name:	10.7 Vanilla

If you don’t comment out these lines, InstaDMG will output a DMG file that will work off the Volume Name and File name from the first catalog in your workflow. So that means you will have to edit usually the vanilla catalog you are working off of.

Packaging

Even though packaging was briefly covered with the Firstboot.pkg, we will not go in-depth into packaging software. You can read all about packaging by reading the article Guidelines for Mac software packaging (Guide). But there are a few things regarding it worth mentioning that may affect InstaDMG:

  • If possible, avoid re-packaging software. You really shouldn’t have to, but if absolutely necessary go ahead. Once you’ve re-packaged software, it’s hard to know where exactly things went wrong if they do.
  • Not all packages will work perfectly in InstaDMG. Some companies make installers that simply don’t play nice (and not just with InstaDMG). In cases like this, you might have to dig into the package and mess around with the pre-flight/post-flight scripts. As an example Office 2011 needs to be modified to get it working with InstaDMG.
  • If you have to re-package software, do not do so just for the sole purpose of including customizations into the package. Use multiple packages to make your life easier. The first package would be of the software in its default state (the original installer). Then the other packages could be customizations. As an example, rather than re-package Firefox with customizations, you can simply create a package that contains the customizations that you want Firefox to have (bookmarks, preferences, etc). So in case anything goes wrong, you don’t have to keep re-packaging Firefox. Perhaps Firefox seems like a small program to use as an example. But imagine having to re-package Final Cut Studio 3 only because you needed to add some customization? That’s a huge program (~50GB) to re-package!

Updating OS specific catalogs

While the catalog files are updated regularly, sometimes you may be in a crunch and may not have time to wait for the svn to be updated. If that happens, you can modify and/or create your own OS catalogs to include new updates from Apple. When you do so, make sure updates are installed in order so that you avoid running into problems. Here are some steps that will help you avoid potential problems:

  1. Restore the BaseOS cache file per build (10.5.6, 10.6.3, 10.7.0 and newest Lion from the MacAppStore).
  2. Boot with no packages added/workflows applied (i.e., don't use deploystudio, just asr at the command line) and run the gui swupdate manually.
  3. grep the install.log for the order in which the packages are applied (only 10.5 had a SoftwareUpdate log, but 'installed' is a good keyword to cut through the fluff).
  4. Rinse and repeat until gui swupdate returns no packages

Then, when compiling those in order, note two other things:

  • Remove any superfluous(hardware/accessory-specific, EFI/firmware/thunderbolt) updates and
  • Check iLife updates with the same gui manner on the most popular version of the OS

User Templates

This is by no means recommended, but it does work. If you need all new users to be configured a certain way on their first log in, you can make use of the User Templates folder located in: /Macintosh HD/System/Library/User Templates/English.lproj

This comes in handy when creating packages. If you’re familiar with Windows, this is the equivalent of the Default User folder. But keep in mind that that folder could be modified by Apple updates at any moment. Use at your own risk! If you wish to do things properly, you may want to look more into Managed Preferences (MCX) which is outside the scope of this guide.

Test, test, test...

You always want to make sure that you can test your images and see that the changes you’ve made have taken effect. A quick simple way to do this is by creating a partition in Disk Utility that you will constantly wipe out by restoring the image you’ve created in InstaDMG.

Installer Choices

Some installers give you different custom options on what to include during installation. When you’re deselecting boxes in the GUI interface, it tells the installer being modified what to include in comparison to its Standard Install (which would be everything presented by default according to how Apple built the mpkg). Taking a step back, this customization is only possible when working with a mpkg. Since we can bundle many pkg installs into one mpkg, when the mpkg is built you may be able to specify certain things to leave out or include, whether or not they are even visible in the GUI installer.

The InstallerChoices readme has a link to a more thorough process, but a one-liner to get started with is:

sudo installer -showChoicesXML -pkg $PATH_TO_MPKG

Where PATH_TO_MPKG= would be /Volumes/Mac\ OS\ X\ Install\ DVD/System/Installation/Packages/OSInstall.mpkg in the case of the retail Snow Leopard OS install itself. Following the instructions in that forum post above for Snow Leopard should end you up with something like this figure:

<array>
	<string>Popular_PrintDrivers</string>
	<string>LanguageTranslations</string>
	<string>AdditionalFonts</string>
	<string>Rosetta</string>
</array>

Every string in this InstallerChoices.xml is considered a click on the checkbox in the GUI installer. In the case of the Snow Leopard install retail disc, it will deselect Nearby and Popular Printers, Language Translations, Additional Fonts, and will select Rosetta.

How to extract Installer Choices on Leopard (OS X 10.5)

Some of this may not be the most elegant way to handle this, but it does work. The example used here is referring to the OS X 10.5 installer.

Step 1: Extract the choice information from the target installer

Use the following command in Terminal:

sudo installer -showChoicesXML -pkg /Volumes/Mac\ OS\ X\ Install\ DVD/System/Installation/Packages/OSInstall.mpkg > /Users/Shared/OSInstall.mpkg_default_choices.xml

This will output a list of the various choices the installer provides, whether they are visible or not within Installer.app. What we're really interested in is the choiceIdentifier tags throughout the file.

grep -A 1 choiceIdentifier /Users/Shared/OSInstall.mpkg_default_choices.xml > /Users/Shared/OSInstall.mpkg_choiceIdentifiers.txt

This will output a text file of more or less readable choiceIdentifiers. Note that there are possibly more choiceIdentifiers in the output of the above command than you actually see in Installer.app. This is normal, since something like "Essential System Software" is more than one package, but you don't really want to not install pieces unless you know what you're doing.

Step 2: Pick your choices

Thumb through the choiceIdentifiers outputted above. You'll probably see items you recognize from Installer.app that you know you want to turn off or on. This would be a good time to actually start the installer of interest and examine the options provided by the installer (for example, Leopard provides these options behind the Customize... button). This will allow you to focus on the important customizations easily.

Choose the choiceIdentifiers you wish to address. Each entry listed is a click within Installer.app. In this case, we want to "click" (disable, since they are enabled by default) the printer drivers (choiceIdentifier "PrinterDriversGroup"), additional fonts (choiceIdentifier "AdditionalFonts"), and X11 (choiceIdentifier "X11"). Create a plain text file (we’ll call ours "Leopard_Choices.xml") and place the choiceIdentifiers inside an array of string tags.

<array> <string>PrinterDriversGroup</string> <string>AdditionalFonts</string> <string>X11</string> </array>

If you have a half-clicked (appears as a dash instead of a checkmark) installation option inside Installer.app, you'll need to list it as many times in the text file as you would need to click it in Installer.app. Click the option twice to clear it inside Installer.app? List it twice in the text file.

Enabling or disabling choices may cause other options to become available or disappear (for example, iSync required iCal in 10.3 and thus you could not disable installing iCal unless the iSync installation was first disabled). To check to see what happens if your text file of choices is applied to a particular installer, run the following command:

sudo installer -showChoicesAfterApplyingChangesXML Desktop/Leopard_Choices.xml -pkg /Volumes/Mac\ OS\ X\ Install\ DVD/System/Installation/Packages/OSInstall.mpkg > /Users/Shared/OSInstall.mpkg_afterChoiceXML.xml

Compare OSInstall.mpkg_default_choices.xml and OSInstall.mpkg_afterChoiceXML.xml to ensure you are enabling and disabling the desired packages.

Step 3: Use your Choices

When running installer from the command line, tell installer to look at your choices:

sudo installer -applyChoiceChangesXML /Users/Shared/Leopard_Choices.xml -pkg /Volumes/Mac\ OS\ X\ Install\ DVD/System/Installation/Packages/OSInstall.mpkg -target /Volumes/TargetHD

Note: Unless the installer is pointed at a particular partition/disk with the -target option, it assumes that you will be installing to /. This presents a problem if you're building an Installer Choice Changes file because the options provided by installer reflect the current installed software on /. If you build your development partition without languages to save installation time, the choices provided by installer and showChoicesXML will not list the languages as enabled.

Point installer at a partition/disk that doesn't have an OS installed to get the plain vanilla showChoicesXML

installer -target /Volumes/InstaDMG_Target

or keep in mind that your XML will reflect the current target of installer.

Editing the Choices File

This example refers to Microsoft Remote Desktop Connection (RDC) for Mac.

Normally if you install RDC, you will end up with an icon in your dock. The option to disable this is unfortunately disabled by Microsoft and normally not visible, but can be enforced nevertheless using an XML choices file. The XML choices file is very similar in concept to an answer file you would give Windows Setup. It contains the choices you would make as a user sitting in front of the installer.

  1. Download the DMG file and unpack the installer package to your desktop.
  2. Open terminal, change the path to the desktop and use the following command to extract a template of the choices file:
    installer -showChoiceChangesXML -pkg RDCInstaller.mpkg/>choices.txt
  3. This will generate a file choices.txt, which can be edited to set the options you require.
    • Edit choices.txt to reflect the options you would like to install RDC with (see below for further details)
    • Test whether the changes you made to the file would be accepted by installer with the command
      installer -showChoicesAfterApplyingChangesXML choices.txt -pkg RDCInstaller.mpkg/>appliedchanges.txt

Installer will throw an error if you gave it a bad file. Or it will just ignore your own choices file, if it is not correctly formatted. You can see this if you go through appliedchanges.txt and there is no difference to the default settings. You could also compare appliedchanges.txt with choices.txt you generated earlier using the command:
diff appliedchanges.txt choices.txt

Install RDC by command line, with your customized options.

installer -applyChoiceChangesXML choices.txt -pkg RDCInstaller.mpkg/ -target /

That’s how to silently install a Mac OS Installer Package with custom options.

The above examples up to now have described the method of simulating mouse clicks. But there’s another method which relies on simply entering the values you want.

The output of the command:

installer -showChoiceChangesXML -pkg RDCInstaller.mpkg/>choices.txt

will give you a raw dump of the possible choices you could change. There will be a lot of useless entries you don't need, and you will have to discard the <plist> tags.

Here is a dump of the choices file unedited:

<?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">
<array>
   <dict>
      <key>attributeSetting</key>
      <false/>
      <key>choiceAttribute</key>
      <string>visible</string>
      <key>choiceIdentifier</key>
      <string>rdc</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <true/>
      <key>choiceAttribute</key>
      <string>enabled</string>
      <key>choiceIdentifier</key>
      <string>rdc</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <integer>1</integer>
      <key>choiceAttribute</key>
      <string>selected</string>
      <key>choiceIdentifier</key>
      <string>rdc</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <false/>
      <key>choiceAttribute</key>
      <string>visible</string>
      <key>choiceIdentifier</key>
      <string>dock</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <true/>
      <key>choiceAttribute</key>
      <string>enabled</string>
      <key>choiceIdentifier</key>
      <string>dock</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <integer>1</integer>
      <key>choiceAttribute</key>
      <string>selected</string>
      <key>choiceIdentifier</key>
      <string>dock</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <false/>
      <key>choiceAttribute</key>
      <string>visible</string>
      <key>choiceIdentifier</key>
      <string>appsupport</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <true/>
      <key>choiceAttribute</key>
      <string>enabled</string>
      <key>choiceIdentifier</key>
      <string>appsupport</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <integer>1</integer>
      <key>choiceAttribute</key>
      <string>selected</string>
      <key>choiceIdentifier</key>
      <string>appsupport</string>
   </dict>
</array>
</plist>

For what we wish to accomplish (disable the creation of the RDC dock icon), the choices file has been edited to simply:

<array>
   <dict>
      <key>attributeSetting</key>
      <false/>
      <key>choiceAttribute</key>
      <string>visible</string>
      <key>choiceIdentifier</key>
      <string>dock</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <true/>
      <key>choiceAttribute</key>
      <string>enabled</string>
      <key>choiceIdentifier</key>
      <string>dock</string>
   </dict>
   <dict>
      <key>attributeSetting</key>
      <integer>0</integer>
      <key>choiceAttribute</key>
      <string>selected</string>
      <key>choiceIdentifier</key>
      <string>dock</string>
   </dict>
</array>

You can either keep every <dict> entry, or you can delete everything you don't need. It works both ways. Note the strange format of the file. A <dict> consist of 3 entries. Relevant for the choices file is only the selected attribute. You can change it from "1" to "0". By reading the descriptive text in the -showChoicesXML dump you can find out what dock is supposed to mean. There is another command line switch for installer, namely -showChoicesXML. Compare this to -showChoiceChangesXML. The two are ENTIRELY DIFFERENT commands. Don't make the mistake of using the wrong command. The man-page (type man installer in Terminal) for installer is a bit problematic as it shows just one of the switches at the top. But: -showChoicesXML is actually very useful. Give it to installer like this to get a lot more human-readable content, as a guide for building your choices file:

installer -showChoicesXML RDCInstaller.mpkg/

The output will contain the descriptive text you would normally see in the installer GUI, right next to the internal names of the options. With this information it’s a lot easier to look for the correct options to select / deselect.

Using InstallerChoices

So now that you got your InstallerChoices.xml, you can use it in the catalog file. Pay attention to the last line:

Installer Disc Builds:	10J3210

ISO Language Code = en

Output Volume Name:	Macintosh HD
Output File Name:	QC_Mac_1067_10J3250_TB_test.dmg

Base OS Disk:
Installer Choices File:	/Users/MyAccount/Dev/instadmg/InstallerFiles/BaseOS/InstallerChoices.xml	sha1:390db880591bec5ff37d92aa2bcb4d21b5639d46

As another example, say you wanted to use it on a package that wasn’t the OS, you can simply use the following in the catalog file:

	Office2011	/instadmg/InstallerFiles/InstaUp2DatePackages/Office Installer.mpkg	sha1:06f726c6f6eb870ccbb777d5a1adcd67892cf88e	/instadmg/Caches/InstaUp2DateCache/InstallerChoices.xml

As always, make sure lines are tab-separated.

Speeding up the creation of your images

InstaDMG will only go as fast as the hard drive it is being run on. It does not depend on CPU or RAM as much. So the faster the hard drive, the quicker it will run. However, you can use a scratch disk to speed things up even further. This will allow all the reading to be done on your primary hard drive while all the writing is done on a secondary hard drive.

Here is the command to use for a scratch disk:

sudo ./instaUp2Date.py -p 10.7_vanilla.catalog --instadmg-scratch-folder=/Volumes/ScratchDriveName

where /Volumes/ScratchDriveName is second drive you wish to use as the scratch disk.

Using InstaDMG only, not InstaUp2Date

Earlier we saw, the InstaUp2Date python program take its instructions from the 10.7_vanilla catalog file, and then proceed to download the updates listed and place them in a cache folder. It checked that you received the updates you wanted “as advertised” (i.e. not corrupted or altered) by verifying the sha1 checksum, included in the catalog file.

Symbolic links (a.k.a. aliases or shortcuts, loosely speaking) are created to point from where InstaDMG would expect packages in the directory structure to where the files that have been cached. InstaDMG is then started up, via being called by the --process flag, at which point instaup2date.pyʼs most visible function is complete.

It was eluded to earlier, but just to re-iterate. InstaUp2Date is a separate component from InstaDMG. It really does make the workflow easier to manage. But if for whatever reason you must do things the old fashion way:

If we’re not utilizing InstaUp2Date to take care of the moving around of packages, we need to sort them ourselves. Adding packages (or mpkgs) to our image after the OS is installed, and making sure iLife gets installed before its updates are applied, means we need to get a handle on what order things are installed in. Even though many of these packages will be updates we get from Apple, it’s a good idea to separate out the ones that deal with the core functionality of the OS (in ./instadmg/InstallerFiles/BaseUpdates) and others, including software or peripheral-specific ones (which belong in ./instadmg/InstallerFiles/CustomPKG).

Manually running updates for the OS (or other products like iLife or Microsoft Office) with their native update software can make it easy to see exactly what order updates should be applied in. In the GUI you can check by going into System Preferences -> Software Update and looking under the Installed Updates tab. Once we’ve assembled the update packages, we place them in numbered folders (01, 02, 03, etc.) with one package per folder to be specific about their ordering.

If you want to get really down and dirty with InstaDMG.bash….

InstaDMG Flags

If you feel inclined, here are some flags you can use with InstaDMG.bash:

Flag/Option Syntax Information
-b <folder path> Look for the base image in this folder (${INSTALLER_FOLDERS[@]})
-c <folder path> Look for custom pkgs in this folder ($CUSTOM_FOLDER)
-f Enable non-paranoid mode (skip checking image checksumms)
-h Print the useage information (this) and exit
-i <iso code> Use <iso code> for the installer language ($ISO_CODE)
-l <folder path> Set the folder to use as the log folder ($LOG_FOLDER)
-m <name> The file name to use for the ouput file. '.dmg' will be appended as needed. ($ASR_OUPUT_FILE_NAME)
-n <name> The volume name to use for the output file. ($ASR_FILESYSTEM_NAME)
-o <folder path> Set the folder to use as the output folder ($ASR_FOLDER)
-q Quiet: print only errors to the console
-r Disable using chroot for package installs ($DISABLE_CHROOT)
-s Do not replace the installd daemon with a chrooted version ($DISABLE_INSTALLD_CHROOT)
-t <folder path> Create a scratch space in this folder ($TEMPORARY_FOLDER)
-u <folder path> Use folder as the BaseUpdates folder ($UPDATE_FOLDER)
-v Print the version number and exit
-w <folder path> Disk to erase and restore the new image to for testing
-y Enable erase-and-restore of new image to testing volume
-z Disable caching of the base image ($DISABLE_BASE_IMAGE_CACHING)
-I <dmg path> Use dmg at this path as the installer disc.
-J <dmg path> Mount dmg at this path during installs.
-K <folder path> Use folder as a source for updates, call multiple time in order for multiple folders.
-L <file path> Use file as installerChoices file for base install

Here are a few examples:

Example 1:

sudo ./instadmg.bash -s -I ./InstallerFiles/BaseOS/InstallESD.dmg -n "Macintosh HD" -m 10.7.0_LionTest

S flag stops installd daemon from being replaced with a chrooted version. I flag specifies the path of the install disc which is located in ./InstallerFiles/BaseOS/InstallESD.dmg. The n flag in this case calls the volume Macintosh HD. And the m flag is the name of the file that is finally created.

Example 2:

sudo ./instadmg/instadmg.bash -f -t /Volumes/stripedRAID0 -o /Volumes/stripedRAID0 -m Dev_10-6-5 -n Restored

F flag denotes non-paranoid mode, which will therefore skip the verification of image checksums. The subsequent flags have the effect of multiplying the spindles doing the work; our InstaDMG directory structure can be housed on a separate disk for the sole purpose of reading the packages( these days that would be a SSD with its superior sequential reads nearly saturating the SATA bus) and another location designated by the T flag (in this example a RAID0 volume), is utilized for both writing the intermediate image into its root directory (instead of the default /tmp of your currently booted volume), and putting the final asr-ready output file (-o, instead of ./instadmg/OutputFiles/).

The M and N flags are convenient ways to help you tell your images apart by setting what you want the resulting asr image to be named, both before restoration (-m, which would result in Dev_10-6-5.dmg instead of the default naming 10-11-17.dmg for November 17th, 2010) and after (-n, so the resulting partition name would be Restored instead of the default InstaDMG).

Other Uses of InstaDMG

Thin Imaging (Modular Imaging)

Currently there has been a move towards a process called thin imaging or modular imaging. The process goes something like this:

  1. Taking computer out of the box
  2. NetBoot into your software deployment utility (DeployStudio, JAMF Casper, Absolute Manage, to name a few)
  3. Deploy the software to the computer and you’re done!

InstaDMG can fit nicely into this process. To do so, all you need to do is create a base image with InstaDMG. After this you will have two options:

  • Use the image created with InstaDMG as the base for your imaging work flow and then let another software deployment utility handle subsequent updates to the software you included in your InstaDMG image.
  • Create an InstaDMG image with Munki (or your software deployment tool of choice). Munki in this case will download all the applications once the computer is booted and also handle updates as well. To learn more about Munki, go to http://code.google.com/p/munki/

References

Also keep in mind, InstaDMG and InstaUp2Date are scripts you can open and look at, so feel free to read through all the options, or pass the --help flag to it. Questions/feedback about this guide? [email protected]

Credits This documentation is a huge compilation of different sources. Many contributed to some of the links provided in the documentation. Some of these contributors include: Mr. Kuehn, Mr. Wisenbaker, Mr. Fergus, Mr. Akins, Mr. Meyer, Mr. Larizza, Mr. Walck, Mr. van Bochoven, Mr. Banks, Mr. Franzkoch, Mr. Pavlov, Mr. Gee, and more!