Skip to main content

As long as we've had JAMF, we've done standard imaging: reformat or partition the drive, install the base OS, software packages, settings, AD bind, etc. But ever since 10.8 came out and forked the OS, I've started to think that thin imaging might be the way to go and just overlay our settings, software, etc. on the target Mac right out of the box. No more reformatting, no more partitioning.

Has anyone else gone this route and wouldn't mind sharing their experiences? Thanks!

For all of our new units, we leave the OS as is and just push the packages, scripts, other settings and enroll through Casper Imaging. Has been working well. When we "re-image", we will use a configuration that includes an OS.


For all of my machines I use thin (hybrid) imaging. When machines are received I scan the serial number into a spreadsheet and then copy the s/n into a pre-stage imaging workflow. The pre-stage has one package in it, and that package simply drops a LaunchDaemon and a first boot script, and it is set to install at boot time.

The script then does all of my configuration settings (time server, disable IPv6, Finder prefs, etc) and then calls software install policies one by one before running softwareupdate and then restarting.

For re-imaging, I manually boot the machines from the restore partition, erase the drive, and then pull down the OS from Apple. I only have to re-image one or maybe two at a time, and it's rare that I have to do that, so I get no advantage from creating an OS image or workflow around that. I just restore from Apple and then run through the same workflow I use for new equipment.


@stevewood - I'm looking to do the same as you. Can you post your first boot script minus anything private. I'm not the best scripter and always looking to improve my scripts.


Certainly one of those 'it depends on your environment' things. Here's another take...

For new machines I'm moving to a single custom triggered deployment policy that contains a pile of packages and scripts. http://tinyurl.com/k9nxz2q

Basic process is to boot machine to the desktop, run a QuickAdd package and then run a payload free custom trigger package. Right now field techs do this, but will be modified slightly in future to allow end users to deploy themselves. Maybe I'll modify the QuickAdd to include the custom trigger.

For re-imaging I still need an imaging configuration that includes a base OS (retail download + AutoDMG). We can't use internet recovery to get back to stock, though I like that idea better.


@pblake I don't mind posting at all. I've scrubbed what I need to out of the script and posted to my Github account:

http://goo.gl/HZNWFD

I have to make sure to give credit to those whose scripts I borrowed from: the folks at Oxford University (@localhorst) and Rich Trouton (@rtrouton) for certain.

If you need any help deciphering, or if you want looks into anything else, just let me know.


@stevewood - Thanks so very much for posting this.

I've been trying to get my hands around something that I could use in a 'thin' mode as we currently use the old USB boot/wipe/install of the latest OS version (currently 10.9.2) from a copy pulled down from the AppStore on each release from Apple.

To be able to pull a machine from the cabinet and just have it use a 'first boot' would be much faster.

Quick newbie question.. How do you get the first boot script onto the machine initially for it to run?

Thanks again!


We've been using thin provisioning since 10.9. It certainly has its advantages for new hardware. Re-images are another story... We've developed a internal app which acts as a user/tech gatekeeper. The user/tech completes the OS X new user account setup assist then downloads and runs the app. It handles basic environmental checks and network settings, gets a one-use quickadd from the JSS, handles machine naming, and calls the policies used to apply the corporate settings/packages. At the end of the process the local account (501) is destroyed because Mac is AD bound burring the process. On a fast connection with a near by Casper DP, it takes ~25 minutes from boot chime to finish. ~20 dmgs/pkgs, ~15 scripts, all over 5 Casper policies called by a single trigger.

That being said, I'm not a fan of junking the old "nuke-and-pave" method... It has its uses. Then again I also don't throw away my broken screwdrivers....


Thanks @stevewood for the mention. Like some ideas of your firstboot script. Added a couple of feature requests to our bug tracker.


We do something similar to the folks above. For new machines out of the box we don't mess with the OS already on the machine. We have the tech create the initial admin account and then they run a deployment app we developed in house that basically allows them to set the name of the machine, what one of the two AD domains that we use that the end user's account is on, checks that the AD computer record was created ahead if time, etc, and them they hit configure which deploys a quick add package and it sets off a shell script that it feeds the various options from the GUI and runs a main policy with a custom trigger for new machines so all of our software packages and scripts get deployed, VPN gets set up for the user, etc.

Cocoa dialog shows the progress of the install. The best part is the app will detect if they aren't on the corporate network and fire up a VPN connection. Since our packages are hosted in the cloud it's always fast no matter where they are.

Since we have hundreds of offices around the world being able to deploy a new machine this way from our of box to ready for user in 20 minutes without much of any work for the tech is awesome. And we don't have to worry about forked OS builds, running NetBoot servers everywhere, etc.


