All Posts Automation

Building a Zero-Touch Deployment Pipeline for Windows Workstations

You just hired three people. Each one needs a laptop. Stop spending hours manually configuring every new machine — here's how to build a zero-touch pipeline with Autopilot and PowerShell.

Zero-touch deployment uses Windows Autopilot and Microsoft Intune to configure new workstations automatically — employees power on a laptop, sign in with Microsoft 365 credentials, and the device installs all applications, applies security policies, and joins the organization without IT ever touching the hardware. For businesses in Deltona and across Volusia County, this eliminates 90 minutes to 3 hours of manual setup per device and ensures every workstation is configured identically, with zero cost beyond your existing Microsoft 365 Business Premium licenses.

You just hired three people. Each one needs a laptop. So your IT person — maybe that’s you — spends a day and a half unpacking boxes, running through the Windows setup wizard, joining each machine to the domain, installing Office, Teams, the VPN client, the line-of-business app, the printer drivers, the security agent, and whatever else your environment requires. By the time the third laptop is configured, the first new hire has been sitting at an empty desk for six hours reading the employee handbook for the second time.

Zero-touch deployment is an automated provisioning method that configures Windows workstations without manual IT intervention. Using Windows Autopilot and Microsoft Intune, devices ship directly from the vendor to employees, who power them on and sign in with their Microsoft 365 credentials. The system automatically joins the device to your organization’s network, installs required applications, applies security policies, and configures settings — all without IT ever touching the hardware.

I see this problem everywhere I work in Volusia County — businesses in Deltona, Daytona Beach, Port Orange, all running into the same bottleneck. They’re growing, hiring people, buying laptops, and the provisioning process hasn’t changed since 2012. Someone sits in front of each machine clicking through wizards. It’s slow, it’s error-prone, and it doesn’t scale. The moment you hire more than two people in the same week, your IT person becomes the bottleneck for the entire onboarding process.

In this guide, I’m going to walk you through building a complete zero-touch deployment pipeline. By the end, you’ll have a system where you order a laptop from Dell or Lenovo, it ships to your employee’s home or office, they power it on, sign in, and everything they need is installed and configured automatically. No USB drives. No imaging servers. No IT person driving across town to set up a laptop at someone’s kitchen table. Let’s get into it.

The Real Cost of Manual Workstation Deployment

Before we build anything, let me quantify what manual deployment actually costs your business. I’ve tracked this across dozens of client environments, and the numbers are remarkably consistent.

A competent IT person takes between 90 minutes and three hours to fully provision a Windows workstation from scratch. That includes the Windows setup wizard, driver updates, Windows Updates (which alone can take 45 minutes of waiting), domain join, application installation, printer configuration, security policy application, and basic verification that everything works.

For a business in Ormond Beach with fifteen employees and a three-year hardware refresh cycle, that means provisioning five machines per year. At two hours per machine, that’s ten hours of skilled IT labor. Not terrible. But those ten hours don’t happen spread evenly across the year — they happen in bursts. You buy five laptops on the same purchase order because your budget approved it, and suddenly your IT person is underwater for two days doing nothing but setup work.

The hidden costs are worse than the labor. Manual provisioning introduces inconsistency. Machine number one gets the latest security agent. Machine number four gets an older version because IT forgot which installer they used for machine number one. Machine number two has the VPN configured for split tunneling. Machine number five doesn’t because the instructions weren’t written down and the IT person was rushing to finish before a meeting.

These inconsistencies create support tickets for months. “Why does my laptop connect to the VPN differently than Sarah’s?” “Why can’t I print to the second-floor printer?” “Why is my OneDrive not syncing?” Each ticket costs another twenty minutes of troubleshooting time, and the root cause is always the same: human variation during manual setup.

Zero-touch deployment eliminates both problems. The labor drops to near zero — you register a hardware hash, assign a deployment profile, and walk away. The consistency becomes perfect — every device gets the exact same configuration, every time, because a computer is applying it instead of a human remembering steps.

What Zero-Touch Deployment Actually Means

Let me be precise about what we’re building, because “zero-touch” gets thrown around loosely and it means different things in different contexts.

