Windows WSL - Virtual Hard Disk (VHDX)

Create VHDX inside an NTFS volume (E:)

$VHDPath = "E:\WSL2_Ext4_Volume.vhdx" 
$FreeSpace = (Get-Volume -DriveLetter E).SizeRemaining 
New-VHD -Path $VHDPath -SizeBytes $FreeSpace -Dynamic
Get-VHD -Path "E:\WSL2_Ext4_Volume.vhdx"
 
ComputerName            : Z440
Path                    : E:\WSL2_Ext4_Volume.vhdx
VhdFormat               : VHDX
VhdType                 : Dynamic
FileSize                : 45705330688
Size                    : 2000160612352
MinimumSize             :
LogicalSectorSize       : 512
PhysicalSectorSize      : 4096
BlockSize               : 33554432
ParentPath              :
DiskIdentifier          : 593C2CED-74D6-416A-A95C-E4B8974CF99A
FragmentationPercentage : 0
Alignment               : 1
Attached                : False
DiskNumber              :
IsPMEMCompatible        : False
AddressAbstractionType  : None
Number                  :
Get-Disk
 
Number Friendly Name Serial Number                    HealthStatus         OperationalStatus      Total Size Partition
                                                                                                             Style
------ ------------- -------------                    ------------         -----------------      ---------- ----------
0      CT1000BX500S… 2506E9A4A510                     Healthy              Online                  931.51 GB MBR
4      Intenso Exte… 20180113100E1                    Healthy              Online                    1.82 TB MBR
1      Patriot Burst A312070C0E2F00104036             Healthy              Online                  447.13 GB MBR
2      Samsung SSD … S754NX0Y804461A                  Healthy              Online                    1.82 TB GPT
3      SanDisk SDSS… 142046401216                     Healthy              Online                  119.24 GB MBR

Format the new VHDX and create Ubuntu EXT4 filesystem

lsblk
 
sudo mkfs.ext4 /dev/sde -L wslevo 
 
mke2fs 1.47.0 (5-Feb-2023) 
Discarding device blocks: done 
Creating filesystem with 488320462 4k blocks and 122085376 inodes 
Filesystem UUID: 4a77bbc2-83ec-4ce0-bd00-7aedabb21122 
Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 102400000, 214990848 
Allocating group tables: done 
Writing inode tables: done 
Creating journal (262144 blocks): done 
Writing superblocks and filesystem accounting information: done

VHDX Check before mounting

# Verify the file exists
Test-Path "E:\WSL2_Ext4_Volume.vhdx"
 
# Check if the file is in use
Get-Process | Where-Object {$_.Modules.FileName -like "*WSL2_Ext4_Volume.vhdx*"}
 
# Shutdown wsl
wsl --shutdown 

Mount the VHDX into WSL2 native approach

This is a WSL-native approach:

  • WSL itself handles the VHD attachment directly
  • --bare exposes the disk as a raw block device in WSL (e.g., /dev/sde) without automatically mounting filesystems
  • The VHD is only accessible within WSL, not visible to Windows
  • Simpler, more integrated with WSL’s architecture
  • Requires WSL to manage the entire lifecycle
wsl --mount --vhd "E:\WSL2_Ext4_Volume.vhdx" --bare
The operation completed successfully
sudo mount /dev/sde /mnt/wslevo
 
df -h /mnt/wslevo
Filesystem      Size  Used Avail Use% Mounted on
/dev/sde        1.8T   13G  1.7T   1% /mnt/wslevo
Automate mount

Write this mount-wsl-vhd.bat script and place it inside C:\Users\athan\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup so that it is executed automatically when the user log in

@echo off
timeout /t 10 /nobreak >nul
wsl --mount --vhd "E:\WSL2_Ext4_Volume.vhdx" --name evo
 
 
:: wsl --mount \\.\PHYSICALDRIVE3
:: wsl --unmount \\.\PHYSICALDRIVE3

Alternative Mount VHDX as a Physical Drive in Windows

This is a Windows-first approach:

  • Mount-VHD attaches the VHD through Windows’ Hyper-V infrastructure
  • The disk becomes visible to Windows as a physical drive
  • Then you manually pass that physical drive number to WSL
  • The VHD is accessible to both Windows and WSL simultaneously
  • More control but more complex - you’re bridging two systems
# mount-wsl-disk.ps1
Mount-VHD -Path "E:\WSL2_Ext4_Volume.vhdx"
$diskNumber = (Get-VHD -Path "E:\WSL2_Ext4_Volume.vhdx").DiskNumber
wsl --mount "\\.\PhysicalDrive$diskNumber"
 
# Check what disk number it gets 
Get-Disk | Where-Object {$_.FriendlyName -like "*Virtual*"}
Unmount VHDX with a script
# unmount-wsl-disk.ps1 
wsl --unmount \\.\PhysicalDrive5 
Dismount-VHD -Path "E:\WSL2_Ext4_Volume.vhdx"
Optimize compact the VHDX
# Optimize/compact the VHDX (requires it to be unmounted) 
wsl --shutdown 
Optimize-VHD -Path "E:\WSL2_Ext4_Volume.vhdx" -Mode Full

Understanding /etc/wsl.conf

/etc/wsl.conf is a configuration file used in Windows Subsystem for Linux (WSL) that allows you to customize how your Linux distribution behaves when running under WSL. This file is read when the WSL instance starts up.