5

It seems that WSL stores the filesystem data in a vhdx file. Ubuntu sees this as a 250GB disk, which is a bit much for my purposes. I want to resize this to a 30GB disk or so, to save disk space on the host machine.

I've seen several links that compact the vhdx file and reclaim disk space that way. That's not what I'm looking for. I need a solution that ideally doesn't require manual steps, but at the very least doesn't require me to shutdown WSL

I've seen several links about resizing vhdx files in the context of Hyper-V. Hyper-V tooling doesn't seem to like my WSL image much. Possibly because it doesn't seem to have a partition table?

Background: I'm going to deploy this thing on a buildserver, meaning it has to be as hands-off as possible, and as much uptime as reasonably possible. And I can budget disk usage pretty much in advance. In fact, I need to, otherwise there will be no room for the Windows builds that'll also be running there

4
  • 1
    I'm pretty sure it's a sparse disk image, ie. unused disk space in a guest doesn't use any disk space on the host.
    – gronostaj
    Nov 9, 2020 at 12:53
  • Like I said, I'll deploy to a buildserver, so there'll be a lot of writes followed by deletes. Deleted space is not returned to the host OS (as evidenced by the popularity of links proposing to compact the image)
    – Kees-Jan
    Nov 9, 2020 at 14:57
  • I found these instructions for increasing the disk size, but since this question is about reducing size, I'll not consider it an answer
    – Kees-Jan
    Nov 4, 2022 at 19:48
  • @Kees-Jan Also, reducing the size that way would require a shutdown, which you want to avoid. But interesting that you are still searching for a solution two years later, it sounds like? Nov 24, 2022 at 2:30

1 Answer 1

2

I know this is a few years old, so you may not have this particular need any longer. However, in the latest WSL releases, the default maximum size of the dynamic VHDX has been increased to 1TB, so the problem may be even worse.

I need a solution that ideally doesn't require manual steps, but at the very least doesn't require me to shutdown WSL

While this solution has a lot of manual steps and a shutdown, it's one-time configuration work to set things up. For there, you can simply use one wsl --import-in-place command to start up new WSL instances using the smaller drive size on the build server.

Also, don't be too scared by the length of the steps/post below - I'm just very (perhaps overly) detailed.

This particular solution requires Windows 11 or Windows 10 running UBR 2311 or later (see this answer for details on how to update currently).

To summarize what I propose:

  • Create a new VHD with your desired maximum size
  • Mount it in WSL and create the filesystem.
  • Copy over all files from an existing WSL distro to the new VHD.
  • wsl --import the VHD as a new distribution.

Full details:

If you are on a Windows 10 xxxxx.2311 or Windows 11 22H2 release:

  • Run wsl --update, which should update your WSL to use the new application package (Store) version of WSL. If you do not have access to the Store from your build server, see the later half of this answer for manual installation steps.

  • You'll need two distributions installed. The one you want to copy and one for doing the copying (a "temp" distro if needed). If you are working with Ubuntu, for instance, then you can just create a new Ubuntu-22.04 instance from the Store.

  • In an admin PowerShell, create a new dynamic VHD using:

    new-vhd -Dynamic -SizeBytes 30gb -BlockSizeBytes 1mb -path ./ext4.vhdx
    

    The -BlockSizeBytes matches the existing setting for WSL2 ext4.vhdx files.

  • Exit the Admin PowerShell and in a new, regular-user PowerShell, run:

    Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\ |
        ForEach-Object {
            (Get-ItemProperty $_.PSPATH) | Select-Object DistributionName,BasePath
    }
    

    Make note of the path of the original distribution that you want to copy. We'll call this <srcdrive>.

  • wsl --shutdown to make sure no files in the original distribution are in use. Make sure there's no process that might automatically restart that distribution (e.g. Docker Desktop).

  • Start the "temp" distribution that you will be using to do the copying with wsl ~ -d <distroname>

  • lsblk and take note of the existing devices listed. Make sure to identify any devices that are the same size as the one you'll be formatting. You don't want to overwrite one that is already in use!

  • Exit WSL and return to PowerShell.

    wsl --mount --vhd --bare \path\to\the\new\ext4.vhdx
    wsl --mount --vhd --name srcdrive path\to\<srcdrive.vhdx>
    

    Using the path you determined above for <srcdrive>.

  • Start your temp WSL instance again.

    lsblk
    
  • Confirm the device name that you want to format. It should be the only 30G device there, hopefully. Regardless, it should be the only 30G device in the list that wasn't there when we checked before the --mount. We'll call this newdev:

    sudo mkfs.ext4 /dev/<newdev>
    sudo mount -t ext4 /dev/<newdev> /mnt/wsl/newdrive -o X-mount.mkdir
    
  • You should have two mounts:

    /mnt/wsl/srcdrive
    /mnt/wsl/newdrive
    

    srcdrive should look like the filesystem from your existing distribution that you want to copy. newdrive should currently be empty other than the default lost+found.

  • Copy over the filesystem:

    sudo cp -axT /mnt/wsl/srcdrive/ /mnt/wsl/newdrive/
    
  • Exit the WSL temp distribution

  • Back in PowerShell:

    wsl --shutdown
    wsl --import-in-place <new_distro_name> \path\to\the\new\ext4.vhdx
    
  • Finally, start the new distro with wsl ~ -d <new_distro_name>. It will start as the root user. To set your default user, create a /etc/wsl.conf file as noted in this answer.

You can now use the new VHD to seed your build system with multiple (if needed) smaller WSL distributions with just an additional wsl --import-in-place.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .