Deploying High Sierra 10.13 with Casper Imaging

reddrop
New Contributor III

Hi All,

I thought i would share with the community my method for deploying High Sierra with Casper Imaging.
The method basically consists for two scripts.

I have tested this with a 10.13.1 Netboot Image created with AutoDMG and AutoCasperNBI

restoreMacOS.sh To deploy the correct image which runs as a "before" script

imagingPostinstall. To run after reboot to run the Sierra Upgrade if needed.

The first script will decide which image to deploy to the Mac based on the currently installed Operating System or File system.

-If it is APFS it will deploy the 10.13.1 APFS image to the APFS container.
-If it is HFS+ it will check the currently installed OS. If the OS is already 10.13 it will image using the 10.13 HFS+ image.
-If the filesystem is HFS+ and the current OS is not 10.13 it will deploy 10.12.6 and then upgrade to 10.13 on next reboot using startOSInstall.

Script 1 RestoreMacOS.sh This replaces your base image in your Casper Admin Config

#!/bin/bash
######################################################################################
#
#   RestoreMacOs.sh - Ashley Stonham <reddrop>
#   Restores either High Sierra or Sierra based on a best guess
#
#   Variables:
#   DP      - Set this to the path that your DP mounts as
#   SIERRA      - Set this to the filename of your Sierra image 
#   HSIERRAAPFS     - Set this to the filename of your HighSierra APFS Image    
#   HSIERRAHFS  - Set this to the filename of your HighSierra HFS Image
#
######################################################################################


## Set these Variables
DP="/Volumes/casperdp"
SIERRA="osx-10.12.6-16G29.hfs.dmg"
HSIERRAAPFS="osx-10.13.1-17B48.apfs.dmg"
HSIERRAHFS="osx-10.13.1-17B48.hfs.dmg"


## No need to change anything below
TARGET="$1"
SOURCE=""

FSTYPE=$( diskutil info "$TARGET" | grep 'Type (Bundle)' | awk '{print $3}' )


## If the filesystem is APFS just restore High Sierra APFS

if [ "$FSTYPE" == "apfs" ]; then
    echo "APFS Detected setting SOURCE to $HSIERRAAPFS"
    SOURCE="$HSIERRAAPFS"
fi


## If the filesystem is HFS check the currently installed OS Version
if [ "$FSTYPE" == "hfs" ]; then
        echo "HFS Detected checking OS Version"
    VERSION=$( defaults read "${TARGET}/System/Library/CoreServices/SystemVersion.plist" ProductVersion )
    echo $VERSION
    if [[ "$VERSION" == *"10.13"* ]]; then
        echo "High Sierra Detected"
        SOURCE="$HSIERRAHFS"
    else
        echo "High Sierra Not Detected"
        SOURCE="$SIERRA"
    fi  
fi


if [ "$SOURCE" == "" ]; then
    echo "ERROR: Unable to determine source"
    exit 1
fi

echo "Running ASR ${DP}/Packages/${SOURCE} to $TARGET"

## If restoring APFS
if [ "$SOURCE" == "$HSIERRAAPFS" ]; then
    echo "Restoring APFS Volume"

    ## Workout APFS Container
    APFSDISK=$( diskutil list "$TARGET" | head -1 | cut -d' ' -f 1 )
    APFSCONTAINER=$( diskutil apfs list "$APFSDISK" | grep 'APFS Physical Store Disk' | cut -d':' -f 2 | tr -d '[:space:]' );

    if [[ "$APFSCONTAINER" == *"disk"* ]]; then
        echo "Restoring ${DP}/Packages/${SOURCE} to /dev/${APFSCONTAINER}"
        asr restore --source "${DP}/Packages/${SOURCE}" --target "/dev/${APFSCONTAINER}" --erase --noprompt 
        diskutil mountDisk "${APFSDISK}"
    else
        echo "Error unable to determine APFS container"
        exit 1;
    fi
else
    echo "Restoring HFS Volume"
    asr restore --source "${DP}/Packages/${SOURCE}" --target "$TARGET" --erase --noprompt --corestorageconvert
    #diskutil cs convert "$TARGET"
fi

exit 0

ImagingPostinstall.sh this scripts runs as an After Reboot and will create a launchDaemon to install HighSierra if the current OS is 10.12

#!/bin/bash

## Check OS Version if 10.12 Upgrade to HighSierra


OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )
if [[ "$OSVERSION" != *"10.12"* ]]; then

    ## Do nothing and exit
    echo "OS is not 10.12"
    exit 0;
fi


/bin/mkdir /usr/local/scripts


cat <<"EOF" > "/usr/local/scripts/NextBoot.sh"
#!/bin/bash
OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )

## If already on 10.13 remove the scripts.
if [[ "$OSVERSION" == *"10.13"* ]]; then
        ## Remove LaunchDaemon
        /bin/rm -f /Library/LaunchDaemons/com.scripts.NextBoot.plist

        ## Remove Script
        /bin/rm -fdr /usr/local/scripts

        launchctl remove com.scripts.NextBoot
        exit 0
