Tiny Deathstars of Foulness

We covered using Time Machine Server previously. Here, we’re going to look at backing up the settings of an OS X Server. To do so, we’re going to install a little app called Bender from the great folks at Robot Cloud. You can download that from

Screen Shot 2015-09-24 at 10.51.00 PM

Once downloaded, run the package installer.

Screen Shot 2015-09-24 at 10.49.32 PM

At the Welcome to Bender screen, click Continue.

Screen Shot 2015-09-24 at 10.52.03 PM

Agree to the licensing agreement by clicking the Continue button.

Screen Shot 2015-09-24 at 10.52.22 PM

Click Agree again (assuming of course that you agree to the license).

Screen Shot 2015-09-24 at 10.52.57 PM

Choose who you wish to install the software for and click Continue.

Screen Shot 2015-09-24 at 10.53.52 PM

I’d go ahead and install Bender at the default location, so click Install. Once the installer is complete, you can view the installed LaunchDaemon at /Library/LaunchDaemons/net.robotcloud.bender.plist. Note that it calls the /usr/local/robotcloud/bin/bender binary when run at 22:00 every day. If you edit this file, the following settings are available:

macOS=$(sw_vers | awk ‘/ProductVersion/{print substr($2,1,5)}’ | tr -d “.”)
macSN=$(system_profiler SPHardwareDataType | awk ‘/Serial Number/{print $4}’)
date=$(date +%Y-%m-%d-%H%M)
pass=$(system_profiler SPHardwareDataType | awk ‘/Hardware UUID/{print $3}’)
pipTitle=”Bender Backup Error on: $macSN”

The most important of these is the backupDestination. You can set this to be the /Backups folder as it is above, or set it to be an external drive. Either should be backed up using your standard backup software.

October 8th, 2015

Posted In: Mac OS X, Mac OS X Server, Mac Security

Tags: , , , , , ,

One Comment

The NetBoot service allows administrators of OS X computers to leverage images hosted on a server to boot computers to a central location and put a new image on them, upgrade them and perform automations based on upgrades and images. Since the very first versions of OS X, the service has been called NetBoot. In the Server app, Apple provides a number of options surrounding the NetInstall service, based on Automator-style actions, now calling the service NetInstall.

The first step to configuring the NetInstall service is to decide what you want the service to do. There are three options available in System Image Utility (available under the Tools menu of the Server app in OS X Server):

  • Create a NetBoot Image: Allows Macs to boot over the network to a disk image hosted on a server.
  • Create a NetInstall Image: Leverage NetBoot as a boot disk so that an image hosted on a server can be used to run an OS X installer.
  • Create a NetRestore Image: Leverage NetBoot as a boot disk so that you can restore a computer that has been configured over a network. Use this option to restore an image that has been prepared.

For the purposes of this example, we’re going to use an OS X El Capitan (10.11) installer running Server 5 to boot an OS X computer over the network. The first step in doing so is to create a Network Disk Image of 10.9, or the 10.9 installation media (which is the Install OS X Mavericks bundle for this example). Before setting it up, download the Install OS X El Capitan installer app into the /Applications directory from the App Store.

Create An Image

To then set up the NetBoot disk image (you can’t start the NetInstall service until you give it an image to serve), often referred to as the NetBoot set, open the Server app and then click on System Image Utility from the Tools menu of OS X.

Screen Shot 2015-09-26 at 8.25.36 PM
When System Image Utility opens, click on the Install OS X El Capitan entry in the list of available sources and click Next.

Screen Shot 2015-09-26 at 8.26.52 PM

Then, in the list of options, click on NetBoot Image and then click on the Next button.

Screen Shot 2015-09-26 at 8.27.40 PM

At the License Agreement screen, click Agree.

Screen Shot 2015-09-26 at 8.28.52 PM

Then provide an account name, short name and password in the Image Settings screen. Also choose the language of the user and select if you want the account to log in automatically. Once provided, click Next.

Screen Shot 2015-09-26 at 8.30.28 PM
Next, select any profiles, packages or post-install scripts to run on the NetBoot image once created. Here, you can use a profile to deploy a printer, bind to Active Directory, or use a package to install software. Post-install scripts allow you to do pretty much anything you’d like to a system, provided it’s allowed by SIP.

Screen Shot 2015-09-26 at 8.31.54 PM

At the System Configuration screen, choose how you’d like systems to receive names. Here, you can provide a name as a base for computers to get a computer name or you can use a file to deploy names. In most cases, you should also check the box for “Match to client after install.” Click Next once you’ve selected how this should occur.

Screen Shot 2015-09-26 at 8.33.21 PM

At the Directory Servers screen, click on the plus sign if you’d like to bind the system to a particular directory server.

Screen Shot 2015-09-26 at 8.33.33 PM

In this example, we’re binding to Also provide an account with access to bind to where you’re binding. In this case, we’re using the built-in admin account for Active Directory. Click Add once you’ve provided the appropriate directory server and credentials.

Screen Shot 2015-09-26 at 8.35.01 PM

At the Image Settings screen, provide a name for the image, as well as how the index number for the image is created. Note that each image should have a unique image index, so unless you’re storing your image on multiple servers, it’s best left at the defaults. Click Next.

Screen Shot 2015-09-26 at 8.36.53 PM

At the Supported Computer Models screen, you can choose which models of computer you don’t wish to support for this image. We’re not doing that here, but it’s useful, for example, if you’d like to preclude desktops from an image.

Screen Shot 2015-09-26 at 8.37.57 PM

At the Filter Clients By MAC Address, you can choose to explicitly allow or deny given MAC addresses for computers. We’re not going to do that as part of this workflow, so just click Next (unless of course you’d like to do that).

Screen Shot 2015-09-26 at 8.38.13 PM
Then, when prompted, select a location to store the Disk Image, provide any tags to be applied to the files that comprise the image and click on Save.

Screen Shot 2015-09-26 at 8.38.58 PM
The computer will then start creating the NetBoot set.


Setup The NetInstall Service

Once finished, it’s time to set up the NetInstall service in OS X Server. To get started, go back to the Server app.

Screen Shot 2015-09-26 at 8.39.33 PM
First, define which disk will host NetBoot Images. To do so, click on the Edit Storage Settings button. At the Storage Settings overlay, select the volume that Images will be hosted as well as the volume that Client Data will be hosted. The Image is what you are creating and the Client Data is dynamic data stored in images.

Screen Shot 2015-09-26 at 8.40.08 PM
If you only have one disk, as in this example, click on “Images & Client Data” for that disk. Then click on the OK button. Once you’ve selected a disk to store your image, we need to copy the disk image into the Library/NetBoot/NetBootSP0 folder of the disk used for images.

Screen Shot 2015-09-26 at 8.41.51 PM

Once in the appropriate folder, click on the Edit button for Network Interfaces and select the appropriate network interface you wish to serve images over, and click OK. Refresh the Server app (Command-R) and provided the image was created and moved into the /Library/NetBoot/NetBootSP0 directory of a volume set to host images, the image will appear in the images list, with a green indicator light.

Screen Shot 2015-09-26 at 9.04.37 PM

The green indicator light means the image is being served over the network. Double-click on an image.

Screen Shot 2015-09-26 at 9.04.41 PM
At the image settings screen, you can select NFS over the default HTTP protocol for “Make available over”.Note, you can also restrict access to the image to certain models of Apple computers and/or certain MAC addresses by using the “Image is visible to” and “Restrict access to this images” options respectively. Additionally, use the Make this image available for diskless booting option to allow computers without hard drives to boot to the image.

Screen Shot 2015-09-26 at 9.06.35 PM

Click on the OK button. Click on the image and then click on the cog-wheel icon. Click on “Use as Default Boot Image” to set an image to be the default images computers boot to when booting to NetBoot. Now, it’s as easy as clicking on the ON button. Do so to start the service.

Screen Shot 2015-09-26 at 9.07.10 PM
Once started, open a Terminal window. Here, let’s get a status of the service using the serveradmin fullstatus option (along with the service name, which is still netboot from the command line):

sudo serveradmin fullstatus netboot

The output of which shows the various components, logs and states of components:

netboot:state = "RUNNING"
netboot:stateTFTP = "RUNNING"
netboot:readWriteSettingsVersion = 1
netboot:netBootConnectionsArray = _empty_array
netboot:logPaths:netBootLog = "/var/log/system.log"
netboot:dhcpLeasesArray = _empty_array
netboot:stateDHCP = "STOPPED"
netboot:stateHTTP = "RUNNING"
netboot:serviceCanStart = 1
netboot:timeOfSnapshot = "2015-09-27 02:07:32 +0000"
netboot:stateNFS = "STOPPED"
netboot:stateImageArray:_array_index:0:_array_index:0 = 1
netboot:stateImageArray:_array_index:0:_array_index:1 = 0
netboot:stateImageArray:_array_index:0:_array_index:2 = 0
netboot:stateImageArray:_array_index:0:_array_index:3 = 1
netboot:stateImageArray:_array_index:0:_array_index:4 = 2
netboot:stateImageArray:_array_index:1:_array_index:0 = 0
netboot:stateImageArray:_array_index:1:_array_index:1 = 0
netboot:stateImageArray:_array_index:1:_array_index:2 = 0
netboot:stateImageArray:_array_index:1:_array_index:3 = 0
netboot:stateImageArray:_array_index:1:_array_index:4 = 2
netboot:stateImageArray:_array_index:2:_array_index:0 = 0
netboot:stateImageArray:_array_index:2:_array_index:1 = 0
netboot:stateImageArray:_array_index:2:_array_index:2 = 0
netboot:stateImageArray:_array_index:2:_array_index:3 = 0
netboot:stateImageArray:_array_index:2:_array_index:4 = 2
netboot:stateImageArray:_array_index:3:_array_index:0 = 0
netboot:stateImageArray:_array_index:3:_array_index:1 = 0
netboot:stateImageArray:_array_index:3:_array_index:2 = 0
netboot:stateImageArray:_array_index:3:_array_index:3 = 0
netboot:stateImageArray:_array_index:3:_array_index:4 = 2
netboot:servicePortsRestrictionInfo = _empty_array
netboot:netBootClientsArray = _empty_array
netboot:servicePortsAreRestricted = "NO"
netboot:setStateVersion = 1
netboot:startedTime = "2015-09-27 02:06:53 +0000"
netboot:stateAFP = "STOPPED"

And to start the service when not running:

sudo serveradmin start netboot

There are also a number of settings available at the command line that are not in the graphical interface. For example, to allow writing to the NetBoot share:

sudo serveradmin settings netboot:netBootStorageRecordsArray:_array_index:0:readOnlyShare = no

Or to get more verbose logs:

sudo serveradmin settings netboot:logging_level = "HIGH"

To stop the service:

sudo serveradmin stop netboot

In the beginning of this article, I mentioned that ways to configure NetInstall images. I’ll cover NetInstall and NetRestore in later articles as they tend to be more involved workflow-wise than copying a volume into a Network Disk Image. But to end this one, many an old-school admin might wonder where all the settings went that used to be in the GUI. Well, serveradmin still maintains a lot of the older stuff. To see a list of all available settings, run serveradmin with the settings verb and then netboot:

sudo serveradmin settings netboot

If there was a feature you want to use (e.g. maximum users), you should see it in the resultant list:

netboot:netBootFiltersRecordsArray = _empty_array
netboot:netBootStorageRecordsArray:_array_index:0:sharepoint = yes
netboot:netBootStorageRecordsArray:_array_index:0:clients = yes
netboot:netBootStorageRecordsArray:_array_index:0:volType = "hfs"
netboot:netBootStorageRecordsArray:_array_index:0:okToDeleteSharepoint = no
netboot:netBootStorageRecordsArray:_array_index:0:readOnlyShare = no
netboot:netBootStorageRecordsArray:_array_index:0:path = "/"
netboot:netBootStorageRecordsArray:_array_index:0:okToDeleteClients = yes
netboot:netBootStorageRecordsArray:_array_index:0:volName = "Macintosh HD"
netboot:netBootPortsRecordsArray:_array_index:0:deviceAtIndex = "en5"
netboot:netBootPortsRecordsArray:_array_index:0:nameAtIndex = "USB 10/100/1000 LAN"
netboot:netBootPortsRecordsArray:_array_index:0:isEnabledAtIndex = yes
netboot:logging_level = "MEDIUM"
netboot:filterEnabled = no
netboot:netBootImagesRecordsArray:_array_index:0:RootPath = "NetBoot.dmg"
netboot:netBootImagesRecordsArray:_array_index:0:IsInstall = no
netboot:netBootImagesRecordsArray:_array_index:0:Kind = "1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:0 = "MacBookAir6,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:1 = "MacBookAir5,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:2 = "MacBookAir7,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:3 = "MacBookAir2,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:4 = "MacBookAir5,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:5 = "MacBookAir4,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:6 = "MacBookAir4,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:7 = "MacBookAir6,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:8 = "MacBookAir7,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:9 = "MacBookAir3,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:10 = "MacBookAir3,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:11 = "MacBookPro5,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:12 = "MacBookPro9,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:13 = "MacBookPro6,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:14 = "MacBookPro6,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:15 = "MacBookPro8,3"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:16 = "MacBookPro11,3"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:17 = "MacBookPro7,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:18 = "MacBookPro11,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:19 = "MacBookPro10,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:20 = "MacBookPro12,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:21 = "MacBookPro11,4"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:22 = "MacBookPro11,5"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:23 = "MacBookPro3,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:24 = "MacBookPro4,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:25 = "MacBookPro8,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:26 = "MacBookPro10,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:27 = "MacBookPro5,3"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:28 = "MacBookPro5,5"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:29 = "MacBookPro5,4"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:30 = "MacBookPro5,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:31 = "MacBookPro9,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:32 = "MacBookPro11,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:33 = "MacBookPro8,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:34 = "iMac14,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:35 = "iMac9,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:36 = "iMac7,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:37 = "iMac12,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:38 = "iMac11,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:39 = "iMac14,4"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:40 = "iMac11,3"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:41 = "iMac13,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:42 = "iMac15,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:43 = "iMac12,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:44 = "iMac8,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:45 = "iMac10,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:46 = "iMac13,3"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:47 = "iMac14,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:48 = "iMac14,3"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:49 = "iMac13,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:50 = "iMac11,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:51 = "Macmini5,3"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:52 = "Macmini5,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:53 = "Macmini4,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:54 = "Macmini5,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:55 = "Macmini3,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:56 = "Macmini6,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:57 = "Macmini6,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:58 = "Macmini7,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:59 = "MacBook8,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:60 = "MacBook7,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:61 = "MacBook5,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:62 = "MacBook6,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:63 = "MacBook5,2"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:64 = "MacPro3,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:65 = "MacPro5,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:66 = "MacPro4,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:67 = "MacPro6,1"
netboot:netBootImagesRecordsArray:_array_index:0:DisabledSystemIdentifiers:_array_index:68 = "Xserve3,1"
netboot:netBootImagesRecordsArray:_array_index:0:Description = "NetBoot of OS X 10.11 (15A178w) Install (9.12 GB)."
netboot:netBootImagesRecordsArray:_array_index:0:Name = "NetBoot of Install OS X 10.11 El Capitan"
netboot:netBootImagesRecordsArray:_array_index:0:imageType = "netboot"
netboot:netBootImagesRecordsArray:_array_index:0:Index = 3089
netboot:netBootImagesRecordsArray:_array_index:0:osVersion = "10.11"
netboot:netBootImagesRecordsArray:_array_index:0:BackwardCompatible = no
netboot:netBootImagesRecordsArray:_array_index:0:SupportsDiskless = no
netboot:netBootImagesRecordsArray:_array_index:0:EnabledSystemIdentifiers = _empty_array
netboot:netBootImagesRecordsArray:_array_index:0:Language = "Default"
netboot:netBootImagesRecordsArray:_array_index:0:BootFile = "booter"
netboot:netBootImagesRecordsArray:_array_index:0:IsDefault = no
netboot:netBootImagesRecordsArray:_array_index:0:Type = "HTTP"
netboot:netBootImagesRecordsArray:_array_index:0:Architectures = "4"
netboot:netBootImagesRecordsArray:_array_index:0:IsEnabled = yes
netboot:netBootImagesRecordsArray:_array_index:0:pathToImage = "/Library/NetBoot/NetBootSP0/NetBoot of Install OS X 10.11 El Capitan.nbi/NBImageInfo.plist"
netboot:afpUsersMax = "50"