True zero-touch deployment means IT never physically handles the device. The workflow looks like this: you order a laptop from your hardware vendor, you provide the vendor with your Autopilot enrollment information, the vendor ships the laptop directly to your employee, the employee opens the box, powers on the laptop, connects to Wi-Fi, signs in with their Microsoft 365 credentials, and the device configures itself completely. IT’s involvement is limited to the initial pipeline setup and ongoing policy management — both of which happen from a web browser, not from sitting in front of a laptop.

This is different from “lite-touch” deployment, which still requires IT to boot the device from a USB drive or network PXE server and kick off an imaging process. Lite-touch is faster than fully manual, but it still requires physical access to the hardware. It still requires IT infrastructure on-premises — an SCCM server, a deployment share, a network that supports PXE boot. Zero-touch moves all of that to the cloud.

The technology stack that makes zero-touch possible includes Windows Autopilot, which is the cloud service that identifies registered devices and triggers the provisioning process; Microsoft Intune, which handles the actual device management, policy application, and app deployment; and Microsoft Entra ID (what used to be called Azure Active Directory), which provides the identity and directory services. If you’re already running Microsoft 365 Business Premium, you have all three of these included in your licensing. You’re paying for zero-touch capability whether you use it or not.

Prerequisites: What You Need Before You Start

Before you configure a single setting, make sure you have the following in place. Missing any of these will cause your deployment to fail in confusing ways, and I’d rather you find out now than when a new employee is sitting at home staring at a laptop that won’t finish setup.

Microsoft 365 Business Premium or Enterprise licenses. These include Intune and Entra ID P1. If you’re on Microsoft 365 Business Basic or Standard, you don’t have Intune, and Autopilot won’t work without it. You can add Intune as a standalone license, but at that point the price difference to Business Premium is usually negligible.

A hardware vendor that supports Autopilot registration. Dell, HP, Lenovo, and Microsoft Surface all support shipping devices pre-registered with Autopilot. This means the vendor includes the hardware hash in their system and associates the device with your tenant before it ships. If your vendor doesn’t support this, you’ll need to collect hardware hashes yourself — which I’ll cover, but it adds a step.

An Entra ID tenant with users configured. Your employees need to exist in Entra ID before their devices arrive. If you’re already using Microsoft 365 for email and Office apps, this is likely already done. If you’re migrating from on-premises Active Directory, make sure Entra Connect sync is working and user accounts are appearing in the cloud.

A clear picture of what your standard workstation looks like. Before you automate anything, write down every application, every configuration setting, every policy that goes on a standard employee laptop. If you can’t articulate what a “properly configured workstation” looks like, automation won’t help — you’ll just automate confusion faster.

Step 1: Configure Your Entra ID and Intune Environment

Start in the Microsoft Intune admin center at intune.microsoft.com. If you haven’t been here before, it can feel overwhelming — the navigation panel has more options than a Cheesecake Factory menu. For zero-touch deployment, you need three areas: Devices, Apps, and Endpoint Security.

First, verify automatic enrollment is enabled. Navigate to Devices > Enrollment > Automatic Enrollment. Set the MDM user scope to “All” or select a specific Entra ID group containing the users who should receive Autopilot-provisioned devices. This setting tells Intune to automatically enroll any device that joins Entra ID, which is what triggers the full provisioning process during Autopilot.

Next, create a device group that Autopilot will use. Go to the Entra admin center, create a new security group called something like “Autopilot Devices,” and set the membership type to Dynamic Device. Use this dynamic membership rule:

(device.devicePhysicalIDs -any (_ -startsWith "[ZTDId]"))

This rule automatically adds any device registered with Autopilot to the group. Every policy, app, and configuration you assign to this group will apply to every device that goes through your zero-touch pipeline. One group to manage them all.

Step 2: Register Devices with Windows Autopilot

This is where the hardware hash comes in. Every Windows device has a unique hardware hash — a cryptographic fingerprint generated from the device’s hardware components. When you register this hash with Autopilot, you’re telling Microsoft’s cloud service: “When this specific device connects to the internet during initial setup, it belongs to my organization. Apply my deployment profile.”

The easiest path is having your hardware vendor register devices at the factory. Dell, HP, and Lenovo all offer this. You provide your Intune tenant information to your vendor rep, and they associate each device’s hash with your tenant before shipping. When the device arrives at your employee’s location, it’s already registered. This is the true “zero-touch” path.

If your vendor doesn’t support factory registration — or if you’re deploying existing machines that were purchased before you set up Autopilot — you’ll need to collect hashes manually. Here’s the PowerShell approach:

# Run this on each device you want to register
# Requires admin PowerShell and internet connection

# Install the collection module
Install-Script -Name Get-WindowsAutoPilotInfo -Force

# Option 1: Upload directly to Intune (interactive auth)
Get-WindowsAutoPilotInfo -Online

# Option 2: Export to CSV for bulk upload
Get-WindowsAutoPilotInfo -OutputFile "C:\AutopilotHashes\$env:COMPUTERNAME.csv"

The -Online flag is the fastest option for individual devices. It authenticates against your Intune tenant and uploads the hash directly. You’ll see a browser window pop up asking for admin credentials. Sign in, and the device is registered within a few minutes.

For bulk scenarios — say you have twenty existing machines in your DeLand office that need to be registered — export to CSV and then upload them all at once through the Intune admin center under Devices > Enrollment > Windows Autopilot devices > Import. For a deeper look at this topic, see our guide on CI/CD for Non-Software Companies: Automating Your Infrastructure Deployments.

For larger operations, I use a Python script that handles bulk registration through the Microsoft Graph API. This is particularly useful if you’re an MSP managing multiple tenants:

#!/usr/bin/env python3
"""
bulk_autopilot_register.py
Registers devices with Windows Autopilot via Microsoft Graph API.
Reads hardware hashes from CSV files exported by Get-WindowsAutoPilotInfo.

Requirements:
    pip install msal requests
"""







from pathlib import Path

# --- Configuration ---
# Store these in environment variables for production use
TENANT_ID = "your-tenant-id"
CLIENT_ID = "your-app-registration-client-id"
CLIENT_SECRET = "your-client-secret"
GRAPH_URL = "https://graph.microsoft.com/beta"


def get_access_token():
    """Authenticate with Microsoft Graph using app credentials."""
    authority = f"https://login.microsoftonline.com/{TENANT_ID}"
    app = msal.ConfidentialClientApplication(
        CLIENT_ID,
        authority=authority,
        client_credential=CLIENT_SECRET,
    )
    result = app.acquire_token_for_client(
        scopes=["https://graph.microsoft.com/.default"]
    )
    if "access_token" not in result:
        print(f"Authentication failed: {result.get('error_description')}")
        sys.exit(1)
    return result["access_token"]


def register_device(token, serial_number, hardware_hash, group_tag=""):
    """Register a single device with Autopilot."""
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }
    payload = {
        "@odata.type": (
            "#microsoft.graph.importedWindowsAutopilotDeviceIdentity"
        ),
        "serialNumber": serial_number,
        "hardwareIdentifier": hardware_hash,
        "groupTag": group_tag,
    }
    response = requests.post(
        f"{GRAPH_URL}/deviceManagement/"
        f"importedWindowsAutopilotDeviceIdentities",
        headers=headers,
        json=payload,
    )
    return response.status_code, response.json()


def bulk_register_from_csv(csv_path, group_tag=""):
    """Read a CSV of hardware hashes and register each device."""
    token = get_access_token()
    csv_file = Path(csv_path)

    if not csv_file.exists():
        print(f"CSV file not found: {csv_path}")
        sys.exit(1)

    results = {"success": 0, "failed": 0, "errors": []}

    with open(csv_file, "r") as f:
        reader = csv.DictReader(f)
        for row in reader:
            serial = row.get("Device Serial Number", "").strip()
            hw_hash = row.get("Hardware Hash", "").strip()

            if not serial or not hw_hash:
                print(f"Skipping row — missing serial or hash")
                results["failed"] += 1
                continue

            status, response = register_device(
                token, serial, hw_hash, group_tag
            )

            if status in (200, 201):
                print(f"  Registered: {serial}")
                results["success"] += 1
            else:
                error_msg = response.get("error", {}).get("message", "Unknown")
                print(f"  Failed: {serial} — {error_msg}")
                results["failed"] += 1
                results["errors"].append({"serial": serial, "error": error_msg})

            time.sleep(1)  # Respect Graph API rate limits

    print(f"\nResults: {results['success']} registered, "
          f"{results['failed']} failed")
    return results


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python bulk_autopilot_register.py <csv_path> [group_tag]")
        sys.exit(1)

    csv_path = sys.argv[1]
    tag = sys.argv[2] if len(sys.argv) > 2 else ""
    bulk_register_from_csv(csv_path, tag)

