Trying out Windows 10 Deployment with OSDCloud

Windows 10 OS deployment with OSDCloud

This blog post captures my experience of trying out the newest development in the OS deployment area – Windows 10 OS Deployment with OSDCloud.

But before getting started, let me put this question first

Do we still need to image devices when we can get a device with an OEM Windows 10 image ready for production use with Windows Autopilot and Microsoft Intune (or any other UEM for the matter of fact) in a matter of minutes?

Windows Autopilot streamlines the provisioning process providing end-users with a customized, organization branded setup experience, that is further aided by a UEM product like Microsoft Intune, which deploys the device configurations and business critical applications during the device setup itself, to provide a production ready device, out-of-box!

Modern management of Windows 10 does not really make it necessary anymore to maintain “golden images” in the environment and with this, the same goes for the need of maintaining an infrastructure to support OS deployment.

Though I do stand by the above statement, I would not say that you would never require to deploy an image to a device in your environment, even if it is completely modern managed.

There are and will always be cases of an OS crash (BSOD and unable to boot) due to system/OS failure, or a HDD/SSD replacement, etc. which essentially brings the device back to a bare-metal state, thereby bringing with it, the need for OS  deployment.

This brings me to today’s topic, trying out Windows 10 OS deployment with OSDCloud, developed by none other than the OSD expert David Segura (@SeguraOSD).

OSDCloud helps to

  • deploy Windows 10 image on a bare-metal device using only WinPE and the OSD PowerShell module.
  • apply DriverPacks to update outdated hardware drivers out-of-box as part of the OS deployment process.
  • apply Autopilot configuration (offline injection) as part of the OS deployment process simplifying the OOBE setup.

The process involves booting the device to a Win Preboot Environment (WinPE) where PowerShell is launched and you pull down a Windows 10 image right from the Internet using the OSD PS module. No infrastructure involved!

So let’s check how it works.

Getting started with OSDCloud – Requirements

The things that you require to test the capabilities of OSDCloud are

  • Access to the Internet with adequate bandwidth,
  • A system to install Windows ADK with WinPE add-on (to enable create a WinPE WIM)
  • An M365 account having sufficient permissions (to connect to Graph and retrieve Autopilot profile for offline use)

OSDCloud: Install Windows ADK and the WinPE add-on

You can install the Windows ADK and WinPE ADK add-on to a physical Windows 10 device, or a Server, or even a Windows 10 VM (you won’t be able to create a USB!). What is important is to match the Windows ADK with the host OS version.

Here the system that I am using as my base machine is running Windows 10 20H2 release. As Microsoft mentions, I can use the Windows ADK for Windows 10 2004 on 20H2 as well.
It is important to install the ADK version supported for the Windows 10 OS Build. Always check the Windows 10 OS build of your host system and then check the Windows ADK website to get the correct ADK version.
It is important to install the ADK version supported for the Windows 10 OS Build. Always check the Windows 10 OS build of your host system and then check the Windows ADK website to get the correct ADK version.

As such, if you are running Windows 10 2004 or 20H2, use the provided download link and install the Windows ADK. Else, please refer Windows ADK site to get the correct ADK installed.

I went with the default install location that is C:\Program Files (x86)\Windows Kits.

Installing Windows 10 ADK  - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK – Windows 10 OS Deployment with OSDCloud.

You get to decide if you would want Microsoft to collect usage data. Select the option that you seem suitable and click on Next.

Installing Windows 10 ADK  - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK – Windows 10 OS Deployment with OSDCloud.

Click on Accept to provide your consent for Microsoft’s License Agreement.

Installing Windows 10 ADK  - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK – Windows 10 OS Deployment with OSDCloud.

Next is when you get to choose the different features of Windows ADK. For the purpose of this blog, we will be only requiring the Deployment Tools feature and as such, I have went with that only.

Installing Windows 10 ADK  - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK – Windows 10 OS Deployment with OSDCloud.

Once the Windows ADK installation is complete, you Close the setup window.

Installing Windows 10 ADK  - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK – Windows 10 OS Deployment with OSDCloud.

Next, it’s time to download and install the WinPE add-on for Windows ADK.

Again I went with the default location. If you have used a different installation path for the Windows ADK, make sure to match it up here accordingly.

Installing Windows 10 ADK WinPE add-on - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK WinPE add-on – Windows 10 OS Deployment with OSDCloud.

After this, as we have seen with the ADK installation, you get to choose if you want to share usage data and after that, you have to accept the Microsoft Software License Agreement. Post that you come to the feature selection screen. Windows PE will be already marked for installation. Click on Install.

Installing Windows 10 ADK WinPE add-on - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK WinPE add-on – Windows 10 OS Deployment with OSDCloud.

Once the installation completes, Close the setup window.

Installing Windows 10 ADK WinPE add-on - Windows 10 OS Deployment with OSDCloud.
Installing Windows 10 ADK WinPE add-on – Windows 10 OS Deployment with OSDCloud.

OSDCloud: Install OSD PS Module and first create a WinPE template

On the same system, start Powershell with Admin rights and first install the OSD PS module.

Install-Module -Name OSD -Force

Next run the below function call to create a WinPE template

New-OSDCloud.template -Verbose

This function as documented in David’s notes creates a more refined copy of the ADK’s WinPE and saves it in $env:ProgramData\OSDCloud.

Creating WinPE template - Windows 10 OS Deployment with OSDCloud.
Creating WinPE template – Windows 10 OS Deployment with OSDCloud.

Though not required by default, there are additional parameters that you can pass along with this function call. Check the function documentation for more info.

This is how the folder structure of the created WinPE template looks like

WinPE template folder structure on local disk.
WinPE template folder structure on local disk.

OSDCloud introduces the concept of Universal WinPE. You can find the WinPE image in the path C:\ProgramData\OSDCloud\Media\sources\boot.wim

WinPE image location on local disk - This is the mostly the ADK's WinPE image to which OSDCloud will add further configurations.
WinPE image location on local disk – This is the mostly the ADK’s WinPE image to which OSDCloud will add further configurations.

OSDCloud: Retrieve Windows Autopilot profile and add it to the WinPE template

This is the step where you have to get the Autopilot profile configured in your tenant as a JSON file for offline use. This is similar to Autopilot for existing devices.

If you do not have the required modules installed already, install them

Install-Module -Name AzureAD -Force
Install-Module -Name WindowsAutopilotIntune -Force
Install-Module -Name Microsoft.Graph.Intune -Force 

If you have them installed already, import them to the current PS session using Import-Module cmdlet.

Connect to Microsoft Graph using the Connect-MSGraph cmdlet.

A sign-in window is displayed for an interactive auth session. Once you have successfully signed in, you will get to see the UPN used for sign-in and the connected TenantId in the PS window.
Retrieve Autopilot profile configuration as JSON for offline use - Windows 10 OS Deployment with OSDCloud.
Retrieve Autopilot profile configuration as JSON for offline use – Windows 10 OS Deployment with OSDCloud.

You can now easily retrieve Autopilot profiles configured in your tenant. If there is only a single Autopilot profile configured, then you can use the below command

Get-AutopilotProfile | ConvertTo-AutopilotConfigurationJSON | Out-File "<$Path\AutopilotProfile.json>" -Encoding ASCII

However, if you have multiple Autopilot profiles configured in the tenant, you would need to use filtering to retrieve any particular profile. For this, you can use the below command

Get-AutopilotProfile | Where-Object DisplayName -eq "<Autopilot_Profile_Name" | ConvertTo-AutopilotConfigurationJSON | Out-File "<$Path\AutopilotProfile.json>" -Encoding ASCII

Either case, the $Path variable points to C:\ProgramData\OSDCloud\AutoPilot\Profiles

You will now have the Autopilot profile (JSON) added to the OSD WinPE template. Note that you can have multiple Autopilot profiles added as shown below.

Retrieve Autopilot profile configuration as JSON for offline use - Windows 10 OS Deployment with OSDCloud.
Retrieve Autopilot profile configuration as JSON for offline use – Windows 10 OS Deployment with OSDCloud.