Boot to Your NetBoot Image

Next, you’ll want to have a computer boot to the NetBoot image you just created. Once upon a time, you would use the bless command to select a path to an image that you wanted to boot to in order to do so. Or you’d just boot holding down the N key and let the system pick an image. As of OS X 10.11, due to SIP restrictions, you’ll use the csrutil command to set a NetBoot address. To do so, run csrutil followed by the netboot option and then the add verb, followed by an address. In the following example, we’ll set the system to boot to the NetBoot server at

csrutil netboot add

Once you’ve finished any NetBoot workflows, use the remove verb to remove that address:

csrutil netboot remove

And to list any available NetBoot servers, use the list verb:

csrutil netboot list

Overall, all of this usually takes me a good 10 minutes of work, plus maybe up to half an hour of waiting for an image to create. You can use NetBoot to remotely boot systems, or NetInstall to remotely install systems. There are lots of articles out there (including here) on how to make sure clients can access these images over a network client, so I won’t rehash

October 7th, 2015

Posted In: Mac OS X, Mac OS X Server, Mac Security

Tags: , , , , , ,

Leave a Comment

You might be happy to note that other than the ability to interpret new payloads, the profiles command mostly stays the same in El Capitan, from Yosemite. You can still export profiles from Apple Configurator or Profile Manager (or some of the 3rd party MDM tools). You can then install profiles by just opening them and installing. Once profiles are installed on a Mac, mdmclient, a binary located in /usr/libexec will process changes such as wiping a system that has been FileVaulted (note you need to FileVault if you want to wipe an OS X Lion client computer). /System/Library/LaunchDaemons and /System/Library/LaunchAgents has a mdmclient daemon and agent respectively that start it up automatically. This, along with all of the operators remains static from 10.10.

To script profile deployment, administrators can add and remove configuration profiles using the new /usr/bin/profiles command. To see all profiles, aggregated, use the profiles command with just the -P option:

/usr/bin/profiles -P

As with managed preferences (and piggy backing on managed preferences for that matter), configuration profiles can be assigned to users or computers. To see just user profiles, use the -L option:

/usr/bin/profiles -L

You can remove all profiles using -D:

/usr/bin/profiles -D

The -I option installs profiles and the -R removes profiles. Use -p to indicate the profile is from a server or -F to indicate it’s source is a file. To remove a profile:

/usr/bin/profiles -R -F /tmp/HawkeyesTrickshot.mobileconfig

To remove one from a server:

/usr/bin/profiles -R -p com.WestCoastAvengers.HawkeyesTrickshot

The following installs HawkeyesTrickshot.mobileconfig from /tmp:

/usr/bin/profiles -I -F /tmp/HawkeyesTrickshot.mobileconfig

If created in Profile Manager:

/usr/bin/profiles -I -p com.WestCoastAvengers.HawkeyesTrickshot

You can configure profiles to install at the next boot, rather than immediately. Use the -s to define a startup profile and take note that if it fails, the profile will attempt to install at each subsequent reboot until installed. To use the command, simply add a -s then the -F for the profile and the -f to automatically confirm, as follows (and I like to throw in a -v usually for good measure):

profiles -s -F /Profiles/SuperAwesome.mobileconfig -f -v

And that’s it. Nice and easy and you now have profiles that only activate when a computer is started up. As of OS X Yosemite, the dscl command got extensions for dealing with profiles as well. These include the available MCX Profile Extensions:

-profileimport -profiledelete -profilelist [optArgs]

To list all profiles from an Open Directory object, use 
-profilelist. To run, follow the dscl command with -u to specify a user, -P to specify the password for the user, then the IP address of the OD server (or name of the AD object), then the profilelist verb, then the relative path. Assuming a username of diradmin for the directory, a password of moonknight and then cedge user:

dscl -u diradmin -P moonknight profilelist /LDAPv3/

To delete that information for the given user, swap the profilelist extension with profiledelete:

dscl -u diradmin -P apple profilelist /LDAPv3/

If you would rather export all information to a directory called ProfileExports on the root of the drive:

dscl -u diradmin -P moonknight profileexport . all -o /ProfileExports

In Yosemite we got a few new options (these are all still in 10.11 with no new operators), such as -H which shows whether a profile was installed, -z to define a removal password and -o to output a file path for removal information. Also, as in Yosemite it seems as though if a configuration profile was pushed to you from MDM, you can’t remove it (fyi, I love having the word fail as a standalone in verbose output):

bash-3.2# profiles -P
_computerlevel[1] attribute: profileIdentifier: 772BED54-5EDF-4987-94B9-654456CF0B9A
_computerlevel[2] attribute: profileIdentifier: 00000000-0000-0000-A000-4A414D460003
_computerlevel[3] attribute: profileIdentifier: C11672D9-9AE2-4F09-B789-70D5678CB397
charlesedge[4] attribute: profileIdentifier: com.krypted.office365.a5f0e328-ea86-11e3-a26c-6476bab5f328
charlesedge[5] attribute: profileIdentifier:
_computerlevel[6] attribute: profileIdentifier: EE08ABE9-5CB8-48E3-8E02-E46AD0A03783
_computerlevel[7] attribute: profileIdentifier: F3C87B6E-185C-4F28-9BA7-6E02EACA37B1
_computerlevel[8] attribute: profileIdentifier: 24DA416D-093A-4E2E-9E6A-FEAD74B8B0F0
There are 8 configuration profiles installed

bash-3.2# profiles -r 772BED54-5EDF-4987-94B9-654456CF0B9A
bash-3.2# profiles -P
_computerlevel[1] attribute: profileIdentifier: F3C87B6E-185C-4F28-9BA7-6E02EACA37B1
_computerlevel[2] attribute: profileIdentifier: EE08ABE9-5CB8-48E3-8E02-E46AD0A03783
_computerlevel[3] attribute: profileIdentifier: 24DA416D-093A-4E2E-9E6A-FEAD74B8B0F0
_computerlevel[4] attribute: profileIdentifier: 00000000-0000-0000-A000-4A414D460003
_computerlevel[5] attribute: profileIdentifier: 772BED54-5EDF-4987-94B9-654456CF0B9A
_computerlevel[6] attribute: profileIdentifier: C11672D9-9AE2-4F09-B789-70D5678CB397
charlesedge[7] attribute: profileIdentifier:
charlesedge[8] attribute: profileIdentifier: com.krypted.office365.a5f0e328-ea86-11e3-a26c-6476bab5f328
There are 8 configuration profiles installed

bash-3.2# profiles -rv 772BED54-5EDF-4987-94B9-654456CF0B9A
profiles: verbose mode ON
profiles: returned error: -204

October 6th, 2015

Posted In: Mac OS X, Mac OS X Server, Mac Security, Mass Deployment

Tags: , , , , , , ,

Leave a Comment

By default, screenshots are pretty big on a retina display on an El Capitan machine. Like about 4 times the size they should be. I haven’t found a defaults key I can use yet to reduce them, so I’ve been using this little screenshotting app called RetinaCapture, available at

Basically, when you’re running it, you just open it up and click on the Window button. There, you can select a window to screenshot.

Screen Shot 2015-09-24 at 8.37.33 AM

Once you’ve selected the window, you’ll be prompted to save it somewhere with a name.

Screen Shot 2015-09-24 at 8.38.00 AM


I don’t love having to use any 3rd party apps for my screenshotting workflow. Screens get resized for books and so I’m really only using this for my site. But, hopefully it helps someone else along the way. Happy screenshotting!

October 6th, 2015

Posted In: Mac OS X

Tags: , , , , , ,


In case your Mac just isn’t emo enough for ya’, Apple’s provided us a cool little new feature in Yosemite called dark mode. No, this won’t cause Hellboy to leap forth from your MacBook Air. Well, maybe he’ll visit your MacBook Pro, but I haven’t tested that so please don’t quote me on that. Instead, you’ll get the nice new dark menu bar:

Screen Shot 2015-09-10 at 10.41.10 PM

But that’s not all folks! Your dock will also get all dark and gothy!

Screen Shot 2015-09-10 at 10.41.29 PM

To turn it on, just open the General System Preference pane and check the box for “Use dark menu bar and Dock”.

Screen Shot 2015-09-10 at 10.42.23 PM

Enjoy! Oh, and if that’s not emo enough for you feel free to watch this sad emo love song video (yes, I googled for “sad emo” to find it; no, it’s not bookmarked; yes, I bought eyeliner after watching it; yes, then my high school self time travelled to present day and kicked the crap out of me; yes, I thanked him).

October 5th, 2015

Posted In: Mac OS X

Tags: , , , , , ,

Leave a Comment

I wrote about using the smbutil for DFS in Lion awhile back. I haven’t needed to write anything else as it hadn’t changed since. The statshares option has an -m option to look at a mount path for showing the path to the mount (e.g. if the mount is called krypted this should be something like /Volumes/krypted):

smbutil statshares -m /Volumes/krypted

When run, you see a list of all the attributes OS X tracks for that mount path, including the name of the server, the user ID (octal), how SMB negotiated an authentication, what version of SMB is running (e.g. SMB_1), the type of share and whether signing, extended security, Unix and large files are supported.

Additionally, if you’d like to see the attributes for all shares, use the -a option after statshares:

smbutil statshares -a

Overall, this is a nice health check type of verb to the smbutil command that can be added to any monitoring or troubleshooting workflow.

October 4th, 2015

Posted In: Mac OS X, Mac OS X Server

Tags: , , ,

Leave a Comment

A nifty little feature of nvram is the ability to delete all of the firmware variables you’ve created. This can get helpful if you’ve got a bunch of things that you’ve done to a system and want to remove them all. If you run nvkram followed by a -p option you’ll see all of the configured firmware variables:

nvram -p

If you run it with a -d you’ll delete the given variables that you define (e.g. boot-args):

nvram -d boot-args

But, if you run the -c you’ll wipe them all:

nvram -c

October 4th, 2015

Posted In: Mac OS X

Tags: , ,


By default, OS X now updates apps that are distributed through the Mac App Store (MAS). OS X Server is really just the Server app, sitting on the App Store. If the Server app is upgraded automatically, you will potentially experience some adverse side effects, especially if the app is running on a Metadata Controller for Xsan, runs Open Directory, or a major release of the Server app ships. Therefore, in this article we’re going to disable this otherwise sweet feature of OS X.

To get started, first open the System Preferences. From there, click on the App Store System Preference pane.

Screen Shot 2015-09-24 at 8.25.39 AM

From the App Store System Preference pane, uncheck the following boxes:

  • Automatically Check For Updates: Unchecking this box disables the download in the background option and the installation of app updates.
  • Automatically Download Apps Purchased on Other Macs: If you buy an upgrade, you could accidentally install that upgrade on production servers you don’t intend to install the upgrade on.

Once disabled, you’ll need to keep on top of updates in the App Store manually. My recommendation is still to create an image of your server before each update.


October 2nd, 2015

Posted In: Mac OS X, Mac OS X Server, Mac Security

Tags: , , , ,

Leave a Comment

In order to use the Apple Volume Purchase Program, you will need an MDM solution (Profile Manager, Casper, MobileIron, Meraki, FileWave, etc). Also, token options were traditionally for one to one (1:1) environments until iOS 9, which marked a change where you can now leverage per-device licensing. This removes the requirement that you need an Apple ID running on each device that you choose to install apps on. Suddenly, VPP is for multi-tenant environments. You can also use codes and options for iOS 7 and up as well as OS X 10.9 and up, but those will use Apple IDs. Also, if you install your vpptoken on OS X Server and you’re running that same vpptoken elsewhere, OS X Server will take all of the codes that have been issued for itself (feature or bug, you decide).

But this article isn’t about the fine print details of the new VPP. Instead, this article is about making Profile Manager work with your new VPP token. Before you get started, know that when you install your vpptoken, if it’s in use by another MDM, Profile Manager will unlicensed all apps with your other MDM. To get started, log into your VPP account. Once logged in, click on your account email address and then select Account Summary.


Then, click on the Download Token link and your token will be downloaded to your ~/Downloads (or wherever you download stuff).


Once you have your token, open the Server app and click on the Profile Manager service.


Click on the checkbox for Distribute apps and books from the Volume Purchase Program.


At the VPP Managed Distribution screen, drag the .vpptoken file downloaded earlier into the screen.


Click Continue. The VPP code email address will appear in the screen. Click Done.

Back at the profile manager screen, you should then see that the checkbox is filled and you can now setup Profile Manager.

The rest of the configuration of Profile Manager is covered in a previous article.

Note: The account used to configure the VPP information is not tracked in any serveradmin settings.

September 27th, 2015

Posted In: Mac OS X, Mac OS X Server, Mac Security, Mass Deployment

Tags: , , , , , , ,

Leave a Comment

Let’s start out with what’s actually available in the Server Admin CLI: serveradmin. The serveradmin command, followed by settings, followed by san shows a few pieces of information:

bash-3.2# serveradmin settings san
san:computers = _empty_array
san:primaryController = "95C99FB1-80F2-5016-B9C3-BE3916E6E5DC"
san:ownerEmail = ""
san:sanName = "krypted"
san:desiredSearchPolicy:_array_index:0 = ""
san:serialNumbers = _empty_array
san:dsType = 0
san:ownerName = "Charles Edge"
san:managePrivateNetwork = yes
san:metadataNetwork = ""
san:numberOfFibreChannelPorts = 2
san:role = "CONTROLLER"

