Skip to content

Workflow Config

Ryan Buzzell edited this page Sep 28, 2018 · 74 revisions

Imagr supports multiple workflows - these workflows consist of components like the image to restore, packages, and scripts. The serverurl key points to your workflow configuration, referenced in the documentation as imagr_config.plist. This plist can be named anything but needs to match your serverurl key from com.grahamgilbert.Imagr.plist. The majority of the options should be straightforward (sample located at the bottom).

Table of Contents

Component Ordering

Imagr will respect the order you put your components in, and will perform the tasks sequentially. Keep in mind that therefore you need to arrange components in the following order to result in the computer name being set properly, because the image task will erase the disk before the naming script will be copied to the target volume:

<dict>
    <key>type</key>
    <string>image</string>
    <key>url</key>
    <string>http://192.168.178.135/osx_custom_150410-10.10.3-14D131.hfs.dmg</string>
</dict>
<dict>
    <key>type</key>
    <string>computer_name</string>
</dict>

Configuration Plist Validation

There is a validation tool included with the git checkout and with the release DMG. You should use it to perform some basic checks on your configuration before running Imagr. You can either use a local file path or a URL.

# Using a local file
$ ./validateplist ~/Desktop/imagr_config.plist

# Using a URL
$ ./validateplist http://192.168.33.10/imagr_config.plist

Root

The following deals with Root level configuration settings.

Password

The password is a SHA hash - designed to stop customers from accidentally imaging their computers, not to keep the crown jewels safe! To generate one:

$ python -c 'import hashlib; print hashlib.sha512("YOURPASSWORDHERE").hexdigest()'

The resulting key/value pair in the workflow config would look like this (substituting the sha512 hash from the command above):

<key>password</key>
<string>INSERTSHA512HERE</string>

As of Imagr 1.0.0, the password is no longer required. Leaving the password key out of the configuration will bypass the login screen entirely. This may allow users to re-image their own machines, so be careful.

Autorun

Imagr has the ability to automatically execute a workflow without user interaction. When Imagr launches and the autorun property is set, a 30s countdown begins. Once the timer expires, the workflow specified in the property is executed.

<key>autorun</key>
<string>Munki_10103</string>

If a password is set, the countdown will only begin once a user has logged in. Users may click the Cancel button and choose a different workflow to execute.

The value must match the name of one of the workflows or validation will fail.

Autorun Time

As of 1.3.5, Imagr now has the capability to configure an arbitrary countdown time. If the key is not present, it will honor the autorun property of 30s.

<key>autorun_time</key>
<integer>5</integer>

Default Workflow

By default, Imagr displays the configured workflows in the order in which they were defined. The first workflow in the configuration file is automatically chosen in the "Choose Workflow" dropdown box.

The default_workflow key allows you to override this behaviour.

<key>default_workflow</key>
<string>Munki_10103</string>

The value must match the name of one of the workflows or validation will fail. This setting only affects the UI.

Background Image

A custom background image can be specified inside the config's main dict (not inside any workflows array):

<key>background_image</key>
<string>http://192.168.33.10/Imagr.jpg</string>

As of Imagr 1.1.1, Imagr can append the NetBoot environment's OS version and build as a query string to the URL, as well as the screen's dimensions and aspect ratio, in case you want to return a customized image. For example: Imagr.jpg?osver=10.11.5&osbuild=15F34&w=2560&h=1440&a=16-9 or Imagr.jpg?osver=10.13.6&osbuild=17G2112&w=1680&h=1050&a=8-5 (8-5 being the "lowest common denominator" reduction of a 16-10 aspect ratio).

The background window is automatically displayed unless Imagr is running from the Finder. You can control it by changing the background_window setting in the App-Config, possible values are never, always, and auto (the default).

Wait for Network

By default, Imagr's first boot script will wait for a valid network connection before proceeding. If your first boot items, configure the network interface, this will be undesirable. To stop this, use the wait_for_network key - this is a boolean (True or False).

<key>wait_for_network</key>
<false/>

Workflow

The following section details with workflow level configuration settings.

Restart Action

Each workflow can have a restart_action defined. If no restart_action is specified, Imagr will fall back to the default of none. The restart action can be overridden by a component - useful if you wish to use a scripted included workflow to set the restart action.

  • restart: Once the workflow is completed, Imagr will restart to the target volume.
  • shutdown: Once the workflow is completed, Imagr will set the startup disk to the target volume and shut the Mac down.
  • none: Once the workflow is completed, Imagr will present a dialog asking if the Mac should be shut down, restarted or if another workflow should be run.