OSDCloud: Create OSD Workspace

This step is basically creating a live WinPE image using the WinPE template we have. If you have not created a template first using the New-OSDCloud.template, one will be created as mentioned in the documentation of the New-OSDCloud.workspace function.

Run the below function call as below to create a new OSD Workspace.

New-OSDCloud.workspace -WorkspacePath <Path>
Create an OSDWorkspace - Creating the live WinPE image from the WinPE template created earlier.
Create an OSDWorkspace – Creating the live WinPE image from the WinPE template created earlier.

The OSD Workspace is an exact replica of the OSD template.

The created OSDWorkspace folder structure is an exact replica of the WinPE template.
The created OSDWorkspace folder structure is an exact replica of the WinPE template.

OSDCloud: Add DriverPacks to the WinPE

Currently OSDCloud can natively pull WinPE DriverPacks from the cloud for Dell, HP, VMWare, and Nutanix, and add those to the WinPE image using the command as below

Edit-OSDCloud.winpe -CloudDriver <Dell, HP, Nutanix, Vmware>

Going through the documentation, OSDCloud support for Lenovo DriverPacks should also be available with the next release of OSDCloud.

However, if you have WinPE drivers obtained from vendor(s), you can add them to the OSDCloud WinPE WIM as well using the command as below

Edit-OSDCloud.winpe -DriverPath "<Path_to_WinPE_Drivers"

OSDCloud: Create ISO for the WinPE

If you are done with configuring the WinPE image, you can finalize your current OSD Workspace (WinPE WIM) to create a bootable ISO by using the command below

New-OSDCloud.iso

This command creates two bootable ISO for your current OSD Workspace (WinPE WIM).

New-OSDCloud.iso creates two bootable ISO for the WinPE WIM.
New-OSDCloud.iso creates two bootable ISO for the WinPE WIM.

When booting with the

  • OSDCloud.iso – it requires you to press any key to start booting to WinPE and in WinPE, it will start PowerShell automatically for you to use OSDCloud.
Booting to OSDCloud WinPE.
Booting to OSDCloud WinPE.
  • OSDCloud_NoPrompt.iso – This is the automated version and does not require any user interactions. It will directly boot to WinPE and take you to the PowerShell prompt in the booted WinPE to start using OSDCloud.
Booting to OSDCloud WinPE.
Booting to OSDCloud WinPE.

From here on, you can use the OSDCloud to deploy the Windows 10 image of your choice pulled directly from the internet to the system, provision the device with Windows Autopilot and let Intune take care of the rest.

Need to prepare a bootable USB with the complete OS package for offline deployment scenarios?  
You get that option as well, with the New-OSDCloud.usb and Save-OSDCloud.usb functions of OSDCloud.

OSDCloud: Device provisioning experience

Here I am trying this on a Hyper-V VM, setting it to boot using the OSDCloud.iso to boot to WinPE.

Trying Windows 10 OS Deployment with OSDCloud on a Hyper-V VM.
Trying Windows 10 OS Deployment with OSDCloud on a Hyper-V VM.

Once booted to WinPE, it will automatically launch PowerShell for you.

Booting to the OSDCloud prepared WinPE inside the VM. PowerShell is automatically started once in WinPE for you to start using OSDCloud.
Booting to the OSDCloud prepared WinPE inside the VM. PowerShell is automatically started once in WinPE for you to start using OSDCloud.

You can change the display resolution to match your screen resolution if you wish to using the below command.

Set-DisRes <screen_resolution_width>

To start with OSDCloud OS deployment, you need to first install the OSD PS module since it is not added to the OSDCloud WinPE. This is to ensure you always start with the latest version of OSD.

Install-Module -Name OSD -Force

Once the module is installed, it’s now time to start the OS Deployment process with OSDCloud.

Start-OSDCloud -Screenshot
The use of the -Screenshot parameter helps to capture screenshots of the OSD process that can be used for documentation purposes later and it is saved to the path C:\OSDCloud\ScreenPNG which can be accessed post device setup.
Install OSD module in WinPE since it is not added to the WinPE WIM when creating it. This ensures you always start with the latest version of OSD. Start-OSDCloud is the function that you would make to start the Windows 10 OS Deployment process.
Install OSD module in WinPE since it is not added to the WinPE WIM when creating it. This ensures you always start with the latest version of OSD. Start-OSDCloud is the function that you would make to start the Windows 10 OS Deployment process.

The Start-OSDCloud function begins by checking the Internet connection. Once the connection test is passed, it will present you with the list of OSBuild to choose from.

Start-OSDCloud - Choose OSBuild.
Start-OSDCloud – Choose OSBuild.

After OSBuild, you get to choose the OS SKU via the OSEdition parameter.

Start-OSDCloud - Choose OSEdition. (OS SKU)
Start-OSDCloud – Choose OSEdition. (OS SKU)

After OS SKU, it’s now time to choose the type of license via the OSLicense parameter.

If your device has an embedded OEM key (devices that comes pre-installed with Windows 10), select the Retail option. However, for the device, if the OEM installed Windows 10 SKU does not match with what you are deploying (OEM installed was HOME SKU and you are deploying PRO or Enterprise SKU), then you would need to choose the Volume option. It would later get activated via the Volume License activation method you have in your environment, like KMS.
Start-OSDCloud - Choose OS Licensing type.
Start-OSDCloud – Choose OS Licensing type.

Next is time to choose the OS Language

Start-OSDCloud - Choose OS Language.
Start-OSDCloud – Choose OS Language.

If you wish, you can also start OSDCloud by passing values for these parameters initially in format as below

Start-OSDCloud -OSBuild <Windows 10 Version> -OSEdition <OS SKU> -OSLanguage <OS Language> -Screenshot (opt)

Start-OSDCloud -OSBuild 21H1 -OSEdition Pro -OSLanguage en-us - Screenshot

It then shows you the details of the OS image that you have selected till this, which will be downloaded from Windows Update as an ESD file. Then it tries to get the drivers that you have added to the WinPE image and get them applied. However, there are exceptions for 32-bit EXE drivers which cannot be expanded in the WinPE. (HP and Lenovo drivers!)

Read here to know more about how OSDCloud handles DriverPacks during the Windows setup.
OSDCloud starts the OS Deploy process. Supported DriverPacks are downloaded and expanded to local storage. However, 32-bit EXE drivers are not applied during WInPE but are instead marked for unattended installation to be handled by OS kernel later on.
OSDCloud starts the OS Deploy process. Supported DriverPacks are downloaded and expanded to local storage. However, 32-bit EXE drivers are not applied during WInPE but are instead marked for unattended installation to be handled by OS kernel later on.

Then you finally get to the point where it will ask you to select the autopilot profile to use for the deployment. It will show you the list of all autopilot profiles that you have added to the WinPE image.

OSDCloud applies the autopilot profile to the OS deployment you choose from the list of Autopilot profiles that was added to the WinPE.
OSDCloud applies the autopilot profile to the OS deployment you choose from the list of Autopilot profiles that was added to the WinPE.

Next it will ask for consent to clear disk.

If you have multiple physical disks in the system, Get-LocalDisk retrieves each and lists them here. Clear-Disk function then asks for consent to clear disk content for each item listed. In such scenario, you only need to consent for the Disk item that you would be preparing as your OS drive.
OSDCloud cleans local disk as part of the OSD process.
OSDCloud cleans local disk as part of the OSD process.

The process then prepares the cleaned RAW disk obtained from the above for OS installation. It does the standard UEFI GPT partitioning that we see during a manual Windows 10 installation.

The Power Plan of the device is set to High Performance, and finally, the process starts retrieving the Windows 10 Feature Update Image (ESD file) to a temporary location on the local disk. (C:\OSDCloud\Temp)