fi

## Sleep for 30s to give the mac a chance to connect to network
sleep 30

## Update Device Inventory
/usr/local/jamf/bin/jamf recon

## Run HighSierra Upgrade
/usr/local/jamf/bin/jamf policy -event highSierraUpgrade 

exit 0

EOF


/usr/sbin/chown root:admin /usr/local/scripts/NextBoot.sh
/bin/chmod 755 /usr/local/scripts/NextBoot.sh

## Install the launchdaemon
    cat << EOF > /Library/LaunchDaemons/com.scripts.NextBoot.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>Label</key>
    <string>com.scripts.NextBoot</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>/usr/local/scripts/NextBoot.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

##Set the permission on the file just made.
/usr/sbin/chown root:wheel /Library/LaunchDaemons/com.scripts.NextBoot.plist
/bin/chmod 644 /Library/LaunchDaemons/com.scripts.NextBoot.plist


exit 0
1 ACCEPTED SOLUTION

reddrop
New Contributor III

ReconOnReboot.sh:
This was extracted from the SierraUpgrade script. I just cut it down i use it quite often for software updates etc.

#!/bin/bash
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# CREATE FIRST BOOT SCRIPT
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

/bin/mkdir /usr/local/jamfps

/bin/echo "#!/bin/bash
## First Run Script to remove the installer.

## Update Device Inventory
/usr/local/jamf/bin/jamf recon

## Remove LaunchDaemon
/bin/rm -f /Library/LaunchDaemons/com.jamfps.reconNextBoot.plist

## Remove Script
/bin/rm -fdr /usr/local/jamfps
exit 0" > /usr/local/jamfps/recon.sh

/usr/sbin/chown root:admin /usr/local/jamfps/recon.sh
/bin/chmod 755 /usr/local/jamfps/recon.sh

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# LAUNCH DAEMON
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

cat << EOF > /Library/LaunchDaemons/com.jamfps.reconNextBoot.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>Label</key>
    <string>com.jamfps.reconNextBoot</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>/usr/local/jamfps/recon.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

##Set the permission on the file just made.
/usr/sbin/chown root:wheel /Library/LaunchDaemons/com.jamfps.reconNextBoot.plist
/bin/chmod 644 /Library/LaunchDaemons/com.jamfps.reconNextBoot.plist

RestoreMacOS.sh
Updated with a few tweaks and bug fixes to handle filesystems that don't have CoreStorage enabled.

#!/bin/bash
######################################################################################
#
#   RestoreMacOs.sh - Ashley Stonham <reddrop>
#   Restores either High Sierra or Sierra based on a best guess
#
#   Variables:
#   DP      - Set this to the path that your DP mounts as
#   SIERRA      - Set this to the filename of your Sierra image 
#   HSIERRAAPFS     - Set this to the filename of your HighSierra APFS Image    
#   HSIERRAHFS  - Set this to the filename of your HighSierra HFS Image
#
######################################################################################


## Set these Variables
DP="/Volumes/casperdp"
SIERRA="osx-10.12.6-16G29.hfs.dmg"
HSIERRAAPFS="osx-10.13.2-17C88.apfs.dmg"
HSIERRAHFS="osx-10.13.2-17C88.hfs.dmg"


## No need to change anything below
TARGET="$1"
SOURCE=""



FSTYPE=$( diskutil info "$TARGET" | grep 'Type (Bundle)' | awk '{print $3}' )


## If the filesystem is APFS just restore High Sierra APFS

if [ "$FSTYPE" == "apfs" ]; then
    echo "APFS Detected setting SOURCE to $HSIERRAAPFS"
    SOURCE="$HSIERRAAPFS"
fi


## If the filesystem is HFS check the currently installed OS Version
if [ "$FSTYPE" == "hfs" ]; then
        echo "HFS Detected checking OS Version"
    VERSION=$( defaults read "${TARGET}/System/Library/CoreServices/SystemVersion.plist" ProductVersion )
    echo $VERSION
    if [[ "$VERSION" == *"10.13"* ]]; then
        echo "High Sierra Detected"
        SOURCE="$HSIERRAHFS"
    else
        echo "High Sierra Not Detected"
        SOURCE="$SIERRA"
    fi  
fi


if [ "$SOURCE" == "" ]; then
    echo "ERROR: Unable to determine source"
    exit 1
fi

echo "Running ASR ${DP}/Packages/${SOURCE} to $TARGET"

