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 -DynamicGet-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 MBRFormat 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: doneVHDX 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
--bareexposes 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 successfullysudo 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/wslevoAutomate 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 \\.\PHYSICALDRIVE3Alternative Mount VHDX as a Physical Drive in Windows
This is a Windows-first approach:
Mount-VHDattaches 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 FullUnderstanding /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.