OSDCloud prepares clead loacl disk to support OS deployment, set the device Power Plan to High Perfromnace mode and starts retrieveing the Windows 10 OS Feature Update as per the chosen OSbuild, OSEdition, OSLanguage. The ESD file is saved to local Temp location.
OSDCloud prepares clead loacl disk to support OS deployment, set the device Power Plan to High Perfromnace mode and starts retrieveing the Windows 10 OS Feature Update as per the chosen OSbuild, OSEdition, OSLanguage. The ESD file is saved to local Temp location.

Once the download is complete, the downloaded ESD file is expanded to the local storage, and boot points are set to boot from the local disk on the next system startup.

As mentioned earlier, 32-bit EXE drivers (HP and Lenovo) cannot be applied during WinPE and as such are marked for unattended installation to be handled during OS Setup later.

OSDCloud expands the downloaded Windows 10 OS image and sets the boot points to make the device boot from the local disk on the next system startup. Drivers that could not be applied in WinPE (32-bit EXE drivers) are marked for unattended install.
OSDCloud expands the downloaded Windows 10 OS image and sets the boot points to make the device boot from the local disk on the next system startup. Drivers that could not be applied in WinPE (32-bit EXE drivers) are marked for unattended install.

The OSD module and PS modules for Windows Autopilot are also saved to the local disk for ready availability on OS boot.

The OSD module and PS modules related to Windows Autopilot are saved to local disk for easy availability on the later stages, if needed.
The OSD module and PS modules related to Windows Autopilot are saved to local disk for easy availability on the later stages, if needed.

If you have used the Start-OSDCloud with -Screenshot parameter, then it shows you the path where you will find all the screenshots captured till this. (C:\OSDCloud\ScreenPNG)

For me, the OSDCloud OS deployment run completed in 13 minutes 11 seconds. As you can understand, this time performance is completely dependent on the internet bandwidth you have at your disposal.

Once completed, you need to Exit the PowerShell window and Quit the booted WinPE session.

To quit the PowerShell session as well as quit WinPE, type exit and press in enter, first on the PowerShell prompt and then on the WinPE CMD prompt.
Once OSDCloud completes the OS deployment process, exit the PowerShell and WinPE to let the system boot from the local disk for OS kernel to boot up and continue with the OS setup.
Once OSDCloud completes the OS deployment process, exit the PowerShell and WinPE to let the system boot from the local disk for OS kernel to boot up and continue with the OS setup.

As you quit WinPE, the system will restart. Post restart, it’s the Windows 10 OS kernel that boots up from the local disk and continues with the OS setup. The drivers that were marked for unattended installation by OSDCloud get installed and finally, after some time, you should see the familiar Windows OOBE (CloudExperinceHost) screen appearing.

Post restart, as the Windows 10 OS kernel boots up from the local disk and continues with the OS setup, the drivers that were marked for unattended install gets installed and after some time, you are presented with the known Windows 10 OOBE screen. Note that Autopilot configurations are added to the OS as part of the OS deployment process, as such you get the same streamlined device setup experience.
Post restart, as the Windows 10 OS kernel boots up from the local disk and continues with the OS setup, the drivers that were marked for unattended install gets installed and after some time, you are presented with the known Windows 10 OOBE screen. Note that Autopilot configurations are added to the OS as part of the OS deployment process, as such you get the same streamlined device setup experience.

It took another 15-20 mins for me during the Autopilot provisioning. Thus in total, I got a device ready to use for work from a bare-metal state in about 33-35 mins with OSDCloud.

OSDCloud: Management experience with Intune

Note that at this point, the device is unknown to Intune, and there is also no pre-created Azure AD device object for this device having the ZTDID stamping for Autopilot.

This is obvious as the device is not actually registered with the Windows Autopilot service, but is able to mimic an Autopilot setup experience because of the Autopilot configurations added to it (offline injected) as part of the OS deployment process.
Since this method of offline Autopilot does not actually register the device to Autopilot service, there is no pre-created Azure AD device object that you get for a registered device. As such this device is not present in any of the dynamic device groups that you may have prepared for your autopilot device groups. As such policies targeted to those groups are not going to get applied to the initial setup. User-targeted policies though get applied.
Since this method of offline Autopilot does not actually register the device to Autopilot service, there is no pre-created Azure AD device object that you get for a registered device. As such this device is not present in any of the dynamic device groups that you may have prepared for your autopilot device groups. As such policies targeted to those groups are not going to get applied to the initial setup. User-targeted policies though get applied.