Let me walk through what this script does. The get_access_token function authenticates your application against Microsoft Entra ID using the MSAL library. This is an app-to-app authentication flow — no user interaction required — which makes it suitable for automation pipelines and scheduled tasks. The register_device function takes a serial number and hardware hash and POSTs them to the Graph API’s Autopilot device identity endpoint. The bulk_register_from_csv function reads a CSV file (the same format that Get-WindowsAutoPilotInfo exports) and registers each device one at a time with a one-second delay between requests to respect Microsoft’s rate limiting.

For the app registration credentials, create an app registration in Entra ID with the DeviceManagementServiceConfig.ReadWrite.All application permission. This grants the script permission to manage Autopilot device registrations without user interaction.

Step 3: Build Your Deployment Profile

The deployment profile tells Autopilot exactly what the user should see (and not see) during the out-of-box experience. This is where you customize the setup flow.

In the Intune admin center, go to Devices > Windows > Windows Enrollment > Deployment Profiles and create a new profile. Here’s the configuration I use for most small business clients:

{
  "displayName": "Standard Workstation — Zero Touch",
  "description": "Default deployment profile for employee workstations",
  "deviceType": "windowsPc",
  "extractHardwareHash": true,
  "outOfBoxExperienceSettings": {
    "hidePrivacySettings": true,
    "hideEULA": true,
    "userType": "standard",
    "skipKeyboardSelectionPage": true,
    "hideEscapeLink": true,
    "deviceUsageType": "singleUser"
  },
  "enrollmentStatusScreenSettings": {
    "hideInstallationProgress": false,
    "blockDeviceSetupRetryByUser": false,
    "allowDeviceResetOnInstallFailure": true,
    "installProgressTimeoutInMinutes": 60
  }
}

A few deliberate decisions here. The userType is set to “standard,” not “administrator.” Your employees should not have local admin rights on their workstations. This is a security decision that zero-touch deployment makes easy to enforce — when IT is manually setting up machines, there’s always pressure to make the user an admin “just to avoid future tickets.” Autopilot removes that temptation. We cover this in more detail in What Does a Cloud Migration Actually Look Like? (Timeline + Cost Breakdown).

The hideEscapeLink setting prevents the user from bypassing the Autopilot process. Without this, a curious employee can escape the setup flow and end up with a partially configured machine that isn’t enrolled in Intune. Then you have a rogue device on your network that doesn’t receive security policies. I’ve seen this happen in New Smyrna Beach — an employee thought they were being helpful by “speeding up the setup” and ended up with a laptop that IT couldn’t manage remotely.

The enrollment status page is set to show progress but allow reset on failure. This means the employee can see what’s happening during setup — “Installing Microsoft 365… Installing VPN client…” — and if something fails, they can reset the device and try again. The sixty-minute timeout gives even large application packages time to download and install on slower connections.

Step 4: Create Your Post-Provisioning PowerShell Scripts

Autopilot handles the big pieces — Entra ID join, Intune enrollment, app installation. But every environment has configuration details that don’t fit neatly into Intune’s built-in policies. Maybe you need to set a specific registry key for your line-of-business application. Maybe you need to configure a mapped drive. Maybe you need to create a local folder structure that your legacy app expects.

This is where PowerShell provisioning scripts come in. Intune can deploy PowerShell scripts to devices during or after the Autopilot process. These scripts run in the SYSTEM context (no user is signed in when they execute during OOBE), so they have full admin access.

Here’s a post-provisioning script I use as a template. It handles the configuration tasks that Intune policies don’t cover:

<#
.SYNOPSIS
    Post-provisioning configuration for Autopilot-deployed workstations.
.DESCRIPTION
    Runs during Intune enrollment to configure settings that
    Intune policies and app deployments don't cover natively.
    Executes in SYSTEM context during OOBE.
.NOTES
    Deploy via Intune: Devices > Scripts and remediations > Platform scripts
    Run as: System | 64-bit PowerShell host | Do not enforce signature check
#>

param(
    [string]$LogDir = "C:\ProgramData\AutopilotLogs"
)

# --- Logging setup ---
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
$logFile = Join-Path $LogDir "post-provision-$(Get-Date -Format 'yyyyMMdd-HHmmss').log"

