I used to tolerate imaging. WDS, MDT, SCCM OSD, task sequences that felt like a hostage negotiation — all of it. It worked, sort of, if your definition of worked includes praying that drivers, domain join, software deployment, and user state all behaved in the exact same five-minute window.

Modern provisioning is better. Not because Microsoft made it magical. It isn’t. It’s better because the whole model changes: identity first, policy first, compliance first, then apps and access. That is a much saner way to build a Windows estate.

Related source repos:

1. The problem with imaging

Classic imaging has a few recurring sins:

  • You spend time building a “gold image” that is obsolete the minute you finish it.
  • Driver injection becomes a special religion.
  • OOBE is not really OOBE. It’s a pile of scripts pretending to be one.
  • The machine is often useful only after someone on the IT side has already touched it three or four times.

The deeper problem is that imaging is artifact-centered. Autopilot is identity-centered.

That matters because the real job is not “build a perfect image.” The real job is “make a device trustworthy, compliant, and ready for a user with as little drama as possible.”

2. Prerequisites

Before I even think about shipping Autopilot, I want the boring pieces squared away:

  • Microsoft Entra ID P1 or equivalent licensing
  • Microsoft Intune licensing
  • MDM authority set correctly
  • Devices registered in Autopilot
  • A clean separation between pilot, pre-production, and production device groups
  • Conditional Access ready to consume compliance signals

Microsoft’s own Zero Trust guidance is basically the same thesis: require healthy and compliant devices before access is granted. That is the part that actually matters.

Useful references:

3. Autopilot deployment profile setup

This is where people usually overcomplicate things.

I think about Autopilot in three modes:

Mode Best for Why I use it
User-driven Standard employee laptops and desktops User signs in, policy does the rest, and I don’t have to babysit the hardware
Self-deploying Kiosks, shared devices, and very controlled scenarios No user affinity nonsense; the device provisions itself
Pre-provisioning / white glove When I want IT to stage the device before handoff Great for reducing first-login pain and letting me verify apps before the user gets it

Microsoft documents the same general split, and they’re right for once. I also like the fact that pre-provisioning and self-deploying are explicitly profile-driven instead of being some weird side quest.

If I had to keep this brutally simple: for normal staff devices, I want user-driven. For shared devices, I want self-deploying. For executive machines or anything that needs to be staged cleanly before handoff, I use pre-provisioning.

Docs:

4. Getting the hardware hash into Autopilot

This part still trips people up because it feels like something that should be automatic and, naturally, isn’t.

Manual collection

For a one-off device, I still like the old reliable route:

Install-Script -Name Get-WindowsAutopilotInfo
Get-WindowsAutopilotInfo.ps1 -OutputFile .\AutopilotHWID.csv

Microsoft’s guidance is straightforward here: the script gives you the hardware hash and serial number, and the CSV can be imported into Autopilot.

Bulk import with Graph

For real deployments, I prefer to stop pretending I’ll only ever touch one device at a time. Bulk import is cleaner.

Connect-MgGraph -Scopes "DeviceManagementServiceConfig.ReadWrite.All"

$devices = Import-Csv .\AutopilotHWID.csv

foreach ($device in $devices) {
    New-MgDeviceManagementImportedWindowsAutopilotDeviceIdentity -BodyParameter @{
        serialNumber      = $device.'Device Serial Number'
        productKey         = $device.'Windows Product ID'
        importId           = [guid]::NewGuid().Guid
        hardwareIdentifier = [Convert]::FromBase64String($device.'Hardware Hash')
        groupTag           = 'Corp'
    }
}

If you want to verify what came in, the Graph cmdlets are there too:

Get-MgDeviceManagementWindowsAutopilotDeviceIdentity

Relevant docs:

5. Entra ID join vs hybrid join

This is the decision point where a lot of environments get stuck in the past.

Join type I use it when I avoid it when
Entra ID join The device can live cloud-native and the app stack doesn’t need on-prem Kerberos dependency The only reason to choose it is fear of changing the old model
Hybrid join I still have an unavoidable legacy dependency on domain auth, old line-of-business behavior, or a server-side control plane that refuses to die I can honestly move away from it without breaking production

My bias is simple: if I can make the device Entra ID joined and keep access controlled with Intune + Conditional Access, that’s the cleaner design.

