Modern OS Provisioning for Windows Autopilot using OSDCloud

Today I want to talk about modern OS Deployment for Windows Autopilot Enrollments using OSDCloud. Also, I will show you where we came from with regards of OS Provisioning and which customizations we made to OSDCloud to make it fit our needs even more.

OSD using a SCCM Task Sequence

When we started using Windows Autopilot back in 2018/19, we needed a solution to prepare existing devices for the enrollment with Autopilot and since we started using Pre-Provisioning (aka. WhiteGlove) as well, the official way for Autopilot for existing devices using the exported .json Profile was not an option. We started using a basic SCCM Task Sequence to install the base Windows Image and upload the Autopilot Hash as described here: https://mikemdm.de/2023/01/29/can-you-create-a-autopilot-hash-from-winpe-yes/ and here: https://mikemdm.de/2023/02/12/automate-autopilot-uploads-with-azure-automation-runbooks/
The Task Sequence looked something like this, and contained basically three things besides the OSD itself, the Autopilot Upload, the “Tennant Lockdown” Feature using a script based on the solution of Michael Niehaus: https://oofhours.com/2022/05/31/requiring-a-network-connection-during-oobe/ and a part for handling drivers (not visible in the Screenshot).

While this solution worked pretty reliable, we had one issue with this solution, the driver management. Since we had to support more than 100 different hardware models from Dell, HP and Lenovo, we needed to provide drivers for all of these models for the inital installation. Additional to that, we wanted to have a way to allow installation of even more models in case something was not available in a specific region. All this created the need for a pretty large Task Sequence that needed to be maintained and also needed more than 100GB of storage on our around 30 Distribution Points all around the world.

Modern OS Provisioning using OSDCloud

Our Solution for this issue came with the wonderful Project OSDCloud, that supported nearly all of our hardware models out of the Box, by downloading drivers directly from the OEMs, eliminating the need of local repositories for these driver packs. Additionally with the support to download drivers from Windws Update, it even can support new / unknown models.

Since we already wanted to get rid of our SCCM Infrastructure and most of our newly bought devies are already uploaded by the OEM, we decided to go with an bootable USB Drive Solution, which in combination of the integrated Wi-Fi support allows us to worst case use an iPhone Hotspot to reprovision a client if needed.

While OSDCloud provides and integration for Autopilot, it is based on the .json file injection, makeing it unsuitable for Self-Deploying or Pre-Provisioning Scenarios. To mitigate this limitation and to further simplify the GUI to the point, where the admin does not have to choose the OS Version, we decided to build a small PowerShell Forms based GUI, that can be used to launch OSDCloud with a few parameters, Upload the device to Autopilot and set the Tenant Lockdown UEFI Variable. You can find the PowerShell Scripts for the launcher on my GitHub, so you can customize it to your needs: https://github.com/mmeierm/Scripts/tree/main/OSDCloud

The first Page of the Launcher will present you two options, the Autopilot Upload Button will unzip a password encrypted archive, containing the Autopilot Upload Script, described here, also i uploaded the script to extract the files to GitHub.

The Start-OSDCloud Button will show a new Page that allows you to select a driverpack and the OS Language.

The Windows Version (Win 10 vs. Win 11) will be automatically selected, based on Hardware support. Since the only devices, that we still want to be able to install Windows 10 have Intel Core CPUs form Generation 2 – 7, i only check for this and an enabled TPM 2.0 Security Chip here.

Once the Launcher checked the HW Compatibility, it fills a global Variable “StartOSDCloudGUI” and hand over the job to OSDCloud with an set ZTD Option, so it won’t ask for permission to wipe the SSD, so be careful during testing.

If you want to know more about this, let me know in the Comments and I will be happy to show you more details if wanted.


Posted

in

by

Comments

33 responses to “Modern OS Provisioning for Windows Autopilot using OSDCloud”

  1. Ahmed

    Hello,

    Very Informative, interested task sequence. could you please share this task sequence.

    Thanks,

    1. Hi,

      sure i exported the TaskSequence for you and uploaded it to GitHub: https://github.com/mmeierm/Scripts/tree/main/TaskSequence

      You will have to customize it to your needs, the driver packages are 7z compressed folders containing the extracted driver files (.inf / .sys / etc.) The boot image and windows image is basically untouched, and the Hash Upload Package is created as described using the OA3Tool and and Azure Automation Runbook in the backend to upload the device to Autopilot.
      Best Regards
      Michael

  2. […] Modern OS Provisioning for Windows Autopilot using OSDCloud. Link […]

  3. […] Modern OS Provisioning for Windows Autopilot using OSDCloud […]

  4. Thomas K

    Hi,

    can you explain

    “ it is based on the .json file injection, makeing it unsuitable for Self-Deploying or Pre-Provisioning Scenarios”

    self-deploying by the end user does not work with json injection?

    Thanks

    1. Hi, sure I mean the self-deploying mode that does not require the end-user to type in credentials: https://learn.microsoft.com/en-us/autopilot/self-deploying
      As described in the article Autopilot for existing devices, which is basically the json incjection, it does not support self-deploying or pre-provisioning (aka. WhiteGlove) scenarios: https://learn.microsoft.com/en-us/autopilot/existing-devices

  5. Mateusz

    It would be cool if you added support for autopilot tags 🙂

    1. What would you need for GroupTag support? Both the Upload script and the Automation Runbook are already ready for Autopilot GroupTags. The upload script from https://github.com/mmeierm/Scripts/blob/main/AzureAutomation/CollectHashandUpload.ps1 has a place to set a GroupTag in Line 27. We are using a Companion App as described here to set an individual GroupTag: https://mikemdm.de/2023/04/08/autopilot-companion-app/

      1. Mateusz

        Well, yes indeed, but if we use this tool in many countries we have only one tag defined in the code without the possibility of choosing another.

        1. Would you like to have a free text input field for a GroupTag or would you prefer a Dropdown field with predefined values? I would need to check, but I think this should both be pretty easy to add.

          1. Mateusz

            It seems to me that a drop-down list would be better here to reduce the risk of user errors.

          2. I will have a look into this this evening

  6. Mateusz

    I understand that this script is called manually from a flash drive during OOBE or already on the desktop? Is it possible to create a bootable flash drive that will actomatically start the process u show the GUI?

    1. This solution is primarily targeting WinPE from USB or PXE, like it’s used in SCCM / MDT etc since this is not possible with the official script. During OOBE you can use the official Microsoft Script, which already contains a GroupTag field and an -online parameter to directly upload it to Autopilot, no need for any backend solution like here: https://www.powershellgallery.com/packages/Get-WindowsAutopilotInfo/3.9
      Another solution during OOBE would be the Autopilot Manager from Oliver Kieslbach: https://oliverkieselbach.com/2021/12/21/evolving-autopilot-manager/
      https://oliverkieselbach.com/2020/12/08/autopilot-manager/

      1. Mateusz

        I am looking for a solution that has capabilities such as send Autopilot hash and download win 10 – 11 and install the system from scratch. With as little user interaction as possible.

        1. I quickly added a simple GroupTag selection UI to the Upload Script on https://github.com/mmeierm/Scripts/blob/main/AzureAutomation/CollectHashandUpload.ps1

          Screenshot of Message

          You can enable it in line 11 and set the allowed GroupTags in line 13.

  7. Thomas K.

    Really great approach.

    Maybe I missed it, but how did you build the osdcloud image to include your launcher and script?

    Thanks

    1. Hi,
      I basically mounted the ready osdcloud image using DISM /Mount-image /imagefile: /MountDir:
      Once the image is mounted, i modified the File in Windows\System32\Startnet.cmd to instead of start the “Start-OSDCloudGUI” to run my modified launcher.
      Also I added a folder called “Autopilot” to Root of the mounted image, that contains the Files for the Autoilot Upload

      Best Regards
      Michael

      1. Thomas K.

        Works fine.

        When the Mike MDMOSDCloud Gui comes up, by default nothing is selected for the DriverPack.

        Although its an Hyper-V virtual machine and the default OSDCloud GUI shows “Microsoft Update Catalog”.

        Anything I missed?
        Thanks in advance.

        1. I think this is normal and it should still download drivers from MS Windows Update, since the only the selection of the word “none” in line 515 in the script would disable driver download from WU.

          I think if we want to display “Microsoft Update Catalog” we could add an else statement to the if selection in line 452 to do a

          else
          {
          $formMainWindowControlDriverPackCombobox.Selectedindex = $formMainWindowControlDriverPackCombobox.FindString(“Microsoft Update Catalog”)
          }

          But this should be only an optical change, it should not affect the result. Let me try this this evening…

          1. Thomas K.

            Great, thanks. And by the way, nice idea the 15x click on USB Version 0.3 🙂

          2. I just updated the file on GitHub, should now show “Microsoft Update Catalog” instead of empty.
            Yes I also like the “easteregg” to show the original OSDCloud UI in case we need something different 🙂

  8. Thomas K.

    Hi,

    the called Get-AutoPilotHashAndUpload.ps1 in Autopilot.ps1 is the same script as here?
    https://github.com/mmeierm/Scripts/blob/main/AzureAutomation/CollectHashandUpload.ps1

    Thanks,
    Thomas

    1. Hi, yes exactly you can use this script. If you don’t want to build the backend needed for the CollectHashandUpload.ps1 script, you can also use https://github.com/mmeierm/Scripts/blob/main/OSDCloud_helpers/OSDCloud_UploadAutopilot.ps1 which uses DeviceCode Authentication instead, however I personally prefer the first variant, as it is easier for the technician.
      Best Regards,
      Michael

  9. Thomas K.

    Is anyone getting the same cosmetic error as everything works, but

    powershell -NoL -C Install-Module -Name OSD -Force

    out of

    :: OSDCloud related commands
    powershell -NoL -C Initialize-OSDCloudStartnet
    powershell -NoL -C Initialize-OSDCloudStartnetUpdate
    powershell -NoL -C Install-Module -Name OSD -Force
    powershell -NoL -C Import-Module OSD -Force

    of the startnet.cmd errors out in:

    PackageManagement\Install-Package: The module ‘OSD’ cannot be installed or updates because the authenticode signature of the file ‘OSD.psd1’ is not valid.

    Thanks

    1. Hi, I had this on one of my boot drives, i modified the module Initialize-OSDCloudStartnet.ps1 from “X:\Program Files\WindowsPowerShell\Modules\OSD\22.11.1.1\Public\Functions\OSDCloud\” to add “-SkipPublisherCheck” in line 33 that does the autoupdate.

  10. Once I initially commented I clicked the -Notify me when new feedback are added- checkbox and now every time a comment is added I get 4 emails with the same comment. Is there any method you possibly can remove me from that service? Thanks!

    1. Hi, you mean the notifications from GitHub? You can log in to GitHub, go to Settings -> Notifications -> under Subscriptions you can show your “watched repositories” and set if and how you want to notified on a per repo basis.

  11. Phillip

    We would like the ability to add the device to autopilot and your screenshot looks great. Do you have an easy guide on how we can add this to our current OSD cloud usb drive that uses winre? Your link to github has a lot of scripts and I’m not sure what to do. Has anyone written any step by step instructions for using your scripts? I see you’re posting screenshots but I’m really confused.

  12. rob bousie

    hi Mike,

    I am hired to helpout with a migration, away from sccm, into intune. The idea is to use sccm software center to deploy a final task sequence. We want to offer the end-users to start this from home (wifi), so initially a vpn is used to catch the task sequence (no CMG available)

    The task sequence should repartition disk 0, to host windows 11. oobe is required to start using autopilot. The devices are already known (hashes imported) into intune. The devices now will no longer be co-managed, just fully intune managed.

    Is there a example task sequence we can take a peak at? Would really love that too help us started.

    1. Hi, haven’t done much with sccm in the last years, but I guess a basic Task Sequence that is created via the wizard in SCCM should pretty much do that? I also uploaded the Task Sequence that we used in the past, so you can use it as a basis. If the devices are already running the right Windows version, you could also evaluate to just wipe the current installation to start fresh over in OOBE.

  13. Tommi Steiniche

    Hey Mike.

    I am a it student, and i am trying to implement OSDCloud on our laptops into Intune. With your MikeMDMUI.ps1. but it failes with the invalidauthenticodesignature “The module ‘Microsoft.Graph.Intune’ cannot be installed or updated because the authenticode signature of the file ‘Microsoft.Graph.Intune.ps1’ is not valid.”

    Our Autopilot script is.
    Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Confirm:$false -Force:$true
    Install-Script get-windowsautopilotinfo -Confirm:$false -Force:$true
    get-windowsautopilotinfo -Online -TenantId XXXXXXX -AppId XXXXXXX -AppSecret XXXXXXX

    I have tried to set the executionpolicy to bypass but it won’t work.

    It works fine when we write it manualy after the install.
    But it would be nice to use your great GUI to set it up while installing.

    1. Hi, do you get this error within WinPE or after the installation in Windows?
      Within WinPE this Script will not be able to run, the WMI Class is not present and the online parameter will also not work, as the login.microsoftonline.com site cannot be displayed successfully.
      If it is in Windows, check the PATH Environmentvariable if there is maybe the x86 PowerShell Modules Folder listed. If yes try to remove it and try it again.

Leave a Reply

Your email address will not be published. Required fields are marked *