Here, we see the metadata network, the GUID of the primary (active) MDC, the name of the SAN, an array of serial numbers (if applicable – in a purely Mountain Lion/Mavericks SAN they aren’t), the owner info plugged in earlier and the metadata network interface being used.
Next, we’ll take a peak at the fsm process for each volume:

bash-3.2# ps aux | grep fsm
root 7030 0.7 0.7 2694708 62468 ?? Ss 10:18AM 0:03.08 /System/Library/Filesystems/acfs.fs/Contents/bin/fsm BettyWhite mdm.pretendco.lan 0
root 6834 0.1 0.0 2478548 2940 ?? S 10:10AM 0:01.37 fsmpm -- -- /var/run/fsmpm-sync.6800 1800

Next, we can look at the version rev, which shows that the Server Revision is the same as in Mavericks, but the build number has incremented by 19 commits:

bash-3.2# cvversions
File System Server:
Server Revision 5 Branch Head
Created on Tue Sep 13 09:59:14 PDT 2015
Built in /SourceCache/XsanFS/XsanFS-527/buildinfo
Host OS Version:
Darwin 14.0.0 Darwin Kernel Version 14.0.0: Sat Sep 24 01:15:10 PDT 2015; root:xnu-2738. x86_64

Next, we’ll check out the contents of /Library/Preferences/Xsan. First the volume configuration file:

bash-3.2# cat BettyWhite.cfg
# Globals
AllocationStrategy Round
FileLocks Yes
BufferCacheSize 32M
Debug 0x0
CaseInsensitive Yes
EnableSpotlight Yes
EnforceACLs Yes
SpotlightSearchLevel ReadWrite
FsBlockSize 16K
GlobalSuperUser Yes
InodeCacheSize 8K
InodeExpandMin 0
InodeExpandInc 0
InodeExpandMax 0
InodeDeleteMax 0
InodeStripeWidth 0
JournalSize 16M
MaxConnections 139
MaxLogSize 10M
MaxLogs 4
NamedStreams Yes
Quotas Yes
QuotaHistoryDays 7
ThreadPoolSize 256
UnixIdFabricationOnWindows Yes
UnixNobodyUidOnWindows -2
UnixNobodyGidOnWindows -2
WindowsSecurity Yes
# Disk Types
[DiskType LUN2Type]
Sectors 488355807
SectorSize 512
# Disks
[Disk LUN2]
Type LUN2Type
Status UP
# Stripe Groups
[StripeGroup All]
Status Up
StripeBreadth 16
Metadata Yes
Journal Yes
Exclusive No
Read Enabled
Write Enabled
Rtmb 0
Rtios 0
RtmbReserve 0
RtiosReserve 0
RtTokenTimeout 0
MultiPathMethod Rotate
Node LUN2 0
Affinity All

The above is not the XML I was thinking we’d see, but the same format and variables previously available. The configuration for the SAN itself is XML though:

bash-3.2# cat config.plist




Charles Edge

The automount file is a plist as well:

bash-3.2# cat automount.plist





The aux-data is also a plist:

bash-3.2# cat BettyWhite-auxdata.plist