<key>restart_action</key>
<string>restart</string>

Setting in a component:

<dict>
    <key>type</key>
    <string>restart_action</string>
    <key>action</key>
    <string>restart</string>
</dict>

First Boot Restart Action

Each workflow can have a first_boot_reboot defined. If no first_boot_reboot is specified, Imagr will fall back to the default of True.

  • True: Once the first boot process is completed, Imagr will clean up and trigger a reboot.
  • False: Once the first boot process is completed, Imagr will clean up and kill LoginLog.
<key>first_boot_reboot</key>
<false/>

Hidden

By default, all workflows are included in the dropdown. If you have workflows that are only to be used within another workflow as an included workflow component, you should make them as hidden. Defaults to false.

<key>hidden</key>
<true/>

Startup Disk

By default, Imagr will bless the target volume to set it as the startup volume. This is usually desirable, but in some cases you will want to not do this (for example, when using createOSXinstallPkg). To avoid this, use the following in your workflow:

<key>bless_target</key>
<false/>

For a full example see the Install OS X workflow in the Sample imagr_config.plist

Component

The following section deals with Imagr components and their settings.

Images

Disk Images to restore are mounted over HTTP & then restored via Apple Software Restore (asr) to the target volume, and as such any images added will need to be scanned for restore beforehand. Verification of the restored image defaults to true. When deploying macOS 10.13 High Sierra, it is recommended that you now use startosinstall instead.

<dict>
    <key>type</key>
    <string>image</string>
    <key>url</key>
    <string>http://192.168.178.135/osx_custom_150410-10.10.3-14D131.hfs.dmg</string>
</dict>

As of Imagr 1.1, you can optionally disable image verification. Below is an example.

<dict>
    <key>type</key>
    <string>image</string>
    <key>url</key>
    <string>http://192.168.178.135/osx_custom_150410-10.10.3-14D131.hfs.dmg</string>
    <key>verify</key>
    <false/>
</dict>

As of Imagr 1.4, you can optionally use a RAM Disk. Below is an example.

<dict>
    <key>type</key>
    <string>image</string>
    <key>url</key>
    <string>http://192.168.178.135/osx_custom_150410-10.10.3-14D131.hfs.dmg</string>
    <key>ramdisk</key>
    <true/>
</dict>

For additional information on RAM disks, please see this wiki article

startosinstall

startosinstall allows you to install macOS, similarly to how Internet Recovery/Mac App Store function. This optional is available on Imagr 1.4 and higher.

<dict>
    <key>type</key>
    <string>startosinstall</string>
    <key>url</key>
    <string>http://192.168.178.135/Install%20macOS%20High%20Sierra-10.13.dmg</string>
</dict>

For additional notes on startosinstall please see this wiki article

As of Imagr 1.4, you can optionally use a RAM Disk. Below is an example.

<dict>
    <key>type</key>
    <string>startosinstall</string>
    <key>url</key>
    <string>http://192.168.178.135/Install%20macOS%20High%20Sierra-10.13.dmg</string>
    <key>ramdisk</key>
    <true/>
</dict>

For additional information on RAM disks, please see this wiki article

Included Workflow

It is possible to chain workflows together using the included_workflow type. Many environments will have more than one workflow but will also have a need for custom packages/scripts. Instead of duplicating large chunks of data in your Workflow Config, you are able to create "sub-workflows" that you might wish to include in multiple workflows. Nested includes are supported (an included_workflow that calls a workflow containing additional included_workflow keys). WARNING: There is no validation or sanity-checking performed by Imagr for infinite loops in nested includes; use carefully.

<dict>
  <key>type</key>
  <string>included_workflow</string>
  <key>name</key>
  <string>Some Workflow Name Here</string>
</dict>
Scripted included workflows

As of Imagr 1.0.0, you can determine the included workflow by using the output of a script. Imagr will run the script and will only select an included workflow if:

  • The script exits with a 0 exit code
  • The script's stdout matches the name of a workflow prepended with ImagrIncludedWorkflow: (including the space between the : and the name of the workflow)
<dict>
    <key>type</key>
    <string>included_workflow</string>
    <key>script</key>
    <string>#!/usr/bin/python
model = "{{machine_model}}"
if model.startswith("VMware"):
    print 'ImagrIncludedWorkflow: vmware_tools'
else:
    print 'ImagrIncludedWorkflow: no_vmware_tools'</string>
    </dict>
</dict>

If you would like to fail out when an included workflow cannot be run, you can exit out and print to stderr.

<dict>
    <key>type</key>
    <string>included_workflow</string>
    <key>script</key>
    <string>#!/usr/bin/python
