wipzy

Shrink the WSL disk image (ext4.vhdx) on Windows

The WSL 2 disk file ext4.vhdx grows as you work and never shrinks by itself. Find it, free space inside Linux, then compact it with diskpart or Optimize-VHD.

The file ext4.vhdx as a bar, part used by Linux and part freed but still on disk, above the steps wsl --shutdown and compact vdisk

WSL 2 keeps each Linux distribution in one file, ext4.vhdx. The file grows as Linux writes, up to a limit of 1 TB by default, and it does not shrink when you delete things inside. Getting the space back takes three steps:

  1. Free space inside Linux.
  2. Shut WSL down.
  3. Compact the file from Windows.

This guide gives the commands for each. It is for Windows 11 and Windows 10 with WSL 2. Wipzy does not run on Windows yet. A version is in the works, and nothing here needs it.

Find the file and its size

In PowerShell, replace Ubuntu with the name of your distribution from wsl --list --verbose:

(Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq 'Ubuntu' }).GetValue("BasePath") + "\ext4.vhdx"

This is the lookup Microsoft documents. It prints a path such as C:\Users\you\AppData\Local\Packages\CanonicalGroupLimited...\LocalState\ext4.vhdx. Check the size of the file:

(Get-Item "C:\path\to\ext4.vhdx").Length / 1GB

Then compare it with what Linux really uses:

wsl df -h /

If the file is 80 GB and df shows 25 GB used, there are 55 GB to win back. If the two numbers are close, compacting will gain little. The space is in use, and step 1 is where you need to work.

Step 1: free space inside Linux

Inside the distribution, find what is large:

du -h --max-depth=1 ~ 2>/dev/null | sort -hr | head -15

The usual suspects are the same as on any developer machine: node_modules folders, ~/.cache, ~/.npm, ~/.cargo, and Docker data if you run Docker Engine inside WSL. For the package manager's own downloads on Ubuntu or Debian:

sudo apt clean

When you have deleted what you do not need, tell the virtual disk which blocks are now free:

sudo fstrim -av

Step 2: shut WSL down

From PowerShell or Command Prompt:

wsl --shutdown

This stops every distribution and the WSL virtual machine. Save your work in Linux first. If Docker Desktop is running, quit it too, because it uses WSL.

Step 3: compact the file

With diskpart, on any edition of Windows

Open Command Prompt as administrator and start diskpart. Then, with the path from the first section:

select vdisk file="C:\path\to\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit

compact vdisk is the step that takes time, a few minutes for a large file.

With Optimize-VHD, on Pro and Enterprise

If the Hyper-V PowerShell module is installed, one line in PowerShell as administrator does the same:

Optimize-VHD -Path "C:\path\to\ext4.vhdx" -Mode Full

Check the file size again afterwards, then start your distribution as usual.

Sparse mode: automatic, and still experimental

WSL can mark a disk file as sparse, so that Windows gets freed blocks back without a manual compact:

wsl --manage Ubuntu --set-sparse true

Treat this one with care. Microsoft lists the matching setting, sparseVhd in .wslconfig, under experimental features, and it is off by default. For a period, WSL releases refused to enable sparse mode without an extra flag and warned of possible data corruption. If you try it, make an export first. And do not mix the two methods: a disk in sparse mode should not be compacted with Optimize-VHD.

The manual compact above is the dull, dependable way.

Docker Desktop has its own file

Docker Desktop on Windows stores its images and containers in a separate disk file under %LOCALAPPDATA%\Docker\wsl. The same logic applies: free space inside with the docker prune commands, quit Docker Desktop, run wsl --shutdown, then compact that file with diskpart.

On a Mac the same pattern has another name. The file is Docker.raw, and its story is in Docker.raw is huge on a Mac.

Keep the limit lower

The 1 TB default is a ceiling, not a reservation. If you would rather hear "disk full" inside Linux than run out of space on C:, set a lower ceiling for new distributions in %UserProfile%\.wslconfig:

[wsl2]
defaultVhdSize=100GB

To change the size of an existing disk, WSL 2.5 and later have wsl --manage <distribution> --resize <size>.

With Wipzy

Wipzy runs on macOS 13 or later on Apple silicon. A Windows version is in the works on the same Rust engine, and it is not available yet, so there is no button for this today. Step 1 is the part Wipzy does on a Mac: knowing which folders your tools can rebuild, and which are your work.

On a Mac, that looks like this:

  • A scan finds node_modules, vendor, target and build output in every project, and 74 developer caches, each with its size.
  • Each row has a level. Safe items come back with one command and are ticked for you. Your call and Careful items are listed for you to decide. Source, .env and anything git tracks are Protected.
  • Clean moves items to a quarantine, and History has Undo.
  • Disk image files are never touched. On a Mac, Wipzy does not offer Docker.raw, for the same reason you should not delete ext4.vhdx: everything is inside it.

For the Windows side of node_modules, see the path too long fix. For the model behind the levels, see Four levels. Only one is ticked for you and the film.

Questions

Why is ext4.vhdx so big when my Linux files are small?

The file grows when Linux writes data and does not give the space back when you delete it. After a large build or download, the file keeps its peak size until you compact it.

Is it safe to compact ext4.vhdx?

Compacting removes only blocks that Linux marked as unused. It does not delete files. Shut WSL down first, and export a backup of the distribution if it holds work you have nowhere else.

Do I need Windows Pro for this?

No. diskpart is in every edition of Windows. Optimize-VHD is shorter but needs the Hyper-V PowerShell module, which Home editions do not have.

The same job, with a scan, a plan and Undo

Wipzy for Mac. Free for Projects and Dev caches. macOS 13 or later, Apple silicon.

Get Wipzy

The first public build is being notarized by Apple.

Docker.raw as a bar: a small part really used inside a 64 GB limit, with the command docker system df and a Protected chip

Docker

Docker.raw is huge on a Mac: how to shrink it

Docker.raw looks like 64 GB in Finder but often uses far less. See its real size, find what fills it with docker system df, and give space back to macOS safely.

, 5 min read

Three prune commands in order: docker builder prune, docker image prune -a, and docker volume prune marked Careful

Docker

docker system prune: what each prune deletes

What docker system prune removes, what -a and --volumes add, and which prune commands are safe. Check with docker system df first, and keep your volumes.

, 5 min read