## If restoring APFS
if [ "$SOURCE" == "$HSIERRAAPFS" ]; then
    echo "Restoring APFS Volume"

    ## Workout APFS Container
    APFSDISK=$( diskutil list "$TARGET" | head -1 | cut -d' ' -f 1 )
    APFSCONTAINER=$( diskutil apfs list "$APFSDISK" | grep 'APFS Physical Store Disk' | cut -d':' -f 2 | tr -d '[:space:]' );

    if [[ "$APFSCONTAINER" == *"disk"* ]]; then
        echo "Restoring ${DP}/Packages/${SOURCE} to /dev/${APFSCONTAINER}"
        asr restore --source "${DP}/Packages/${SOURCE}" --target "/dev/${APFSCONTAINER}" --erase --noprompt 
        diskutil mountDisk "${APFSDISK}"
    else
        echo "Error unable to determine APFS container"
        exit 1;
    fi
else
    echo "Restoring HFS Volume"
    diskutil cs convert "$TARGET"
    diskutil cs resizeVolume "$TARGET" 0
    asr restore --source "${DP}/Packages/${SOURCE}" --target "$TARGET" --erase --noprompt --corestorageconvert

    #diskutil cs convert "$TARGET"
fi

NEWNAME=$( echo "$TARGET" | cut -d'/' -f3 )
diskutil rename /Volumes/Macintosh HD "$NEWNAME"

exit 0

ImagingPostInstall.sh

#!/bin/bash

## Check OS Version if 10.12 Upgrade to HighSierra


OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )
if [[ "$OSVERSION" != *"10.12"* ]]; then

    ## Do nothing and exit
    echo "OS is not 10.12"
    exit 0;
fi


/bin/mkdir /usr/local/scripts


cat <<"EOF" > "/usr/local/scripts/NextBoot.sh"
#!/bin/bash
OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )

## If already on 10.13 remove the scripts.
if [[ "$OSVERSION" == *"10.13"* ]]; then
        ## Remove LaunchDaemon
        /bin/rm -f /Library/LaunchDaemons/com.scripts.NextBoot.plist

        ## Remove Script
        /bin/rm -f /usr/local/scripts/NextBoot.sh

        launchctl remove com.scripts.NextBoot
        exit 0
fi

## Sleep for 30s to give the mac a chance to connect to network
sleep 30

## Update Device Inventory
/usr/local/jamf/bin/jamf recon

## Run HighSierra Upgrade
/usr/local/jamf/bin/jamf policy -event highSierraUpgrade 

exit 0

EOF


/usr/sbin/chown root:admin /usr/local/scripts/NextBoot.sh
/bin/chmod 755 /usr/local/scripts/NextBoot.sh

## Install the launchdaemon
    cat << EOF > /Library/LaunchDaemons/com.scripts.NextBoot.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>Label</key>
    <string>com.scripts.NextBoot</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>/usr/local/scripts/NextBoot.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

##Set the permission on the file just made.
/usr/sbin/chown root:wheel /Library/LaunchDaemons/com.scripts.NextBoot.plist
/bin/chmod 644 /Library/LaunchDaemons/com.scripts.NextBoot.plist


exit 0

View solution in original post

86 REPLIES 86

fred
New Contributor
New Contributor

Cool

bsuggett
Contributor II

Awesomeness !

daniel_hayden
New Contributor III

5f740383803c4625a8cca7f2ed5e9cf4

This is for AHFS only I used the package outlined by Graham. https://github.com/grahamgilbert/imagr/wiki/High-Sierra-Notes
Firmware. Lay the image then the firmware pkg and ad my postlight to it..been working good

sebastianl
New Contributor III

@daniel.hayden

Thanks for that. From your screenshot, do you still use the RestoreMacOS.sh and ImagingPostinstall.sh? Mine to share your workflow?

Thanks!

reddrop
New Contributor III

@daniel.hayden

I considered using the firmware package as you describe. The advantage of doing it with the scripts I wrote is that it stays within the confines of what Apple Support as High Sierra deployment workflows.

emmayche
New Contributor III

Maybe I missed something, but just how does one do an APFS "disk image"? I was under the impression that APFS couldn't do that. Could someone enlighten me? TIA. Never mind. Helps to read the OP.

alexjdale
Valued Contributor III

Any word on when Casper Imaging will be able to leverage ASR for imaging? I'm confused why this isn't already built in.

This looks pretty slick and I'll be testing out a variation of the script.

matin
New Contributor III

Just looking for clarity from the script and screenshot, there is a 10.13 HFS+ autodmg (osx-10.13.1-17B48.hfs.dmg). How is everyone creating this? By default, autodmg creates a 10.13 afps dmg file.

alexjdale
Valued Contributor III

AutoDMG has a menu/preference option to create an HFS+ DMG.

ndempsey
New Contributor II

@reddrop

How, specifically, are you creating your 10.13.1 NetBoot image for this workflow? Are you using the APFS or HFS+ dmg created with AutoDMG? Or are you doing something totally different?

mwilkerson
New Contributor III

@ndempsey , it looks like you'll make two 10.13.1 images from AutoDMG. The first is the standard APFS image, then the second will be the HFS+ variant. Put both of those resulting images in your JSS DP, then modify the first script with the proper image and DP names.