We've been doing "thin" imaging for a couple of years now. New computers come in, net booted, and then Casper Imaging is used to install packages and scripts, and the hard drive is not erased nor is the OS replaced. Works great.

I've stopped using the term "thin imaging" or "imaging" all together after reading this article.http://www.afp548.com/2013/05/21/deployment-a-pedagogical-manifesto/ But it's been a struggle to get everyone on board with the new terms. But it also took me a while to convince them of how thin imaging works.

Examples:
Standard parent config title: Arrived with 10.9 from Apple factory, CompanyNameHere Customize Only (do not erase disk) has 32 packages (all set to install on boot drive after imaging) and 6 scripts (all set at reboot).
Smart (child) config title: Rebuild 10.9 Erase disk, installs OS for most macs, and CompanyNameHere Customize and the only additional item in it is the OS X DMG created using AutoDMG.

Once Apple begins shipping all new devices with 10.10 (or the next OS), I'll change the parent 10.9 config to include the OS and rename it so that it's for rebuilding. No reason to keep around a "thin" configuration if 10.9 isn't arriving any more.

Since Casper Imaging shows the configurations in alphabetical order, the our configuration center appreciates that the title starts with "Arrived". It's at the top of the list and easy to pick.

I really wish I could control when erase disk is enabled or disabled so I didn't have to include that in the name of the configuration.


I am implementing thin imaging at my place of business. The thought being that it can save me some time. Also with the forked OS builds it is easier to adapt to those changes until the common release. Also letting the JSS do the heavy lifting I can add remove components of the build much easier.


Thanks @stevewood. I see a lot of cool things in it.


@RickNTX the process to get the script onto a machine at imaging time is pretty easy. I build a package using Packages that drops a LaunchDaemon and this script onto the machine at imaging time. Here's the LaunchDaemon:

<?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.integer.postimage</string>
    <key>ProgramArguments</key>
    <array>
        <string>/private/var/inte/scripts/postimage_10.9.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

Once the computer restarts, it will run the script and away we go.


These are great comments everyone… appreciate the replies!

Sounds like the re-imaging piece is something I'll need to consider. I agree with Steve in that it's not something that happens very often, but when it does we'll need a way to either return the Mac to "stock" or reformat with a stock OS image.


Robb,

I use net install to re-image, you could go with internet recovery too......
http://support.apple.com/kb/HT5599

@ Steve, thank you for that script!!!

C


We still do it the olde skewl way, nuke & pave.

Unless the OS is forked & then we do the "no-imaging" workflow.

Internet recovery isn't always an option, especially behind proxies & offices on poor MPLS links.


I'm kinda geeking out about this (something I've been wanting to do).

@stevewood - I have a couple questions to adapt to our environment though:
how would it work with having 2 admin accounts, we have our JSS account and then our actual local admin that we use via createusrpkg. Would I just comment out that portion (the admin) of your script and add the createusrpkg via your script's policy id section?

we have asset tag stickers we put on each machine- which is how we ID them (along with a prefix), how could something like that be utilized? In our traditional nuke/pave method - casper imaging sets the machine name for us (we specify each machine name individually). We don't have a lot of mass deployment machines, most of ours come in as one or two at a time.


@ john,

You can use scutil to set the machine name

scutil --set HostName $machinename scutil --set ComputerName $machinename scutil --set LocalHostName $machinename

and I have a casper policy to add the support admin account trigger to run just like the installs in Steve's script.


@jwojda][/url I think you are referring to this section of code:

if [[ ! -d "/var/<adminuser>" ]]; then

    rm -rf /var/<adminuser>/*
    cp -R /System/Library/User Template/English.lproj/* /var/<adminuser>/
    chown -R <adminuser>:staff /var/<adminuser>

else

    rm -rf /var/<adminuser>/*
    cp -R /System/Library/User Template/English.lproj/* /var/<adminuser>/
    chown -R <adminuser>:staff /var/<adminuser>

fi

That code was used to fix the template on my admin user. For some reason the home folder was not getting the full template. On top of that, I was making a change in admin users, so I was testing for one user name and if it did not exist I knew the new admin name was on the machine. I can probably get rid of that and just apply once.

But to answer your question, if you have two admin users that you are putting on the system, whether by script/config/CreateUserPkg, you can absolutely just run that block of code twice for each of the user names. So if your users were "admin1" and "admin2", you would really just need this block of code:

rm -rf /var/admin1/*
cp -R /System/Library/User Template/English.lproj/* /var/admin1/
chown -R admin1:staff /var/admin1

rm -rf /var/admin2/*
cp -R /System/Library/User Template/English.lproj/* /var/admin2/
chown -R admin2:staff /var/admin2

Make sense? Of course, you could also remove that section and test to see if you have any problems with your two admin user accounts. It may turn out that you do not need that code.

As far as your other question, you could still name the computer using Casper Imaging like you already are. I imagine you are manually triggering CI and not using a Pre-Stage Imaging workflow. The only thing that changes is that rather than have all of your packages (including OS) in a configuration that CI uses, you only have one package that puts down the launchd and the First Boot script. This is literally all there is to my configuration:

http://cl.ly/VJCq

Hope that helps you out. If you need more info, just let me know.


I think that @jhalvorson][/url][/url 's approach is the way to go.

It makes sense to leverage Casper's tools and frameworks as much as possible. Stuff like the first boot scripts, directory bindings, configurations and adobe deployment are all built to work with Casper Imaging... it's all been built by JAMF so it makes sense to use it to me. I do think they should rename Casper Imaging to Casper Deploy though since you don't have to "image" with it.

I am just finalising our new workflow at the moment, but a "thin" base config, with an erase and perhaps a clever https://jamfnation.jamfsoftware.com/discussion.html?id=10094 backup user data script (shameless plug) as a smart configuration under that base config.

Drop all your computer config scripts into casper imaging, set them to run at first boot.

The Workflow for my L1/2 guys.. take computer out of box, setup standard admin account..

Go to web portal, download a copy of Casper Imaging and a little script in a zip.

Download... run the script to start Casper Imaging (it will save them configuring jss url and clean up once we are done).

Set computer name, choose configuration, start "image"...

One of my config scripts will take the setup assistant created admin account, and hide it...

All done

StartCasperImaging.command

#!/bin/bash
mypath=$(dirname $0)

defaults write com.jamfsoftware.jss allowInvalidCertificate -bool true
defaults write com.jamfsoftware.jss url -string "https://jss.yourcompany.tld:8443"

open "$mypath/Casper Imaging.app" &
while [ "$(ps aux | grep "[C]asper Imaging.app")" != "" ]
do
    sleep 1
done

rm -R "$mypath"

exit

@loceee I agree that leveraging Casper is exactly what we should do, and that's exactly what I do here. I'm curious about why you have your techs creating an account and then downloading Casper Imaging. We Casper and a a Pre-Stage Imaging setup, you can reduce the steps to: take computer out of box, NetBoot (or boot from external drive) computer, and wait for Casper to finish with a completed machine.

That is basically the workflow that I use. My current workflow is this:

- computer arrives and the serial number barcode is scanned into an asset tracking spreadsheet

- serial number is copied into a pre-stage imaging workflow in the JSS

- computer is unboxed and plugged into ethernet

- computer is NetBooted

- Casper Imaging is set to launch on boot, it finds the s/n in the pre-stage and starts the configuration that is set in the pre-stage

- Casper Imaging completes, machine restarts

- Casper first run script lays down my first boot script and restarts computer

- my first boot script takes over, configures machine settings and installs all software via policies in the JSS

- machine reboots and is ready to go

Now, I don't bind computers during imaging time, but I could, that's an easy enough step to add to the process. I also don't have to create any users on the machine or download anything from anywhere, it is all handled during the imaging process by Casper. The Casper Imaging process handles putting my admin user on the machine and hiding the admin user.

So, again, just curious why you have your techs adding a user manually to the machine.


@stevewood][/url - i noticed in your script, you have a firstboot SG mentioned. what's scoped off that? and the jamf software enroll.sh and firstrun.enroll.plist, that's what you get from Casper Imaging (automagically appears)?


@jwojda I was having a problem with machines not getting into the Firstboot Smart Group, so I added those two lines (touch a dummy receipt and then recon) to get them into the group. The Smart Group is used to scope all of my first boot policies that install software. So all of the policies that are under this section in the script:

# Install software and such via policy

As far as the enroll.sh and firstrun.enroll.plist, yes, those are the parts laid down by CI. Again, I was troubleshooting a problem and was watching to see if those were done. I forgot to scrub those out of the script before posting on Github. :-)


I just started doing this with version 9. The process that we've been following consist of:

  1. Unboxing a new machine, or installing a fresh OS on a repurposed machine.
  2. Enroll the computer with the JSS using a QuickAdd package
  3. Run a deployment script using a policy in self service.

The deployment script is basically just a bunch of custom triggers. The difficult part has been making the smart groups to scope the particular software to the policies so that the deployment script picks up the correct software packages. Over all it has worked every well.


@stevewood

Thanks for posting that first boot script. You have a lot of nice stuff I am going to add to my firstboot script. Really great stuff for easy deployment.