Hybrid join still exists because reality is annoying. Some environments have old apps, old auth assumptions, and old vendors who think Kerberos is a personality trait. Fine. Use hybrid when you have to. Just don’t pretend it’s modern because it has the word cloud somewhere in the documentation.

6. Intune configuration profiles and compliance

Autopilot without policy is just a nicer way to log into a machine that still isn’t managed.

What I want in place:

  • Baseline configuration profiles
  • BitLocker enforcement
  • Defender or endpoint protection settings
  • LAPS for local admin recovery
  • Wi-Fi / VPN profiles where needed
  • Compliance policies that map to actual access decisions

The key idea is this: compliance should not be decorative. It should drive Conditional Access.

If a device is compliant, it gets access. If it isn’t, it doesn’t. That is the whole point of Zero Trust. Not vibes. Not checkboxes. Access.

References:

7. App deployment

This is where a lot of teams still carry dead habits around like an old tool belt.

If the app is a Windows app and it matters, I package it as Win32. That is the sane route now. Microsoft has made it pretty clear that Win32 is the path forward, and the old Microsoft Store for Business world is dead enough that we can stop talking about it like it’s coming back.

What I usually do:

  • Package the app with IntuneWinAppUtil.exe
  • Define proper install and uninstall commands
  • Use detection rules that actually prove the app is there
  • Mark the app Required when it’s critical to the user’s first day
  • Use Company Portal for optional user-driven installs

Example packaging command:

.\IntuneWinAppUtil.exe -c .\Source -s Install.ps1 -o .\Output -q

The important part is not the tool. The important part is the discipline:

  • silent install support
  • reliable detection
  • dependency ordering
  • no dumb GUI prompts during provisioning

Relevant docs:

8. OOBE walkthrough

Here’s the part the end user actually sees.

On a good day:

  1. They unbox the device.
  2. They connect to Wi-Fi or Ethernet.
  3. They sign in once with their Entra ID account.
  4. Autopilot recognizes the device and assigns the right profile.
  5. ESP holds the desktop until the required policies and apps are in place.
  6. The machine lands on the desktop already branded, compliant, and mostly boring.

That last word is the goal. Boring is good. Boring means I don’t have to get involved.

I don’t have a trustworthy fleet timing benchmark from your environment, so I am not inventing one here.

[NEEDS INPUT: your usual first-login timing from a pilot Autopilot device, if you want a real-world number in this section]

9. Lessons learned and gotchas

This is where the fantasy meets the floor.

Sync is not instant

In my user provisioning work, I literally wait for sync and poll Graph because identity systems are rarely immediate. The GUI provisioning script waits 300 seconds for AD Connect sync and then polls Entra ID repeatedly until the user shows up.

That is not a random implementation detail. That is reality.

Relevant source: New User Provisioning GUI

Entra-only changes the auth game

I also have a real example of the opposite problem: a pure Entra-joined device does not magically satisfy old Windows Integrated Authentication assumptions.

From the NiceLabel 2019 troubleshooting notes:

  • Entra-only devices have no domain machine trust
  • the browser can work while the client auth flow still fails
  • whoami /groups returned nothing useful because there was no domain security context

That is the kind of thing that gets ignored until someone says, “but it works on my machine,” which is usually code for “my machine has the old join type.”

What I do not have a clean source for here

I don’t have a vault-captured Autopilot ESP timeout, VPN profile push timing failure, or driver-delivery postmortem that I trust enough to quote as fact.

[NEEDS INPUT: one real ESP timeout or driver-delivery incident from your Autopilot rollout, if you want a concrete war story here]

10. Closing

Autopilot is not just a better way to install Windows. It’s a better way to think about Windows.

Once you stop centering the image and start centering the identity, the rest of the stack makes more sense:

  • Entra ID owns the identity
  • Intune owns the policy
  • Conditional Access owns the gate
  • Win32 packaging owns the ugly legacy apps
  • Autopilot owns the first impression

And if the estate is still stuck on imaging because someone is emotionally attached to SCCM task sequences, I get it. I’ve been there. It was useful. It also belongs in the museum.

The next thing I’m watching is Autopilot device preparation. That feels like the direction this whole mess is heading, which is probably for the best.

If you want the infrastructure philosophy behind the rest of my lab, this is the repo that matters: