2022/2023 DEP - Complete Zero Touch (DEPNotify & NoMAD-login)

New Contributor III

Hi All,

Really just wanted to post the video of our 2022/2023 device enrollment that is currently fully automated and 'zero touch' really just as a thankyou for all the knowledge you guys and gals have inadvertently poured into me to make any of this possible.

If anyone has any comments, require assistance or even suggestions id be more than happy to take the time to reply,


Kind regards and keep doing what your doing!



New Contributor II

Thank you Sassy!


New Contributor III

Emmanuel College Warrnambool DEP

Hi @supersev @thanks heaps for commenting here are some rough points on what I have included in our workflow and the references you can use to build your own ‘zero touch’ instance.

  1. Getting Started with DEPNotify:


Excellent comprehensive user guide & Jamf workflow:

HCS Technology Group - How to Deploy DEPNotify as a Jamf Pro PreStage Enrollment Package with Custom...

  1. Auto login user:

Easy to follow, we just pass the account created in our PreStage as the ‘auto login’ user and be sure to include:

/usr/bin/defaults delete /Library/Preferences/com.apple.loginwindow autoLoginUser &> /dev/null

At the end of your DEPNotify script to turn of the ‘Auto login’ user


    3. Video playing in background of DEPNotify

I use a cloud hosted GIF that is publicly accessible and without any URL encryption.

Currently I use ‘Imgur’ but used a GoogleCloud ‘bucket’ originally, both allow full ‘https’ un-encrypted URL paths.


My production DEPNotify ‘Video’ example:

echo "Command: Video: https://imgur.com/KNJMyVj.mp4" >> "$DEP_NOTIFY_LOG"
     4. Policy Arrays:

The policy’s run via DEPNotify are very simple and related generically to student devices,


"Naming device via Google Doc,NameDevice"

"Binding Device to Active Directory,Bind2AD"

"Enabling Remote Management,EnableRemote"

    "Enabling Remote Management Options,EnableRemote2"

    "Installing Google Drive,googleDrive"

"Installing Google Chrome,GoogleChromeUni"

  "Installing Zoom,InstallZoom5"

  "Installing the College Print Drivers,2022Printer"

"Rejigging the default Dock Items,InstallDock"

"Installing Creative Cloud,installCCuni"

"Installing NoMad Login,noMadInstall"

    "Download Latest MacOS,downloadMacOS"

  "Uninstalling DEPnotify installers,uninstall-depnotify-installers"



The most notable policies would be:

NameDevice’, this is a bash script I created to Curl down a Google Sheet of serials and computer names then using the Jamf Binary ‘setComputerName -fromFile’ command to name this device.

Note: I did rely on a Python script originally for this but as Pythons is no longer native with MacOS ‘Big Sur’ and onward I needed to create a universal solution.

GoogleChromeUni’, this I quite handy due to the fact it Curls the latest Google Chrome every time. No need to re-package anything (which I’m a big fan of not having to do)

noMadInstall’, this one installs the ‘NoMAD login’ application (repackaged via Composer to include images and icons)
        5. NoMAD-login:

This was added to the workflow to enable ‘non-mobile’ accounts, so we can continue to migrate more things to the cloud (printing, file shares etc) and also to change up the login window, which I had done fun with..


The main trick here was to not include the ‘post install’ script but rather use an additional policy with the NoMAD options as Jamf ‘positional parameters’ so everyone could get the install but different login window/wallpapers based on smart groups or year level. Much more universal application.


Putting it all together:

Timing is everything and it’s paramount that policies trigger in the right order, this may differ from the documentation shared but the principles are the same.


  1. Device is assigned to PreStage (in our scenario this is the ‘group or bulk version’ PreStage. Due to the fact we have a ‘custom’ version I had to get creative to ensure the two don’t clash down the line.

Note: DEPNotify is not deployed during our PreStage.. due to the ‘auto login’ this occurs later.
        2. Auto login

The ‘Auto login’ script runs in a policy set as an ‘Enrolment Complete’ trigger so it’s the first thing that runs… the computer reboots immediately to initiate the ‘auto login’ process


Follow this excellent guide to create an extension attribute that will then have the computer’s with ‘auto login enabled’ fall into a ‘auto advance’ smart group then it can trigger DEPNotify




       3.Once ‘auto logged in’ DEPNotify will run due to it being scoped to computers that have ‘auto login enabled’ and waits for the user to be at the desktop.


         4. All the policies will run as discussed above and if the computer requires an update that will also occur in the background, the last step is a reboot for the new user to login..


By this point the computer has fallen into the correct smart group to obtain the right ‘NoMAD login’ wallpaper and icon.


I go one step further for our year 7’s as we create a wifi config profile so they can login to there own AD account themselves when they receive the laptop at school.


No need for a cables login..

Any questions I’d be more than happy to elaborate further or share any scripts they may help.


Valued Contributor

This looks great! How are you applying updates during zero-touch, and does this step also apply to Apple Silicon Macs?

New Contributor III

Hi there @jtrant @I created the following script,based on others around to ‘fetch’ the appropriate installation.

This is a policy that is called during our DEPNotfy Policy Array, basically grabs an install if need be otherwise moves on…



GET_OS_UPDATE=$(softwareupdate --list-full-installer | sed -n 3p)
echo "$OS_BUILD"


majorVersion=$(echo $OS_BUILD | cut -d "." -f 1)
minorVersion=$(echo $OS_BUILD | cut -d "." -f 2)


echo "$TRIM_OS_NAME"
OS_NAME=${TRIM_OS_NAME%%, Version:*}
echo "$OS_NAME"

echo "Latest Major Available OS Version is: ${OS_NAME}, ${majorVersion}"
echo "Latest Minor Available OS Version is: ${OS_NAME}, ${majorVersion}.${minorVersion}"


installerFileName=$(ls /Applications/ | grep "Install ${OS_NAME}")
macOSVersion=$(sw_vers -productVersion)
macOSMajor=$(sw_vers -productVersion | cut -d '.' -f1)
macOSMinor=$(sw_vers -productVersion | cut -d '.' -f2)
macOSName=$(awk '/SOFTWARE LICENSE AGREEMENT FOR macOS/' '/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf' | awk -F 'macOS ' '{print $NF}' | awk '{print substr($0, 0, length($0)-1)}')


if [[ ${majorVersion} -gt ${macOSMajor} ]] && [[ ${installerFileName} == "" ]]; then
echo "You currently have ${macOSName}, version: ${macOSVersion}, you will now be ugraded to the newest release, ${OS_NAME}, ${OS_BUILD}";
softwareupdate --fetch-full-installer --full-installer-version ${OS_BUILD}
elif [[ ${majorVersion} -eq ${macOSMajor} ]] && [[ ${macOSMinor} -lt ${minorVersion} ]]; then
echo "You currently have ${macOSName}, version: ${macOSVersion}, you will now be ugraded to the newest release, ${OS_NAME}, ${OS_BUILD}";
softwareupdate --fetch-full-installer --full-installer-version ${OS_BUILD}
elif [[ ${majorVersion} -gt ${macOSMajor} ]] && [[ ${installerFileName} != "" ]]; then
echo "Looks like you already have ${installerFileName} sitting in the Apllications folder... quiting now"
exit 0
echo "Oh dear..., looks like your computer cannot upgrade past ${macOSName}, version:${macOSMajor}...";
exit 0


Then after the policy array I run a stand alone policy in the background (using ampersand) that will install the update if it exists.. 


The script is:


set x

installerFileName=$(ls /Applications/ | grep "Install macOS")
cpuNameIntel=$(system_profiler SPHardwareDataType 2>/dev/null | awk -F ": " '/Processor Name/ {print $NF}')
cpuNameApple=$(system_profiler SPHardwareDataType 2>/dev/null | awk -F ": " '/Chip/ {print $NF}')
macOSVersion=$(sw_vers -productVersion)
macOSName=$(awk '/SOFTWARE LICENSE AGREEMENT FOR macOS/' '/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf' | awk -F 'macOS ' '{print $NF}' | awk '{print substr($0, 0, length($0)-1)}')

echo "password is $password, passed via Jamf as $5"

if [ -z "$currentUser" ]; then
currentUser=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }')

installerFileName=$(ls /Applications/ | grep "Install macOS")
if [ "$installerFileName" == "" ] ; then
echo "Installer not found!"
exit 1

if [ -z "$cpuNameApple" ]; then
if [ -z "$currentUser" ]; then
echo "Current user cannot be found. Exiting program."
exit 1

"/Applications/$installerFileName/Contents/Resources/startosinstall" --agreetolicense --forcequitapps --nointeraction &
osascript -e 'display dialog "MacOS is updating in the background, please ensure you do not turn the device off, the device will reboot automatically" buttons {"Ok"}'
osascript -e 'beep'

elif [ -n "$cpuNameApple" ]; then
if [ -z "$password" ]; then
echo "This macOS device has a Apple Processor or is on Big Sur or newer. Please rerun shell script with a admin password appended"
exit 1

if [ -z "$currentUser" ]; then
echo "This macOS device has a Apple Processor or is on Big Sur or newer. Please rerun shell script with a admin password appended."
exit 1