Next, cvadmin remains basically unchanged, with the addition of restartd/startd/stopd (managing the fem and the removal of :

Xsanadmin (BettyWhite) > help
Command summary:
activate, debug, dirquotas, disks, down, fail, filelocks, fsmlist, help, latency-test, multipath, paths, proxy, qos, quit, quotas, quotacheck, quotareset, ras, repfl, repquota, repof, resetrpl, rollrj, select, show, start, stat, stop, up, who, ?
activate [ | ]
Activate a File System .
This command may cause an FSM to activate.
If the FSM is already active, no action is taken.
debug [ [+/-] ]
Get or Set (with ) the FSS Debug Flags.
Enter debug with no value to get current setting and bit meanings.
Value should be a valid number. Use 0x to indicate hexadecimal.
If the ‘+’ or ‘-’ argument is used, only specified flags
will be modified.
‘+’ will set and ‘-’ will disable the given flags.
dirquotas <create|mark|destroy>
The ‘create’ command turns the given directory into the root of a
Directory Quota namespace. The command will not return until the
current size value of the directory is tallied up. The ‘mark’
command also turns the given directory into the root of a
Directory Quota namespace, but the current size value is left
uninitialized.  The command ‘quotacheck’ should be run later to
initialize it. The ‘destroy’ command destroys the namespace
associated with the given directory.  The directory’s contents
are left unchanged.
disks [refresh]
Display the acfs Disk volumes visible to this machine.
If the optional “refresh” is used, the volumes will.
be re-scanned by the fsmpm.
disks [refresh] fsm
Display the acfs meta-data Disk volumes in use by the fsm.
If the optional “refresh” is used, additional paths to these
volumes may be added by the fsm.
Bring down stripe group .
fail [ | ]
Failover a File System .
This command may cause a stand by FSM to activate.
If the FSM is already active, the FSM will
shut down. A stand-by FSM will take over or the
FSM will be re-launched if it is stand-alone.
fsmlist [] [on ]
Display the state of FSM processes, running or not.
Optionally specify a single to display.
Optionally specify the host name or IP address of the system
to list the FSM process(es) on.
help (?)  This message.
latency-test [ | all] []
Run an I/O latency test between the FSM process and one
client or all clients.  The default test duration is
2 seconds.
multipath < balance | cycle | rotate | static | sticky >
Change the Multi Path method for stripe group
to “balance”, “cycle”, “rotate”, “static”, or “sticky”.
Display the acfs Disk volumes visible to this machine
grouped according to the “controller” identity.
proxy [ long ]
proxy who
Display Disk Proxy Servers, and optionally the disks
they serve, for this filesystem
The “who” option displays all proxy connections
for the specified host.
qos       Display per-stripe group QOS statistics.
quit      Exit
Query cluster-wide file/record lock enforcement.
Enter filelocks with no value to get current setting.
Currently Cluster flocks are automatically used on Unix.
Windows file/record locks are optional.
Get the current state of the quota system
quotas get <user|group|dir|dirfiles>
Get quota parameters for user, group, or directory .
quotas set <user|group|dir|dirfiles>
Set current quota parameters for user, group, or directory
. can be the name of a user or group or the
path to a directory. For users and groups, it can also be an
integer interpreted as a uid or gid.  Setting the hardlim,
softlim, and timelim to 0 disables quota enforcement for that user,
group, or directory. The values for hardlim and softlim are
expressed in bytes when setting user, group, or dir values.  When
setting dirfiles values, they are numbers of regular file inodes.
The value for timelim is expressed in minutes.
Recalculate the amount of space consumed (the current
size field of the quota record) by all users,
groups, and directory namespaces in the file system. This
command can be run on an active file system although file
updates (writes, truncates, etc.) will be delayed until
quotacheck has completed.
Like quotacheck, but deletes the quota database before
performing the check. All limits and directory namespaces
will be lost. Use with extreme caution.
ras enq “detail string”
Generate an SNFS RAS event.  For internal use only.
ras enq “detail string”
Generate a generic RAS event.  For internal use only.
Generate quota reports for all users, groups, and directory
namespaces in the file system. Three files are generated:
1. quota_report.txt – a “pretty” text file report.
2. quota_report.csv – a comma delimited report
suitable for Excel spreadsheets.
3. – a list of cvadmin commands that
can be used to set up an identical quota database
on another Xsan.
Generate a report of currently held locks
on all connected acfs clients.
Generate a report of currently open files
on all connected acfs clients.
resetrpl [clear]
Repopulate Reverse Path Lookup (RPL) information.
The optional “clear” argument causes existing
RPL data to be cleared before starting repopulation.
Note: “resetrpl” is only available when cvadmin is
invoked with the -x option.  Running resetrpl
may significantly delay FSM activation.  This command
is not intended for general use.  Only run “resetrpl”
when recommended by Technical Support.
restartd [once]
Stop and start the process.
For internal use only.
Force the FSM to start a new restore journal.
This command is only used on a managed file system
select [ | | none]
Select the active File System .
Typing “select none” will de-select the current FSS.
If the FSM is inactive (standing by) it cannot be selected.
Using this command with no argument shows all active FSSs.
show [ ] [ long ]
Show all stripe groups or a specific stripe group .
Adding the modifier “long” shows more verbose information.
start [on] []
Start the File System Service for .
When running on an HA MDC, the local service is started and
then an attempt is made to start the service on the peer MDC.
Optionally specify the hostname or IP address to start the
FSM on that MDC only.
startd [once]
Start the process.
For internal use only.
stat      Display the general status of the file system.
stats [clear]
Display read/write statistics for the file system.
If clear, zero the stats after printing.
stop [on] [] |
Stop the File System Services for
or . Stopping by name without specifying a
hostname will stop all instances of the service, and will
cancel any pending restart of the service on the local system.
Stopping by name on a particular system will stop or cancel
a restart of the service on that system.  Stopping by
number only stops the service associated with the index.
Indexes are displayed on the left side as “nn>” when.
using the “select” command.
Stop the process.
For internal use only.
Bring up stripe group .
If there are no stripe groups that have exclusively numeric names,
the stripe group index number shown in the “show” command may be
used in place of .
who [] [long]
List clients attached to file system.
In the short form, “who” returns the following information:
- acfs I.D.       – Client License Identifier
- Type            – Type of client connection
FSM              – File System Manager (FSM) connection
ADM              – Administrative (cvadmin) connection
CLI              – File system client connection. May be
followed by a CLI type character:
S – Disk Proxy Server
C – Disk Proxy Client
H – Disk Proxy Hybrid Client
- Location        – Client’s hostname or IP address
- Up Time         – Total time client has been connected to FSM
- License Expires – Date client’s license will expire
In the long form, “who” returns network path, build, latency
and reconnect information, if available.
Administrative and FSM clients return a limited set of information.
Xsanadmin (BettyWhite) > select
List FSS
File System Services (* indicates service is in control of FS):
1>*BettyWhite[0]        located on (pid 7030)

September 25th, 2015

Posted In: Mac OS X, Mac OS X Server, Mac Security, Xsan

Tags: , , , , , ,

Leave a Comment

Next Page »