function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $entry = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [$Level] $Message"
    Add-Content -Path $logFile -Value $entry
}

Write-Log "Post-provisioning script started"
Write-Log "Computer: $env:COMPUTERNAME"
Write-Log "OS Build: $((Get-CimInstance Win32_OperatingSystem).BuildNumber)"

# --- Configure power settings for first-boot reliability ---
Write-Log "Configuring power settings to prevent sleep during setup"
powercfg /change standby-timeout-ac 0
powercfg /change hibernate-timeout-ac 0
powercfg /change monitor-timeout-ac 30

# --- Create standard folder structure ---
$folders = @(
    "C:\CompanyData",
    "C:\CompanyData\Templates",
    "C:\CompanyData\SharedTools"
)
foreach ($folder in $folders) {
    if (-not (Test-Path $folder)) {
        New-Item -ItemType Directory -Path $folder -Force | Out-Null
        Write-Log "Created folder: $folder"
    }
}

# --- Set required registry keys ---
# Example: Configure LOB app connection string
$regPath = "HKLM:\SOFTWARE\CompanyApp"
if (-not (Test-Path $regPath)) {
    New-Item -Path $regPath -Force | Out-Null
}
Set-ItemProperty -Path $regPath -Name "ServerEndpoint" `
    -Value "https://app.company.com/api" -Type String
Set-ItemProperty -Path $regPath -Name "AutoUpdate" `
    -Value 1 -Type DWord
Write-Log "Registry keys configured for LOB application"

# --- Configure Windows Defender exclusions ---
# Necessary for LOB apps that trigger false positives
$defenderExclusions = @(
    "C:\CompanyData",
    "C:\Program Files\CompanyApp"
)
foreach ($exclusion in $defenderExclusions) {
    Add-MpPreference -ExclusionPath $exclusion -ErrorAction SilentlyContinue
    Write-Log "Added Defender exclusion: $exclusion"
}

# --- Disable first-run experience for Edge ---
$edgeRegPath = "HKLM:\SOFTWARE\Policies\Microsoft\Edge"
if (-not (Test-Path $edgeRegPath)) {
    New-Item -Path $edgeRegPath -Force | Out-Null
}
Set-ItemProperty -Path $edgeRegPath -Name "HideFirstRunExperience" `
    -Value 1 -Type DWord
Write-Log "Edge first-run experience disabled"

# --- Set default file associations ---
# Deploy a default associations XML if it exists
$assocXml = "C:\CompanyData\Templates\DefaultAssociations.xml"
if (Test-Path $assocXml) {
    dism /online /Import-DefaultAppAssociations:$assocXml
    Write-Log "Default file associations applied"
}

# --- Configure time zone (Florida, Eastern) ---
Set-TimeZone -Id "Eastern Standard Time" -ErrorAction SilentlyContinue
Write-Log "Time zone set to Eastern Standard Time"

# --- Final status ---
Write-Log "Post-provisioning script completed successfully"
Write-Log "Total execution time: script finished at $(Get-Date -Format 'HH:mm:ss')"

# Return success for Intune reporting
exit 0

Every line in this script is deliberate. The power settings prevent the laptop from going to sleep during the provisioning process — I’ve seen deployments fail in Deltona because a laptop went to sleep during a large app download and the Intune enrollment timed out. The logging writes to C:\ProgramData\AutopilotLogs, which persists across user profiles. When something goes wrong three months from now, you’ll have a record of exactly what the provisioning script did on that specific device.

Deploy this script through Intune under Devices > Scripts and remediations > Platform scripts. Set it to run in the System context and in a 64-bit PowerShell host. Assign it to your Autopilot Devices group so it runs on every device that comes through the pipeline.

Step 5: Package and Assign Applications

Applications are where most zero-touch deployments get complicated. Intune supports several app types, and choosing the right one matters for reliability.

For Microsoft 365 Apps (Office), use Intune’s built-in Microsoft 365 Apps configuration. Don’t try to deploy Office as a Win32 app — the built-in integration handles updates, licensing, and configuration profiles natively. Go to Apps > Windows > Add > Microsoft 365 Apps and configure which apps to include, the update channel, and whether to install 32-bit or 64-bit versions.

For third-party applications — your VPN client, your security agent, your line-of-business app — package them as Win32 apps using the Microsoft Win32 Content Prep Tool. This wraps the installer into a format Intune can deploy reliably:

# Download the Win32 Content Prep Tool
# https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool

# Package an MSI installer
.\IntuneWinAppUtil.exe `
    -c "C:\Packages\VPNClient" `
    -s "VPNClient-Setup.msi" `
    -o "C:\Packages\Output" `
    -q

# Package an EXE installer with silent switches
.\IntuneWinAppUtil.exe `
    -c "C:\Packages\SecurityAgent" `
    -s "SecurityAgent-Setup.exe" `
    -o "C:\Packages\Output" `
    -q

The -c flag points to the folder containing the installer and any supporting files. The -s flag specifies the setup file. The -o flag sets the output directory where the .intunewin package is created. Upload the resulting package to Intune and configure the install and uninstall commands, detection rules, and requirements. Our knowledge base covers MLOps infrastructure for A/B testing if you want to dig into the technical side.

Detection rules are critical — and they’re where most app deployment problems originate. A detection rule tells Intune how to verify that the application installed successfully. If your detection rule is wrong, Intune will either report success when the app isn’t installed, or it will keep trying to install an app that’s already there. Use file-based detection (check that the .exe exists in the expected path) or registry-based detection (check for a specific registry key the installer creates). MSI-based detection using the product code is the most reliable for MSI installers.

Assign all applications to your Autopilot Devices group as “Required” deployments. This ensures they install during the enrollment status page — the employee won’t reach their desktop until all required apps are installed and verified.

Step 6: Test the Pipeline End to End

Do not deploy this to your first real new hire without testing it. I’ve made that mistake exactly once. The employee in Port Orange waited three hours for a laptop that kept failing at the VPN client installation because the detection rule was checking the wrong path. Test on a dedicated device first.

Here’s my testing process. Get a device that’s registered with Autopilot. Factory reset it — Settings > System > Recovery > Reset this PC > Remove everything. Let it restart and go through the Autopilot process as if it were a brand-new device. Watch every step. Time it. Note where it pauses. Take screenshots of any errors.

After the deployment completes and you’re at the desktop, run this validation script to verify everything landed correctly:

<#
.SYNOPSIS
    Validates that an Autopilot deployment completed successfully.
.DESCRIPTION
    Checks Entra ID join, Intune enrollment, BitLocker, installed apps,
    and custom configuration from post-provisioning scripts.
#>

$checks = @()
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

Write-Host "`n=== Autopilot Deployment Validation ===" -ForegroundColor Cyan
Write-Host "Device: $env:COMPUTERNAME"
Write-Host "Time:   $timestamp`n"

# --- Check 1: Entra ID Join ---
$dsregOutput = dsregcmd /status 2>&1
$entraJoined = $dsregOutput | Select-String "AzureAdJoined\s*:\s*YES"
$checks += [PSCustomObject]@{
    Check  = "Entra ID Join"
    Status = if ($entraJoined) { "PASS" } else { "FAIL" }
    Detail = if ($entraJoined) { "Device joined to Entra ID" }
             else { "Device NOT joined — check Autopilot profile" }
}

# --- Check 2: Intune Enrollment ---
$enrollments = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Enrollments\*" `
    -ErrorAction SilentlyContinue |
    Where-Object { $_.ProviderID -eq "MS DM Server" }
$checks += [PSCustomObject]@{
    Check  = "Intune Enrollment"
    Status = if ($enrollments) { "PASS" } else { "FAIL" }
    Detail = if ($enrollments) { "Enrolled in Intune MDM" }
             else { "NOT enrolled — check auto-enrollment settings" }
}

# --- Check 3: BitLocker ---
$blVolume = Get-BitLockerVolume -MountPoint "C:" -ErrorAction SilentlyContinue
$blEnabled = $blVolume.ProtectionStatus -eq "On"
$checks += [PSCustomObject]@{
    Check  = "BitLocker Encryption"
    Status = if ($blEnabled) { "PASS" } else { "FAIL" }
    Detail = if ($blEnabled) { "C: drive encrypted, protection ON" }
             else { "BitLocker not active — check compliance policy" }
}

# --- Check 4: Required Applications ---
$requiredApps = @(
    @{ Name = "Microsoft 365"; SearchTerm = "*Microsoft 365*" },
    @{ Name = "Microsoft Teams"; SearchTerm = "*Teams*" },
    @{ Name = "Company VPN";    SearchTerm = "*VPN*" }
)
foreach ($app in $requiredApps) {
    $found = Get-Package -Name $app.SearchTerm -ErrorAction SilentlyContinue
    $checks += [PSCustomObject]@{
        Check  = "App: $($app.Name)"
        Status = if ($found) { "PASS" } else { "FAIL" }
        Detail = if ($found) { "Installed — v$($found.Version)" }
                 else { "NOT FOUND — check Intune app assignment" }
    }
}

# --- Check 5: Custom Configuration ---
$lobRegPath = "HKLM:\SOFTWARE\CompanyApp"
$regExists = Test-Path $lobRegPath
$checks += [PSCustomObject]@{
    Check  = "LOB Registry Config"
    Status = if ($regExists) { "PASS" } else { "FAIL" }
    Detail = if ($regExists) { "Post-provisioning registry keys present" }
             else { "Missing — check PowerShell script deployment" }
}

# --- Check 6: Time Zone ---
$tz = Get-TimeZone
$checks += [PSCustomObject]@{
    Check  = "Time Zone"
    Status = if ($tz.Id -eq "Eastern Standard Time") { "PASS" } else { "FAIL" }
    Detail = "Current: $($tz.Id)"
}

# --- Results ---
Write-Host ""
$checks | Format-Table Check, Status, Detail -AutoSize

$passed = ($checks | Where-Object { $_.Status -eq "PASS" }).Count
$total  = $checks.Count
$color  = if ($passed -eq $total) { "Green" } else { "Red" }

Write-Host "`nResult: $passed/$total checks passed" -ForegroundColor $color

