Posted on 11-02-2017 08:28 PM
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
Solved! Go to Solution.
Posted on 12-14-2017 04:17 PM
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
Posted on 11-02-2017 08:51 PM
Cool
Posted on 11-02-2017 10:49 PM
Awesomeness !
Posted on 11-02-2017 11:11 PM
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
Posted on 11-03-2017 12:06 AM
Thanks for that. From your screenshot, do you still use the RestoreMacOS.sh and ImagingPostinstall.sh? Mine to share your workflow?
Thanks!
Posted on 11-03-2017 03:42 AM
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.
Posted on 11-03-2017 08:07 AM
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.
Posted on 11-08-2017 08:59 AM
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.
Posted on 11-13-2017 02:31 PM
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.
Posted on 11-13-2017 03:01 PM
AutoDMG has a menu/preference option to create an HFS+ DMG.
Posted on 11-14-2017 03:39 PM
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?
Posted on 11-15-2017 08:50 AM
@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.
Posted on 11-15-2017 01:58 PM
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?
Posted on 11-16-2017 01:56 PM
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.
Posted on 11-16-2017 10:44 PM
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 :)
Posted on 11-20-2017 03:28 AM
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
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
Posted on 11-21-2017 02:09 PM
@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?
Posted on 11-21-2017 05:59 PM
@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.
Ash :)
Posted on 11-27-2017 01:12 PM
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.
Posted on 11-27-2017 07:13 PM
@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?
Posted on 12-01-2017 08:30 AM
@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?
Posted on 12-05-2017 05:07 AM
@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
Posted on 12-08-2017 06:48 AM
Awesome, thanks for posting this! Customizing this for our environment now, where can I get the reconOnReboot script (in the highSierraUpgrade policy)?
Posted on 12-08-2017 06:56 AM
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.
Posted on 12-08-2017 07:23 AM
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).
Posted on 12-08-2017 07:34 AM
@TomDay Here's the Recon at Reboot script we use.
Posted on 12-08-2017 12:20 PM
@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?
Posted on 12-08-2017 12:35 PM
Paging @reddrop …
Posted on 12-14-2017 04:17 PM
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
Posted on 01-03-2018 07:23 AM
Any advise for using this in an environment that doesn't utilize Netboot?
Posted on 01-03-2018 11:06 AM
@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).
Posted on 01-07-2018 10:23 PM
@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
Posted on 01-09-2018 04:07 PM
@reddrop Do you use Filevault after imaging / deploying the computers? Or do you not use Filevault with this workflow?
Posted on 01-09-2018 05:51 PM
@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
Posted on 01-11-2018 05:52 PM
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.
Posted on 01-14-2018 06:13 PM
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
Posted on 01-16-2018 03:44 PM
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?
Posted on 01-16-2018 09:50 PM
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.
Posted on 01-22-2018 06:42 AM
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.
Posted on 01-22-2018 11:23 AM
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...)