How to use DeployStudio when you can’t have a Mac in the data centre

UPDATE: Ben Toms’ excellent AutoCasperNBI is the perfect tool for helping you create an NBI that you can use with this guide. Go get it here!

I have created a script to do some post processing to the AutoCasperNBI created NBI, however it is extremely site specific so there is no point in me sharing it. However, to achieve a basic DeployStudio Server running inside a NetBooted client as I have described in this post. Just use AutoCasperNBI to create a NBI and then follow the steps below:

• Create your NBI with AutoCasperNBI.

• Mount the DMG and install the DeployStudio Server package to the mounted NBI.

• Now you will need to edit the DeployStudio plist to add the extra items (I’ve listed them in the original post below) it should end up looking like this  (You will need to change the login username and password to the username and password you want, note that the password is encrypted and you need to use DeployStudio Assistant to create a new plist in to get the password. I’ve been unable to work out what encryption DS uses to generate the password)

• Remove the LaunchAgent for Casper Imaging (/Library/LaunchAgents/com.AutoCasperNBI.CasperImaging.plist)

• Replace it with your own that triggers your script which should be similar to what I have shown you below.

• Essentially your script should mount your DS_Repository from your fileserver using whatever logic you need to do this. It could be as simple as hard coding the IP address. Then once mounted start DeployStudio via launchctl.

• Finally open up the DeployStudio Runtime! It should autologin and you’re set!

So we all know and love DeployStudio. BUT the main problem for using it in some enterprises or educational sites is that we have to run the DeployStudio Server on Mac OS X, which require Mac hardware.  For some sites having Mac hardware in the data centre is never going to happen.

I was in this exact position and there  was absolutely no chance that I could get a Mac into the data centre or out to our remote sites to act as the DeployStudio Server.

That doesn’t leave many other options available for super easy and slick netboot based imaging for our Macs.

Then I had an idea. The machines that we are netbooting are Macs…. So why can’t we run the DeployStudio Server from the NBI? Then we just have the Runtime application connect to itself at 127.0.0.1:6080 and away we go.

So I went ahead and created a netboot image that had DeployStudio server installed on it and configured it to access a local repository at /Volumes/DS_Repo.

The reason I told DS to use a local file repository instead of a network share is because if I specified a network share, then that address is hardcoded into the com.deploystudioserver.plist on the NBI. I have multiple remote sites and would rather have just one NBI that I can shove out to the remote sites, I can then have a script that runs at boot thanks to launchd and mounts the correct file share repository based on IP address. We know that at each remote site we have a file server at x.x.x.20 so it is trivial to get our IP address strip off the last octet and replace it with 20 and then use that IP address to mount our network share into /Volumes/DS_Repo ready for DeployStudio to access.

Here is an example of the script that I use, I also enabled ARD as it can be handy for troubleshooting especially at remote sites.

#!/bin/bash
## Build and set our variables
## Get our IP address and knock off the last octet
baseip=`ifconfig en0 | awk '/inet[ ]/{print $2}' | cut -d "." -f1-3`

fileserver=$baseip.20 ## Now we create our file server address
usrname=ladmin # username to access our fileshare
password=admin # password to access our fileshare
mntpoint=/Volumes/DS_Repo # mount point on the filesystem to place our share
share=DS_Repo # Name of our sharepoint

## Script Actions
mkdir $mntpoint # Go ahead and create a folder to put our sharepoint in

## Mount the share
/sbin/mount_smbfs //$usrname:$password@$svrip/$share $mntpoint

## Now start DeployStudio Server
## This should be run as root
/bin/launchctl load -F /Library/LaunchDaemons/com.deploystudio.server.plist

## Oh lets start ARD for the fun of it as well
# Enable ARD for user
enabled_ard_user="ladmin"

# Enable for user and give all privileges
/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -users $enabled_ard_user -access -on -restart -agent -privs -all
# Allow access for all users
/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -configure -allowAccessFor -specifiedUsers

# Finally open DeployStudio Runtime
/Applications/Utilities/DeployStudio\ Admin.app/Contents/Applications/DeployStudio\ Runtime.app/Contents/MacOS/DeployStudio\ Runtime.bin

I also modified the deploystudio server launchdaemon in order to prevent it from starting the server automatically at boot. Instead we will get our script that mounts the network share to start DS after it has successfully mounted the network share.

The DeployStudio Server launchdaemon exists at : /Library/LaunchDaemons/com.deploystudio.server.plist

To prevent the server from starting automatically we need to edit this line

<key>RunAtLoad</key>
<true/>

to

<key>RunAtLoad</key>
<false/>

So now we have a netboot image that boots up, checks to see what IP address it has and then connects to its local file server and mounts our DS_Repository share. Then it goes ahead and starts the DeployStudio server process, and opens up the Runtime application which is configured to access 127.0.0.1:60080

This is done by editing the /Library/Preferences/com.deploystudio.plist file and ensuring these keys are present

<key>server</key>
 <dict>
 <key>url</key>
 <string>http://127.0.0.1:60080</string>

Awesome.

But how do we update the workflows, scripts and packages?

Easy.

I run a DeployStudio Server instance in a VM, this accesses a local file share for its DS_Repository which we call the master then if I need to make changes to a workflow, these changes are saved into this master DS_Repository file share.

All we to do is have our master DS_Repository sync up to our remote sites DS_Repository file shares and the netbooted clients will pick up all the changes. We have a pretty tricky way of doing this via SCCM, but for smaller sites this could be a simple rsync script that synchronises the repositories over night.

13 comments

    1. I’m working on an automated way to do this. But for this example I simply installed OS X onto an external hard drive, made all my modifications and installations as needed. Then created the NBI using system image utility. I use BSDPy as my netboot server, so I also had to modify the rc.netboot file on the NBI image afterwards to use a RAM disk for shadow storage. so that the internal hard drive on the netbooted machine could be umounted and erased for imaging.

      Like

      1. Thanks, I’ll have to give it a try. I have never needed to use SIU as the DeployStudio Assistant always handled NBI creation for me. I have been working with BSDPy, so that is why this approach appeals to me.

        Like

      2. Yep, will probably end up with some kind of post processing script that works over an existing DS assistant created NBI to add the extra bits we need.

        Like

    1. Yep, I looked at that first, but I found AutoCasperNBI was easier for me. I didn’t like the way the ds sys builder created the image and the way it launched DS, using the rc.netboot file. for me, i need an app to run before DS that authenticates the user via AD then collects info from the user does some AD ldapsearches and then gets more info from another DB. I started writing a script that would extend per’s to suit my needs but then autocasper nbi came along and i could instead just drop a couple of packages into the build and boom i had an nbi ready to rock.

      Like

  1. Calum, in having used this method for a couple of months, have you seen any issues with having multiple clients running workflows at the same time? I’m wondering about the integrity of things like the logs SQLite database, which normally would be expected to be accessed only by the server, not many simultaneous instances of the server.

    Like

    1. Yeah I was worried about this as well. But so far no problems have cropped up. We don’t see a lot of simultaneous clients netbooting usually only 5-8 at a time and this has so far been fine. Still running in test/pilot stage at the moment so this hasn’t hit all of our sites yet. Will post back if we run in to any troubles once we start rolling it out to all of our sites

      Liked by 1 person

  2. Awesome writeup! I’m trying to get this to work with an external hard drive. How are you running the script that mounts the share point as a local volume? Are you using LaunchDaemon .plist file? I’m able to run the script manually and it works great with my modifications, however when creating a .plist and using LaunchDaemon, it runs before the user logs in, and doesn’t complete the share mounting, resulting in an empty repository. I have my master images in there, but they only appear if I manually run the script when I login. Thanks for any tips!

    Like

    1. Hi,

      You’re so close.

      A LaunchDaemon runs as the root user at boot. Its great for background processes / daemons. These types of things don’t require a user to be logged in for them to work.

      What you need is a LaunchAgent. LaunchAgents run in the user context.

      Here is my LaunchAgent script, it should be saved in /Library/LaunchAgents also you will need to pay attention to permissions it should be root:wheel 644


      <?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"&gt;
      <plist version="1.0">
      <dict>
      <key>Label</key>
      <string>com.domain.calumhunter.dsnetbootstartup</string>
      <key>ProgramArguments</key>
      <array>
      <string>/Library/Scripts/mount_share.sh</string>
      </array>
      <key>RunAtLoad</key>
      <true/>
      </dict>
      </plist>

      Like

      1. Hmm….I tried that – however it kept prompting me for the user’s password when I logged in. Some of the commands in the script require root. This was the problem I ran into when using a LaunchAgent – how do we make sure they run as root? I’d like the process to be seamless and not have to type in the password over and over.

        Thank you for your help!

        Like

      2. I should also add – the account I’m logging into this machine with is an Administrator account. Should I enable the root user, and login as root instead?

        Like

  3. Why does your script require root? There shouldn’t be anything that requires root privileges? I use an administrator account, no need for root.

    Like

Leave a comment