@reddrop , I tried this solution, but after the first reboot, I'm getting a login window where the entire process stops. The login window has a username and password field, but it's an "Other..." user, since there are no existing users yet.

Any ideas where I made a mistake? I initially thought it was because I first tried this after reformatting the SSD, since there isn't an OS for the script to determine the version, but even after installing a fresh 10.12, the process stops at the same point.

dstranathan
Valued Contributor II

I'm just starting to dig into imaging 10.13 High Sierra. A few (possible naive) questions:

-Doesn't Apple's High Sierra installer convert the target volume to APFS is the target volume is an SSD (and HFS+J if it's a rotational drive)?

-Where can I get the standalone firmareupdater packages? I can't find them in the 10.13.1 "Install macOS High Sierra.app" installer app (I have the full ~5GB installer, not the ~20MB "stub")

-When imaging with Casper (Jamf Pro), do you still check the checkbox "Erase target Drive"? Or is all of this 'heavy lifting' being done via the 'RestoreMacOs.sh' script described above?

-Regarding the 'RestoreMacOs.sh' described script above, is this script running BEFORE any other workflow steps? Im failry new to Jamf (1.5 years) and have ever ran a script BEFORE the actual imaging process.

-Does it matter if my NetBoot .nbi image is APFS or HFS+J?

-I'm still on Jamf 99.9 (will upgrade to 10.x soon). In my EARLY 10.13 testing, I didnt see the Jamf "please wait..." GUI screen during it's post-imaging workflow (i.e.; installing packages, running post-imaging scripts etc). Is this expected behavior and is it fixed in later versions of Jamf? Or is this a 10.13 issue?

-Cant I just create (2) base images: (1) HFS+J image for older Macs with rotational drives and (1) APFS image for newer Macs with SSD drives?

ndempsey
New Contributor II

@mwilkerson @reddrop

Right. Got that. The two 10.13.1 images go in Casper/JAMF Admin. Then, you need to use one of them with AutoCasperNBI to create the NetBoot image. I chose to use the HFS+ one. I think I also tried to use the APFS one, but, couldn't get clients to use it.

I also encountered the stop-at-login-window. If you sign in with your management account (ours is created with our imaging Configuration) and navigate to /usr/local/scripts/NextBoot.sh, you can manually run the script (to see what it will do.). It gets to a point where it triggers a policy named highSierraUpgrade, implying that you need to create a policy named highSierraUpgrade. I'm not sure what this highSierraUpgrade policy is expected to be.

Malcolm
Contributor II

Im leaning towards ditching imaging altogether, as I cant seem to get a localadmin user into my autodmg isntaller deployed image, our wifi is pretty strong, but the only downside to this process is that its not zero touch, only because I cant give instructions to 13 year olds and think they will follow them properly.

If ender user device is BYOD wipe and install with high sierra via USB or thunderbolt,
Else
Boot device
Create localadmin account and password
Manual enroll device against user using quick add package stored on USB for quicker access
Use smartgroup to identify if new device and if on macOS 10.12
If device is on macOS 10.12 install highseirra update
If device is on macOS 10.13 and is new device enrollment install app packages.

I could use DEP for the enrollment process, but I find the enrollment notification very clumsy, and disappears too easily.
Atleast the above process would help ensure the right user ends up with the right device, and it will be assigned to them in the MDM, unlike the regular netboot imaging. Which in turn is data entry I would usually have to do anyway through netboot image.

What I would love Apple to do is to make the DEP process pre on first use local admin creation, and Apple configurator to support macOS imaging, for non DEP :)

reddrop
New Contributor III

Hi Guys,

Just to clarify a few of the bits of confusion above. My Macs are bound to AD and the first local-admin account (Non casper managment account) is created by a policy on enrollment complete.

I also have a pkg that is installed as part of the imaging workflow. This will cause the machine to reboot which should then trigger the /usr/local/scripts/NextBoot.sh script. This script is run by a launchDaemon that will run when the machine reboots for the second time.

You also don't want to select erase drive as the script needs to read info on the existing install and then uses ASR to wipe the drive.

Here is what my Jamf Imaging looks like
00c7bd5b6c794ab4b21b07a326eaefbc

Having any package install on drive after reboot in your config will cause the mac to reboot after enrollment complete and trigger the 10.13 upgrade.
Ash

mwilkerson
New Contributor III

@reddrop it sounds like the final missing piece that still baffles me a bit is the policy that the LaunchDaemon actually calls, named "highSierraUpgrade". What does this policy do?

In my case, most of the machines I'd be running this on would be 10.12 machines, so based on the restoreMacOs script, the workflow would be:
- machine would get an asr restore of our fresh 10.12 image
- reboot to get the NextBoot script and NextBoot LaunchDaemon (plus any other packages needed)
- reboot so that the highSierraUpgrade policy is called by LaunchDaemon
- ?
Does that sound correct?