if ($passed -lt $total) {
    Write-Host "`nFailed checks require investigation before deploying to users." `
        -ForegroundColor Yellow
}

Run this on your test device. If everything passes, your pipeline is ready. If something fails, the detail column tells you exactly where to look. Fix it, reset the device, and test again. I usually do three full test cycles before I’m confident enough to deploy to real users.

Monitoring and Troubleshooting Your Deployments

Once your pipeline is live, you need visibility into what’s happening. Intune provides deployment status in the admin center under Devices > Windows > Windows Enrollment > Deployment Profiles — select your profile and check the device status tab. You’ll see each device’s enrollment state: pending, in progress, completed, or failed.

For deeper troubleshooting, the Enrollment Status Page logs on the device itself are invaluable. They’re stored at:

C:\Users\<username>\AppData\Local\Temp\IntuneMDMDiagReport

Also check the Event Viewer under Applications and Services Logs > Microsoft > Windows > DeviceManagement-Enterprise-Diagnostics-Provider. This log captures every policy application, app installation, and configuration change that Intune makes during enrollment.

The most common failure I see in Volusia County deployments is network-related. Autopilot requires reliable internet connectivity throughout the entire process. If the employee’s home Wi-Fi drops during a large app download, the enrollment status page may time out. Delivery Optimization failures — where Intune can’t download app content — are almost always caused by network instability, proxy interference, or firewall rules blocking Microsoft CDN endpoints.

The second most common failure is application detection rules that don’t match reality. You test on one machine and it works. You deploy to a different model and the app installs to a different path. The detection rule checks the wrong location. Intune thinks the app failed. The enrollment status page shows an error. Always test your detection rules on at least two different hardware models before going live.

Scaling the Pipeline: Group Tags and Multiple Profiles

As your organization grows, you’ll need different configurations for different roles. The marketing team needs Adobe Creative Cloud. The accounting team needs QuickBooks. The warehouse team needs inventory management software. You don’t want to install everything on every machine.

Group tags solve this problem. When you register a device with Autopilot, you can assign a group tag — a text label like “Marketing,” “Accounting,” or “Warehouse.” You then create dynamic device groups in Entra ID based on these tags:

(device.devicePhysicalIDs -any (_ -contains "[OrderID]:Marketing"))

Each group gets its own deployment profile and its own set of assigned applications. The marketing laptop gets Creative Cloud. The accounting laptop gets QuickBooks. The warehouse laptop gets the inventory app. Same pipeline, different configurations, all driven by a tag you set during registration.

For businesses in Daytona Beach and across Volusia County that are managing twenty to fifty devices, group tags are the feature that transforms zero-touch deployment from a convenience into a genuine operational system. You’re not just automating setup — you’re building a repeatable, role-based provisioning platform.

The White Glove Option: Pre-Provisioning for Sensitive Roles

Some roles need more verification before the employee gets the device. Executive workstations, machines that will handle financial data, devices for employees with access to sensitive systems. For these, Autopilot offers a “pre-provisioning” mode (formerly called White Glove).

In pre-provisioning mode, IT (or a reseller) runs the device-targeted phase of Autopilot before shipping the device. They power on the device, press the Windows key five times at the OOBE screen to enter the Autopilot pre-provisioning flow, and the device installs all apps and policies in IT’s hands. IT verifies that everything is correct, then seals the device and ships it. When the employee receives it, they sign in and only the user-targeted phase runs — account setup, OneDrive sync, and user-specific configurations. The heavy lifting is already done.

This adds a touch back to your “zero-touch” process, but for high-security roles, the tradeoff is worth it. You get the consistency of Autopilot’s automated deployment with the verification of human oversight before the device reaches the employee.

When to Call a Professional

Zero-touch deployment is conceptually straightforward, but the devil is in the details. Entra ID conditional access policies interacting with Autopilot enrollment. Application packaging that requires custom detection rules. Hybrid join scenarios where devices need to reach both cloud and on-premises resources. Network configuration that allows the enrollment status page endpoints through your firewall.

If you’re managing ten to fifty workstations and you’ve never set up Autopilot before, budget time for learning and testing. You can absolutely do this yourself. But if you’re deploying during a hiring surge and need the pipeline working by next week, bring in help. The difference between a well-configured pipeline and a fragile one is experience with the failure modes — and those failure modes are not obvious until you hit them.

For businesses in Deltona, Ormond Beach, DeLand, and across Volusia County, we build and manage zero-touch deployment pipelines as part of our automation practice. We handle the initial configuration, application packaging, testing, and monitoring — you handle ordering laptops and assigning them to employees. The pipeline does the rest.

If your IT person is still building machines by hand, or if you’re about to hire five people and dreading the setup work, let’s talk about automating your workstation deployments.

FAQ

What is zero touch deployment for Windows?

Zero-touch deployment for Windows is an automated provisioning method where new laptops and desktops configure themselves when an employee first powers them on. Using Windows Autopilot with Microsoft Intune, devices automatically join your company directory, install required applications, apply security policies, and land on the employee’s desk ready to work — no IT staff needs to physically handle the hardware.

How does Windows Autopilot work?

Windows Autopilot uses a device’s hardware hash — a unique digital fingerprint — to identify it to Microsoft’s cloud services. When a registered device connects to the internet during initial setup, Autopilot downloads the organization’s deployment profile, joins the device to Entra ID, enrolls it in Intune for management, installs assigned applications, and applies security and configuration policies automatically.

Can small businesses use zero touch deployment?

Yes. Any organization with Microsoft 365 Business Premium or Enterprise licenses can use Windows Autopilot for zero-touch deployment. The setup requires Entra ID, Microsoft Intune, and device hardware hashes from your vendor. Small businesses with 10 to 50 workstations see the biggest efficiency gains because they eliminate the repetitive manual setup that consumes IT hours during hiring surges or hardware refreshes.

What is the difference between zero touch and lite touch deployment?

Zero-touch deployment requires no IT hands on the device — it ships from the vendor directly to the employee and configures itself. Lite-touch deployment still requires IT to perform some manual steps, like booting from a USB drive or connecting to a deployment server. Zero-touch is cloud-driven through Autopilot and Intune, while lite-touch typically relies on on-premises infrastructure like SCCM or MDT.

How much does Windows Autopilot cost for small businesses?

Windows Autopilot itself is included with Microsoft 365 Business Premium (around $22 per user per month) or Microsoft Intune Plan 1 licenses. There is no additional per-device cost for Autopilot. The real cost is the time to set up deployment profiles, register hardware hashes, and configure your application packages — a one-time investment that pays back with every device you deploy afterward.

Free Discovery Call

Start With a Conversation, Not a Commitment

Every engagement begins with a free 30-minute discovery call. We'll map what's slowing your business down and tell you exactly what we'd fix first – no pitch deck, no obligation.