/usr/bin/expect <<EOF
set timeout -1
set password ${password}
spawn {/Applications/$installerFileName/Contents/Resources/startosinstall} --agreetolicense --forcequitapps --nointeraction --passprompt --user {$currentUser}
expect "By using the agreetolicense option, you are agreeing that you have run this tool with the license only option and have read and agreed to the terms.\r\nIf you do not agree, press CTRL-C and cancel this process immediately.\r\nPassword: "

send "$password\r"


osascript -e 'display dialog "MacOS is updating in the background, please ensure you do not turn the device off, the device will reboot automatically" buttons {"Ok"}'
osascript -e 'beep'


echo "Could not verify if device is a Apple Product"



Hope this helps



Would you be able to elaborate a little more in how you setup the MacOS updating? I'm still a little new to Jamf management and got lost on the second script you sent, I get the policy creating to search for updates, but don't know what to do with the second script to install them. 


Sure thing!
In the main DEPNotify script near the end I run another policy trigger

"$JAMF_BINARY" policy "-$TRIGGER" installMacOS &

This runs the second 'installMacOS' script in the background
You need to:

  1. Attach the second script to a policy
  2. Define the admin username and pw as positional perameters $4 and $5 in the policy
  3. Scope to 'all users and devices'
  4. Set it up as a 'custom event' policy trigger
  5. Set it as 'ongoing' to be able to call it anytime.

Please let me know if you want further clarification, happy to help


Sorry to bug, but do you add that "$JAMF_BINARY" script to the very end of the DEPNotify Script before "exit 0 " or in the Policy Array?

New Contributor III

Great work @sassy_p, that looks spotless, and well put together!

@snazarian – I can't be certain, but it's possible this is based on my Automated Lab Deployment blog post series: https://irritatedsysadmin.substack.com/p/fully-automated-lab-imac-deployment-with-jamf-pro-ade-part-...

I also did a talk at the MacAdmins Meeting based on this: https://stream.lib.utah.edu/index.php?c=details&id=13493

You can find more info and plenty of links here, too: https://github.com/GrahamWilliams-DMT/macadmins-presentation-labdeployment

It's also very possible that @sassy_p put all the puzzle pieces together themselves, just like I did :).

New Contributor III

Hi @grayw , this is indeed from your excellent blog, well at least the ‘auto login’ & extension attribute to smart group section. 

An invaluable piece in the puzzle, most other things are bits and pieces from everywhere, pouring through blogs and posts. 

I have without know at the time credited you above in reply to the first question , please feel free to have a look at the workflow and see what you think,

I’ll be sure to look at the other links you attached In response to @supersev @‘S questions,

Thanks again for sharing your knowledge, it’s certainly helped myself and my team in another seamless run up of 450 devices in around 3 days, 


New Contributor

Thanks for those links, they are very useful for me.

By the way, if anyone over here face problems in writing your essay assignments then you can simply visit https://letsgradeit.com/review/myperfectwords/ here where you can find a lot of reviews for an essay writing service. And can choose according to you.

Valued Contributor

Hi @sassy_p I guess this is run on the campus network so that the domain bind works yes?   I'm still working on this and your posts here help heaps. 

New Contributor III

Yes, indeed at the moment we still bind to AD, if you need a hand feel free to ask, i'll check in when I can, cheers

New Contributor III

This is exactly what I was looking for to get started with depnotify!

Does this also work with Kerberos?

Hi emanueldiaz_09, not exactly sure which part you'd be referring to with Kerberos but I haven't tried implementing anything related to it, sorry I couldn't help further, if you get stuck with you implementation im here and happy to help, Cheers Pete

Cheers Pete

New Contributor III

Hi @sassy_p, would you share your NameDevice bash script?  I'm currently using the Apple Zero Touch Deployment process to update the table in JAMF, but it's quite outdated at the point.

Best, Fred

New Contributor III

Sure thing!
Its a simple one passing a Google Sheet URL to a policy, the script is:



# Curl CSV

curl -L "https://docs.google.com/spreadsheets/d/${FILE_ID}/export?exportFormat=csv" -o "${CSV_PATH}${FILE_NAME}"

# Use the jamf binary to set the name

/usr/local/bin/jamf setComputerName -fromFile "${CSV_PATH}${FILE_NAME}" && exit 0 || echo "Something went wrong... follow the Jamf log" && exit 1;


The positional perameters names and example:

Parameter 4
URL to Google Sheet (Set permissions to 'Anyone with link')
Parameter 5
Parameter 6
In the spreadsheet you only need the serial number of the device and its name (See test spreadsheet)
Then I call the custom trigger in the policy array:
"Naming device via Google Doc,NameDevice"
 Any other questions dont hesitate to ask,
Kind regards