reddrop
New Contributor III

@mwilkerson This is a policy with a custom trigger called highSierraUpgrade
You can find instructions for creating this policy here:
https://www.jamf.com/resources/webinar/managing-ios-11-and-macos-high-sierra-upgrades/
Starts at around 22Minutes.

Basic of it are:
1. Download the High Sierra Installer from the App Store
2. Drag the installer into casper admin.
3. Create a policy that installs that package you just copied to casper admin.
4. Create a custom event trigger called highSierraUpgrade

Here are screen shots of my policy.
8e922f6943b14101a3a6d410bc16e24b
4e2bd25993b249a9bef9c9aabdec85e7
5457a9ebadc447d99da344f76502bfdb
beed4536586f40bba7606b35cd5f495a

Ash :)

msmith80
New Contributor III

I can get this to work but the system runs at a crawl as soon as I log in for the first time and stays that way.

BOBW
Contributor II

@reddrop Hey, just getting this up and running thanks, but I have a quick question.

When using this through Casper imaging :

## No need to change anything below
TARGET="$1"
SOURCE=""

FSTYPE=$( diskutil info "$TARGET" | grep 'Type (Bundle)' | awk '{print $3}' )

it shows the target as the booted drive (the netboot image). I presume this is not correct?
I changed the target to "Volumes/Macintosh HD" in place of the $1 which shows the booted image. If you keep it this way it will always be the netboot image?

cwaldrip
Valued Contributor

@reddrop This is a great solution, thanks.

My current problem is that I have High Sierra listed as a restricted software.

I've tested using an EA to test for the NextBoot.sh in /usr/local/scripts, created a smart group based on the result of that EA showing it installed, and then making an exception for my restricted software for that smart group. The NextBoot script runs recon before it runs the 10.13 installer, so it should detect the script (and the machine shows up in the correct smart group). But I still get my restricted software warning. I re-run recon a second time so the machine should pull down an updated restricted software xml file, but I still get my restricted software alert.

Thoughts?

reddrop
New Contributor III

@BOBW
$1 is reserved variable in Jamf Pro and it references the Target drive, this is passed to the script by Jamf Imaging. It will only work in Jamf imaging.

If you want to test it by hand you can run with an argument like so:

bash-3.2#  ./RestoreMacOS.sh /Volumes/<Name of target>

Ash

TomDay
Release Candidate Programs Tester

Awesome, thanks for posting this! Customizing this for our environment now, where can I get the reconOnReboot script (in the highSierraUpgrade policy)?

cwaldrip
Valued Contributor

You can use Outset (https://github.com/chilcote/outset) and create a boot-once script to run Recon. Have the script (and Outset if needed) installed by calling a policy as part of the ImagingPostinstall.sh script. If you're not using it yet, it's a pretty handy tool in the toolbox.

This is sort of how I fixed my problem above with the machine still being covered by restricted software to keep High Sierra from running. I added a jamf recon, and then a jamf manage command at the beginning of my ImagingPostinstall.sh so that my EA to test if they machine is ready to run High Sierra (does NextBoot.sh exist) can be captured and put the machine in an exclusion group for that restricted software.

allanp81
Valued Contributor

I'm seeing the same issue as @mwilkerson in that after the Jamf Imaging stage the mac reboots but then just sits on a login screen. If I log in with the management account it then brings up the black Jamf imaging screen and starts to go through all of the post install tasks.

I've seen this issue on 10.13, 10.13.1 and now still on 10.13.2 so I'm not sure what the issue is. I've also set it to not update to APFS.

I've created my images the same way I've always done them which is to create my setup and then capture it. I know most people would recommend AutoDMG etc. but the old fashioned has always worked great for our setup(s).

dan-snelson
Valued Contributor II

@TomDay Here's the Recon at Reboot script we use.

TomDay
Release Candidate Programs Tester

@dan.snelson Thanks for that, I read your post and reviewed the script, see that it gets dumped to the client but in Reddrop's Jamf policy it looks like he has recononreboot.sh uploaded to the jamf server. I'm confused how the 2 relate to each other?

dan-snelson
Valued Contributor II

Paging @reddrop

reddrop
New Contributor III

ReconOnReboot.sh:
This was extracted from the SierraUpgrade script. I just cut it down i use it quite often for software updates etc.

#!/bin/bash
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# CREATE FIRST BOOT SCRIPT
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

/bin/mkdir /usr/local/jamfps

/bin/echo "#!/bin/bash
## First Run Script to remove the installer.

## Update Device Inventory
/usr/local/jamf/bin/jamf recon

## Remove LaunchDaemon
/bin/rm -f /Library/LaunchDaemons/com.jamfps.reconNextBoot.plist

## Remove Script
/bin/rm -fdr /usr/local/jamfps
exit 0" > /usr/local/jamfps/recon.sh

/usr/sbin/chown root:admin /usr/local/jamfps/recon.sh
/bin/chmod 755 /usr/local/jamfps/recon.sh

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# LAUNCH DAEMON
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

cat << EOF > /Library/LaunchDaemons/com.jamfps.reconNextBoot.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>Label</key>
    <string>com.jamfps.reconNextBoot</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>/usr/local/jamfps/recon.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

##Set the permission on the file just made.
/usr/sbin/chown root:wheel /Library/LaunchDaemons/com.jamfps.reconNextBoot.plist
/bin/chmod 644 /Library/LaunchDaemons/com.jamfps.reconNextBoot.plist

RestoreMacOS.sh
Updated with a few tweaks and bug fixes to handle filesystems that don't have CoreStorage enabled.

#!/bin/bash
######################################################################################
#
#   RestoreMacOs.sh - Ashley Stonham <reddrop>
#   Restores either High Sierra or Sierra based on a best guess
#
#   Variables:
#   DP      - Set this to the path that your DP mounts as
#   SIERRA      - Set this to the filename of your Sierra image 
#   HSIERRAAPFS     - Set this to the filename of your HighSierra APFS Image    
#   HSIERRAHFS  - Set this to the filename of your HighSierra HFS Image
#
######################################################################################


## Set these Variables
DP="/Volumes/casperdp"
SIERRA="osx-10.12.6-16G29.hfs.dmg"
HSIERRAAPFS="osx-10.13.2-17C88.apfs.dmg"
HSIERRAHFS="osx-10.13.2-17C88.hfs.dmg"


## No need to change anything below
TARGET="$1"
SOURCE=""



FSTYPE=$( diskutil info "$TARGET" | grep 'Type (Bundle)' | awk '{print $3}' )


## If the filesystem is APFS just restore High Sierra APFS

if [ "$FSTYPE" == "apfs" ]; then
    echo "APFS Detected setting SOURCE to $HSIERRAAPFS"
    SOURCE="$HSIERRAAPFS"
fi


## If the filesystem is HFS check the currently installed OS Version
if [ "$FSTYPE" == "hfs" ]; then
        echo "HFS Detected checking OS Version"
    VERSION=$( defaults read "${TARGET}/System/Library/CoreServices/SystemVersion.plist" ProductVersion )
    echo $VERSION
    if [[ "$VERSION" == *"10.13"* ]]; then
        echo "High Sierra Detected"
        SOURCE="$HSIERRAHFS"
    else
        echo "High Sierra Not Detected"
        SOURCE="$SIERRA"
    fi  
fi


if [ "$SOURCE" == "" ]; then
    echo "ERROR: Unable to determine source"
    exit 1
fi

echo "Running ASR ${DP}/Packages/${SOURCE} to $TARGET"

## If restoring APFS
if [ "$SOURCE" == "$HSIERRAAPFS" ]; then
    echo "Restoring APFS Volume"

    ## Workout APFS Container
    APFSDISK=$( diskutil list "$TARGET" | head -1 | cut -d' ' -f 1 )
    APFSCONTAINER=$( diskutil apfs list "$APFSDISK" | grep 'APFS Physical Store Disk' | cut -d':' -f 2 | tr -d '[:space:]' );

    if [[ "$APFSCONTAINER" == *"disk"* ]]; then
        echo "Restoring ${DP}/Packages/${SOURCE} to /dev/${APFSCONTAINER}"
        asr restore --source "${DP}/Packages/${SOURCE}" --target "/dev/${APFSCONTAINER}" --erase --noprompt 
        diskutil mountDisk "${APFSDISK}"
    else
        echo "Error unable to determine APFS container"
        exit 1;
    fi
else
    echo "Restoring HFS Volume"
    diskutil cs convert "$TARGET"
    diskutil cs resizeVolume "$TARGET" 0
    asr restore --source "${DP}/Packages/${SOURCE}" --target "$TARGET" --erase --noprompt --corestorageconvert

    #diskutil cs convert "$TARGET"
fi

NEWNAME=$( echo "$TARGET" | cut -d'/' -f3 )
diskutil rename /Volumes/Macintosh HD "$NEWNAME"

exit 0

ImagingPostInstall.sh

#!/bin/bash

## Check OS Version if 10.12 Upgrade to HighSierra


OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )
if [[ "$OSVERSION" != *"10.12"* ]]; then

    ## Do nothing and exit
    echo "OS is not 10.12"
    exit 0;
fi


/bin/mkdir /usr/local/scripts


cat <<"EOF" > "/usr/local/scripts/NextBoot.sh"
#!/bin/bash
OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )

## If already on 10.13 remove the scripts.
if [[ "$OSVERSION" == *"10.13"* ]]; then
        ## Remove LaunchDaemon
        /bin/rm -f /Library/LaunchDaemons/com.scripts.NextBoot.plist

        ## Remove Script
        /bin/rm -f /usr/local/scripts/NextBoot.sh

        launchctl remove com.scripts.NextBoot
        exit 0
fi

## Sleep for 30s to give the mac a chance to connect to network
sleep 30

## Update Device Inventory
/usr/local/jamf/bin/jamf recon

## Run HighSierra Upgrade
/usr/local/jamf/bin/jamf policy -event highSierraUpgrade 

exit 0

EOF


/usr/sbin/chown root:admin /usr/local/scripts/NextBoot.sh
/bin/chmod 755 /usr/local/scripts/NextBoot.sh

## Install the launchdaemon
    cat << EOF > /Library/LaunchDaemons/com.scripts.NextBoot.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>Label</key>
    <string>com.scripts.NextBoot</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>/usr/local/scripts/NextBoot.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

##Set the permission on the file just made.
/usr/sbin/chown root:wheel /Library/LaunchDaemons/com.scripts.NextBoot.plist
/bin/chmod 644 /Library/LaunchDaemons/com.scripts.NextBoot.plist


exit 0

boanes
New Contributor III

Any advise for using this in an environment that doesn't utilize Netboot?

cwaldrip
Valued Contributor

@boanes We don't use Netboot and I've tweaked it a tiny bit to work. I figured all this out in early December, and i've been on vacation or out for training since then, so this is after a quick review of my notes from then. The below may be missing something...

In our environment we use Casper Imaging from an external boot drive. I have the MacOSInstall.sh as the first thing run during imaging to check the existing OS. If needed it then does what the original script does. The configuration also puts the 10.13 installer put into Waiting Room (or /var/tmp/ or wherever). I have the ImagingPostinstall.sh script check if the 10.13 installer is where its suppose and create the launchdaemon and NextBoot.sh script for running on reboot. All the paths in the scripts work regardless if I'm booted from our imaging drive and using a locally replicated repository (great when your remote location has only 2Mbps total) or the distribution point is mounted.

On reboot everything works like the original workflow above.

I'll have to re-read my notes and I need to re-run through the process again. But it seems to work for us for now (I haven't even documented it for my team yet).

reddrop
New Contributor III

@boanes We use this script in our environment with USB images as well as Netboot images.
All created with AutoDMG and AutoCasperNBI.

Just make sure you are on a network connection like Ethernet as wifi will not always reconnect.

Ash

mrhollywoodgate
New Contributor II

@reddrop Do you use Filevault after imaging / deploying the computers? Or do you not use Filevault with this workflow?

reddrop
New Contributor III

@mrhollywoodgates Yes we use FileVault

We enable FV via a policy later after imaging.

There is a alot of stuff broken in High Sierra around FV2 right now though.

Ash

TSOAFTVPPC
Contributor

Maybe being stupid here. Is there some reason one can't just disable APFS and Create the image from there as usual? In our environment we have multiple partitions to allow rebooting to optimally configured systems for particular software packages.

Deploying High sierra without converting to APFS

reddrop
New Contributor III

@TSOAFTVPPC

See https://support.apple.com/en-us/HT208020 Specifically the section. "About monolithic system imaging"

Also we want to enjoy the benefits of APFS.

Ash

TSOAFTVPPC
Contributor

Don't really appreciate the snark. Answering a question as if the person asking it hasn't already looked at all available resources is disingenuous at best.

"See https://support.apple.com/en-us/HT208020 Specifically the section. "About monolithic system imaging"

Who said anything about monolithic imaging? I just wanted to create the base OS without enabling APFS. I want to avoid APFS because I want to continue to be able to maintain multiple bootable OS X partitions, and I want to avoid APFS. I've already come to grips with losing compiled configurations, even though my typical payload is 100GB over a slowish network.

"Also we want to enjoy the benefits of APFS."
Any file system where file copies are not really bit for bit file copies is a trade off. What till you need to delve into file recovery as I often need to. APFS eliminates the most common endusers achieving local data redundancy: copying files. A copied file in APFS actually creates a lightweight clone with no duplicated data. Corruption of the underlying device would mean that both "copies" were damaged, whereas with full copies localized data corruption would affect just one. Also APFS checksums its own metadata, but not user data. SSD/flash drives are more prone to specific types of corruption caused by power issues etc.
Spare me lectures about cloud storage etc. Delegation of risk is not elimination of risk.
So can anyone answer the question I posed?

reddrop
New Contributor III

@TSOAFTVPPC

There was no snarkyness in my comment. Deploying 10.13 via an image to a mac that has never run 10.13 before is not a supported workflow by Apple whether it is APFS or HFS. That is why I pointed you at the article. It is not just the fact that APFS is being deployed that makes imaging 10.13 more difficult than previous MacOS versions.

I have no idea what your background is or the research you have done. I was only trying to be helpful and point you at the most relevant information to answer your question.

You asked:

Maybe being stupid here. Is there some reason one can't just disable APFS and Create the image from there as usual? In our environment we have multiple partitions to allow rebooting to optimally configured systems for particular software packages.