model = "{{machine_model}}"
if model.startswith("VMware"):
    print 'ImagrIncludedWorkflow: vmware_tools'
else:
    print >> sys.stderr, '\n\nNot a virtual machine.'
    exit(1)</string>
    </dict>
</dict>

Packages

Packages included in the workflow are installed at first boot by default. Set the first_boot key to false to install packages during the Imagr runtime. You can specify flat packages or bundle style packages that are in a disk image. Just make sure they are Suitable for Deployment.

<dict>
    <key>type</key>
    <string>package</string>
    <key>url</key>
    <string>http://192.168.178.135/MunkiTools.pkg</string>
    <key>first_boot</key>
    <false/>
</dict>

Extra HTTP headers can be specified for flat packages (added in 0.0.5):

<dict>
    <key>type</key>
    <string>package</string>
    <key>url</key>
    <string>http://192.168.178.135/MunkiTools.pkg</string>
    <key>additional_headers</key>
    <array>
        <string>Authorization: Basic YWRtaW46c2VjcmV0</string>
        <string>X-enrollment-build: production</string>
        <string>X-enrollment-site: london</string>
        <string>X-enrollment-salgroup: 36</string>
    </array>
</dict>

Computer Name

You can choose to set the computer name of the machine you restore with Imagr. (This means all three names, Bonjour, Apple Remote Desktop, and internal hostname.) Using the below component will result in a text field being displayed in which your desired name can be manually entered during the workflow Imagr runs. If no other modifiers are used, the existing HostName of the mounted volume (which would mean the netboot set you're booted from) will be the default value used (or blank if none exists).

<dict>
    <key>type</key>
    <string>computer_name</string>
</dict>

Adding the use_serial key will use the Mac's serial number as a default for the name:

<dict>
    <key>type</key>
    <string>computer_name</string>
    <key>use_serial</key>
    <true/>
</dict>

Adding the auto key will use the default name (either existing or serial) without allowing it to be overridden during the workflow:

<dict>
    <key>type</key>
    <string>computer_name</string>
    <key>use_serial</key>
    <true/>
    <key>auto</key>
    <true/>
</dict>

Localization

Imagr supports setting the following items (as of 1.0.3):

  • Keyboard Layout Name
  • Keyboard Layout ID
  • Language
  • Locale (currency, date format etc)
  • Timezone

To generate possible values for these, you can use the included get_locale tool, consult the SACountry.plist on your Mac to verify what is the correct code for the desired localization.

$ ./get_locale gb

All values are optional, if you leave any out, they will be left untouched.

Example configuration:

<dict>
    <key>type</key>
    <string>localize</string>
    <key>keyboard_layout_name</key>
    <string>British</string>
    <key>keyboard_layout_id</key>
    <integer>2</integer>
    <key>language</key>
    <string>en</string>
    <key>locale</key>
    <string>en_GB</string>
    <key>timezone</key>
    <string>Europe/London</string>
</dict>

Important: You cannot have non-escaped spaces in the keyboard_layout_name. Here's an example of how to get such a layout to work with Imagr:

<dict>
    <key>type</key>
    <string>localize</string>
    <key>keyboard_layout_name</key>
    <string>Candadian\ -\ CSA</string>
    <key>keyboard_layout_id</key>
    <integer>80</integer>
    <key>language</key>
    <string>fr_CA</string>
    <key>locale</key>
    <string>fr_CA</string>
    <key>timezone</key>
    <string>America/Montreal</string>
</dict>

Scripts

Scripts can be utilized with Imagr two ways:

Method 1: Embed Script
<dict>
    <key>type</key>
    <string>script</string>
    <key>content</key>
    <string>#!/bin/bash
/usr/bin/touch "{{target_volume}}/some_file"</string>
    <key>first_boot</key>
    <false/>
</dict>

Any non-xml safe characters will need to be encoded. The following variables are available for usage in scripts:

  • {{target_volume}} - used to refer to the target volume
  • {{serial_number}} - access to the machine's serial number
  • {{machine_model}} - access to the machine's model
Method 2: Script URL
<dict>
    <key>type</key>
    <string>script</string>
    <key>url</key>
    <string>http://192.168.178.135/some_script.sh</string>
</dict>

Note both methods support the first_boot key which allows scripts to be executed at first boot (the default -- <true/>) or during a Imagr workflow run. Changing the first_boot key to false will run scripts during the Imagr runtime. See above for examples.

When using a URL, you can pass additional HTTP headers (added in 0.0.5):

<dict>
    <key>type</key>
    <string>script</string>
    <key>url</key>
    <string>http://192.168.178.135/get_script</string>
    <key>additional_headers</key>
    <array>
        <string>Authorization: Basic YWRtaW46c2VjcmV0</string>
        <string>X-enrollment-build: production</string>
        <string>X-enrollment-site: london</string>
        <string>X-enrollment-salgroup: 36</string>
    </array>
</dict>

Scripts can output progress information by writing to stdout. First boot scripts will output to the first boot log window, and you can add color to the output by prepending lines with %{ color=red } (see NSColor() for a list of available colors). Scripts that run during a workflow display their last line of output below the progress bar.

Erase Volume

The target volume can be erased beforehand. You can optionally assign a new name (default -- Macintosh HD) and format the target volume (default -- Journaled HFS+):

<dict>
    <key>type</key>
    <string>eraseVolume</string>
    <key>name</key>
    <string>My Volume Name</string>
    <key>format</key>
    <string>Journaled HFS+</string>
</dict>

To see a complete list of supported file systems, run diskutil listFilesystems in Terminal on a Mac running the same build as the nbi is built on. It is recommended to use HFS+ on Macs running 10.12 and below. APFS is not supported on 10.11 and below and is not recommended on 10.12 as a boot volume.

Coming in 1.4.2: Setting the eraseVolume format to auto_hfs_or_apfs will detect the format of the selected volume (HFS+ or APFS) and erase it using the same format. Allowing for a single eraseVolume for mixed deployments, i.e. on SSD, HDD, and Fusion Drive. For use with startosinstall.

The default if no format is specified is still JHFS+

Note that this is not necessary to do before Image tasks. The Image component will erase the drive as part of the restore process.

Partition

The target parent disk of the target volume can be repartitioned with a new set of volumes. A partition map choice must be specified (GPTFormat, APMFormat, or MBRFormat). The partitions are specified as a list of format, name, and size triplets. Additionally, one and only one partition must be chosen as a target, which will be used as the target volume for future tasks in the workflow:

<dict>
    <key>type</key>
    <string>partition</string>
    <key>map</key>
    <string>GPTFormat</string>
    <key>partitions</key>
    <array>
        <dict>
            <key>format_type</key>
            <string>Journaled HFS+</string>
            <key>name</key>
            <string>First</string>
            <key>size</key>
            <string>50%</string>
            <key>target</key>
            <true/>
        </dict>
        <dict>
            <key>format_type</key>
            <string>Journaled HFS+</string>
            <key>name</key>
            <string>Second</string>
            <key>size</key>
            <string>50%</string>
        </dict>
    </array>
</dict>

Sample imagr_config.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>password</key>
  <string>b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86</string>
  <key>workflows</key>
  <array>
    <dict>
      <key>name</key>
      <string>Munki_10103</string>
      <key>description</key>
      <string>Deploys a 10.10.3 image with Munki Tools and its configuration.</string>
      <key>components</key>
      <array>
        <dict>
          <key>type</key>
          <string>image</string>
          <key>url</key>
          <string>http://192.168.178.135/osx_custom_150410-10.10.3-14D131.hfs.dmg</string>
        </dict>
        <dict>
            <key>type</key>
            <string>package</string>
            <key>url</key>
            <string>http://192.168.178.135/MunkiTools.pkg</string>
        </dict>
        <dict>
            <key>type</key>
            <string>package</string>
            <key>url</key>
            <string>http://192.168.178.135/Munki_Config.pkg</string>
        </dict>
        <dict>
            <key>type</key>
            <string>package</string>
            <key>url</key>
            <string>http://192.168.178.135/clearReg.pkg</string>
        </dict>
        <dict>
          <key>type</key>
          <string>script</string>
          <key>content</key>
          <string>#!/bin/bash
echo "&lt;"
echo "{{target_volume}}"
/usr/bin/touch "{{target_volume}}/some_file"</string>
        </dict>
      </array>
    </dict>
    <dict>
      <key>name</key>
      <string>Install OS X</string>
      <key>description</key>
      <string>COSXIP example workflow to installs OS X on the target volume.</string>
      <key>components</key>
      <array>
        <dict>
          <key>type</key>
          <string>package</string>
          <key>url</key>
          <string>http://192.168.178.135/COSXIP-10.11.3.dmg</string>
          <key>bless_target</key>
          <false/>
          <key>first_boot</key>
          <false/>
        </dict>
      </array>
      <key>restart_action</key>
      <string>restart</string>
    </dict>
  </array>
</dict>
</plist>
You can’t perform that action at this time.