As such, though you will still encounter the standard ESP during device setup (if you have ESP configured for all users and all devices), unless you have used deployment type as All devices for all the policies (config profiles, apps, etc.) which should not be the case ideally, none of your policies targeted to (any) dynamic device group is going to get applied on this go. I have seen only the user-targeted policies take effect on the initial setup run.

This brings me to one failure point –

If you have set ESP to track a particular application which is deployed to a device group, you may encounter a ESP timeout since the device will never get the app which ESP is expecting to track during device setup.

Once the device provisioning completes, you will have the Intune and Azure AD device objects created for the device.

You can then go into the MEM Admin portal to create a dynamic device group for your OSDCloud provisioned devices. This can be easily done by using the EnrollmentProfileName as the cue for the dynamic group query

(device.enrollmentProfileName -eq "<OfflineAutopilotprofile-ZtdCorrelationId")

You can find the ZtdCorrelationId from the Autopilot JSON file that you retrieved during the initial steps.

To create the device dynamic group for your OSDCloud provisioned device, grab the ZtdCorrealationId from the Autopilot JSON file that you downloaded initially.
To create the device dynamic group for your OSDCloud provisioned device, grab the ZtdCorrealationId from the Autopilot JSON file that you downloaded initially.

Provided you have Convert all devices to autopilot devices set to Yes in the Autopilot profile, add this group to the Autopilot profile deployment, and Intune will automatically register the OSDCloud provisioned devices to Windows Autopilot service.

Once the device gets Autopilot registered, it will also become a member of your regular Autopilot dynamic device group that is based on the ZTDId query. Thus, you now have your OSDCloud provisioned devices as members of multiple dynamic device groups that you can use to deploy device-targeted policies.

Further, the device being registered to Autopilot enables you to trigger an Autopilot reset in the future, if there be a need 🙂

OSDCloud: The Problems Addressed and Way Forward

Traditional OS Deployment MethodOSDCloud Method
Involves maintaining a “golden image”Pulls down the Windows 10 image (Build, Edition, Language of your choice) directly from the Internet.
Involves an infrastructure.Only requires an active internet connection.
Devices remain vulnerable for a time gap till Windows Update patches the OS completely, since the “golden image” is not always the latest build.Devices are always deployed with the latest build of the Windows 10 image. (Except where you use OSDCloud the offline way.)

Even in modern managed environments, where devices are coming from OEM pre-installed with OEM OS image, the devices mostly sit idle at inventory stock rooms for a few months before being handed over to the end-user. As such when an end-user starts the device for the first time, the OS build is not the latest. The device is patched via Windows Update post provisioning, in accordance with the organization update policy. Thus there still remains a time gap for which the devices remain vulnerable.

What OSDCloud brings to the table are

  • important concepts like Universal WinPE,
  • ability to update outdated drivers out-of-box via DriverPacks,
  • deploying the latest OS build.

OSDCloud is still fairly a new product (only a few weeks old!) and David is actively working on it to add more and more features to it, adding additional device support and functionalities. It will be really interesting to see how the product grows up to be put at work, at scale.

What’s missing in OSDCloud?

From my testing experience, it is the ability to connect to a Wi-Fi network during the WinPE.

Though this is more of an incapability of the WinPE than OSDCloud itself. however, it's not completely impossible to add wireless support in WinPE. Hopefully, we might see the wireless support being added in an upcoming version of OSDCloud.

Adding wireless network support would make it a lot easier to OSDCloud a device without an Ethernet port, like most slim devices these days, which otherwise requires getting the device plugged into the ethernet cable via an adapter.

It’s Wrap Up Time

When you do not have any typical OSD infrastructure at your disposal, OSDCloud serves as an excellent choice to quickly do OS deployment to bare-metal devices.

Have any queries or feedback regarding OSDCloud? You can DM David(@SeguraOSD) on Twitter. He is very active and quite fast to reply!