Skip to main content

# ๐Ÿงช Offline Boot Testing & Generalization of VHDX OS Images

This guide follows the Disk2vhd imaging and Azure upload process. In networks where the .vhdx is synced to local hypervisor storage, the image must be tested offline to validate bootability before being generalized and cleaned.


1. ๐Ÿ”Œ Boot Test in Local Staging Hypervisor

Objective:

Ensure the .vhdx image boots in a virtual machine within a completely offline staging environment.

Steps:

  1. Import the .vhdx into your hypervisor (e.g., Hyper-V, Proxmox, VMware Workstation).
  2. Create a test VM:
    • Connect the disk as the primary boot volume.
    • Ensure no internet/network adapters are connected.
  3. Power on the VM.

๐Ÿข Special Case: Ridgebrook Client Deployment

For Ridgebrook:

  • Images stored in the Azure file share:
    • Storage account: clientosimages01e2usdtc
    • File share: client-os-images-01
  • The image should be synced to the local staging hypervisor:
    • Hypervisor name: ELDERBRAIN
    • Local path:
      D:\Virtual Hard Disks\client-os-images-01
  • Ridgebrook .vhdx images should be placed into a subfolder matching their PSA company name (e.g., ridgebrook-industrial).

Once synced, follow the standard boot validation and conversion process below.


2. ๐Ÿ”„ Convert MBR to GPT (If Needed)

If the VM fails to boot, the .vhdx likely uses MBR instead of GPT.

โœ… Option 1: MBR2GPT (Recommended)

Steps:

  1. Boot into Windows Recovery Environment or ISO shell.

  2. Run:

    mbr2gpt /validate /disk:0 /allowFullOS
    mbr2gpt /convert /disk:0 /allowFullOS
    

Make sure the OS volume is the last volume and delete any non-essential partitions (see below).


3. ๐Ÿงผ Cleaning Up Partitions With DiskPart

Target Partition Layout (Post-Conversion):

PartitionPurposeSize
1EFI System10 GB
2Recovery10 GB
3OS VolumeRemainder

Why fixed sizes?
Microsoft has misaligned these in the past โ€” we standardize to 10 GB for EFI and Recovery to avoid risk.

DiskPart Steps:

diskpart
list disk
select disk 0
list partition
  • Delete unwanted partitions (OEM, redundant recovery, etc).
  • Create EFI:
create partition efi size=10240
format quick fs=fat32 label="System"
assign letter=S
  • Create Recovery (optional):
create partition primary size=10240
format quick fs=ntfs label="Recovery"
assign letter=R

4. ๐Ÿฅพ Rebuild BCD Bootloader

bcdboot C:\Windows /s S: /f UEFI
  • C: = OS path
  • S: = EFI partition
  • /f UEFI = Force GPT boot

5. ๐Ÿงฝ Generalize the OS Image (Post-Boot Cleanup)

Once the VHDX boots successfully in offline staging, clear agent registration info and then run Sysprep.

๐Ÿ” Clear Agent Identity & Token Data

Do not uninstall the agents โ€” only remove identity/config/token files to force a fresh enrollment after Sysprep.

ToolRemove Registration From
NinjaRMMDelete contents of:
C:\ProgramData\NinjaRMMAgent\ (excluding binaries if needed)
BlackpointDelete:
  • C:\ProgramData\Blackpoint\
  • Any .json or .db token/cache files | | Veeam Agent | Clear config from:
  • C:\ProgramData\Veeam\
  • Delete any persistent task or repo references | | MSP360 | Remove:
  • C:\ProgramData\CloudBerryLab\
  • Clear backup plans and identity info |

๐Ÿงน Windows Log Cleanup

del /s /q C:\Windows\System32\winevt\Logs\*.*
del /f /q %SystemRoot%\Panther\*.*

6. ๐Ÿงพ Optional: Skip OOBE with unattend.xml

To bypass Out-of-Box Experience (OOBE) and skip all prompts (including user account creation), use an unattend.xml file with Sysprep.

๐Ÿ”’ Note: This method will not create new user accounts, and will not alter existing ones.

Key Capabilities:

  • Skips first-time setup UI
  • Does not create or modify user accounts
  • Disables telemetry and feedback services

Sample unattend.xml Snippet

<unattend xmlns="urn:schemas-microsoft-com:unattend">
  <settings pass="oobeSystem">
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
      <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
        <NetworkLocation>Work</NetworkLocation>
        <ProtectYourPC>3</ProtectYourPC>
        <SkipMachineOOBE>true</SkipMachineOOBE>
        <SkipUserOOBE>true</SkipUserOOBE>
      </OOBE>
      <TimeZone>Eastern Standard Time</TimeZone>
    </component>
  </settings>

  <settings pass="specialize">
    <component name="Microsoft-Windows-Feedback" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
      <DisableFeedback>true</DisableFeedback>
    </component>
    <component name="Microsoft-Windows-CEIPEnable" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
      <CEIPEnable>false</CEIPEnable>
    </component>
    <component name="Microsoft-Windows-ApplicationExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
      <AITEnable>false</AITEnable>
    </component>
    <component name="Microsoft-Windows-ErrorReportingCore" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
      <DisableWerReporting>true</DisableWerReporting>
    </component>
  </settings>
</unattend>

How to Use:

  1. Save as unattend.xml.

  2. Copy to:

    C:\Windows\System32\Sysprep\
    
  3. Run Sysprep:

    sysprep /generalize /oobe /shutdown /unattend:C:\Windows\System32\Sysprep\unattend.xml
    

โœ… Final Checklist

  •  Image booted offline on hypervisor
  •  Converted to GPT, EFI+Recovery+OS partitions validated
  •  Agent registration/token data cleared
  •  Existing users left untouched
  •  unattend.xml disables OOBE and telemetry
  •  Sysprep completed and image shut down cleanly