The reason you cant just disable APFS and deploy a HFS image to upgrade MacOS is because it is a workflow that Apple specifically says not to do. There are firmware upgrades that occur during the upgrade process when run via startosinstall that are not done at any other time.

If you ask why cant you just deploy a HFS image. I can only assume you have not seen the article. Hence I say to you see https://support.apple.com/en-us/HT208020 Specifically the section. "About monolithic system imaging"

Monolithic system imaging can only be used to re-install macOS, not to upgrade to a new macOS version. If you try to use a monolithic system image, required firmware updates will be missing from the installation. This causes the Mac to operate in an unsupported and unstable state. You can use system images to re-install the existing operating system on a Mac.

The purpose of my scripts is to detect what the currently installed version of MacOS is and deploy the the most appropriate image. With the end result of getting a clean never booted install of High Sierra on the mac.

el2493
Contributor III

For the purpose of upgrading our lab computers to High Sierra, I'm using a slightly-modified version of ImagingPostInstall.sh (right now I'm not concerned with RestoreMacOS.sh). I have this (we have computers ranging from 10.12.3-10.12.6, for computers that aren't already at 10.12.6 I want to get them to that version before running the High Sierra installer because I ran into an issue with a 10.12.3 computer where after upgrading to High Sierra none of the Admin accounts worked):

#!/bin/bash -v

## Check OS Version if 10.12 Upgrade to HighSierra

OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )
if [[ "$OSVERSION" != *"10.12"* ]]; then

    ## Do nothing and exit
    echo "OS is not 10.12"
    exit 0;
else
    echo "OS is ${OSVERSION}"
fi


/bin/mkdir /usr/local/scripts


cat <<"EOF" > "/usr/local/scripts/NextBoot.sh"
#!/bin/bash
OSVERSION=$( defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion )

## If already on 10.13 remove the scripts.
if [[ "$OSVERSION" == *"10.13"* ]]; then
        ## Remove LaunchDaemon
        /bin/rm -f /Library/LaunchDaemons/com.scripts.NextBoot.plist

        ## Remove Script
        /bin/rm -f /usr/local/scripts/NextBoot.sh

        launchctl remove com.scripts.NextBoot
        exit 0
fi

## Sleep for 30s to give the mac a chance to connect to network
sleep 30

## Update Device Inventory
/usr/local/jamf/bin/jamf recon

if [[ "$OSVERSION" == *"10.12.6"* ]]; then
    ## Run HighSierra Upgrade
    echo "Upgrading to 10.13.2"
    /usr/local/jamf/bin/jamf policy -event highSierraUpgrade
elif [[ "$OSVERSION" == *"10.12.1"* ]] || [[ "$OSVERSION" == *"10.12.2"* ]] || [[ "$OSVERSION" == *"10.12.3"* ]] || [[ "$OSVERSION" == *"10.12.4"* ]] || [[ "$OSVERSION" == *"10.12.5"* ]]; then
    ## Run Sierra Upgrade to upgrade to 10.12.6
    echo "Upgrading to 10.12.6"
    /usr/local/jamf/bin/jamf policy -event sierraUpgrade
fi

exit 0

EOF


/usr/sbin/chown root:admin /usr/local/scripts/NextBoot.sh
/bin/chmod 755 /usr/local/scripts/NextBoot.sh

## Install the launchdaemon
    cat << EOF > /Library/LaunchDaemons/com.scripts.NextBoot.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>Label</key>
    <string>com.scripts.NextBoot</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>/usr/local/scripts/NextBoot.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

##Set the permission on the file just made.
/usr/sbin/chown root:wheel /Library/LaunchDaemons/com.scripts.NextBoot.plist
/bin/chmod 644 /Library/LaunchDaemons/com.scripts.NextBoot.plist


exit 0

It seems pretty straightforward: if it's not 10.12.* do nothing, otherwise create the script and .plist. When it next reboots if it's 10.12.6 upgrade to High Sierra or if it's 10.12.1-10.12.5 upgrade to 10.12.6 (then in theory after rebooting the next time it'll detect it's at 10.12.6 and install High Sierra). However, whenever I run this through JSS all I see in the logs is "Failed" and in the Details it just says "Executing Policy Sierra/High Sierra Upgrader (Create Launch)" with no errors/feedback. All the Policy includes is the above script, set to run Before (I also tried After and it didn't make any difference). I also checked and the /usr/local/scripts folder isn't created, and I created separate policies for the triggers sierraUpgrade and highSierraUpgrade.

Am I missing something obvious? I looked in jamf.log on the computer and all it shows is that the policy executed (with no errors/feedback), but I'm struggling to find out why it's failing.

el2493
Contributor III

Figured out my issue...I'd named the script "Sierra/High Sierra Upgrader" and apparently JSS won't run scripts with "/"s in the title (it won't give you any error/warning message when you create a script with that in the title, which is kinda annoying...)