Migrate a physical Ubuntu 20.04 Desktop to WSLg in Windows 11 by mounting the system SSD

rs flag

I have a existing physical Ubuntu 20.04 Desktop system running on a SSD with ext4 as the file system.

I mounted the SSD into the WSLg Ubuntu in Windows 11.

To keep the same experience as much as possible, I want to use the mounted SSD as the main system disk to replace the default installation of Ubuntu in WSLg.

Is that possible?

I have tried chroot into the SSD in WSLg and successfully ran some CLI software. But it failed to launch all those GUI applications like Jetbrains IDEs.

What's more, after migration, I wish I could still boot into the same physical Ubuntu system using the same SSD when needed.

ChanganAuto avatar
us flag
Short answer: No, not possible or even desirable.
NotTheDr01ds avatar
vn flag
@ChanganAuto Just curious, what makes you so sure? You may be right, but heck, I'm a pessimist/realist by nature and I can see *some* hope of this working. I can at least see the *possibility* of solving the `chroot` issue by mapping the Interop socket.
rs flag
@NotTheDr01ds Thanks! Could you please provide more informations about the mapping the Interop socket ?
vn flag

While I'm not sure (yet) that there's a way to use the drive as a WSL instance itself, I do think we can get the chroot method working, at least to some degree.

Here's the setup that I used:

  • Ubuntu Base 21.10 rootfs image extracted (as sudo) to $HOME/chroot/Ubuntu21.10.
  • For testing, after the below configuration was completed, apt install xterm
  • For anyone attempting this with an actual rootfs, note that you should untar with the xattrs option, e.g.:
    # Download Ubuntu Base rootfs into the current directory, then:
    mkdir Ubuntu21.10
    cd !$
    sudo tar -xvz --xattrs -f ../ubuntu-base-21.10-base-amd64.tar.gz

Off the top of my head, I can't see a reason that this wouldn't be a semi-accurate representation of an existing SSD that you've been able to mount into a directory inside of a WSL/Ubuntu instance. However, I'm sure there will be items I didn't anticipate from your configuration. Let me know via comment here (plus possibly via new question if warranted) if you run into issues.

What's working

  • Networking
  • Running Windows .exes from within the chroot (including GUI apps)
  • Running Linux GUI apps from within the chroot (requires, of course, Windows 11)

What's known not to work

  • Cannot mount Windows drives from within the chroot (e.g. mount -t drvfs ...). This is likely due to the fact that I haven't yet been able to find a way to mount the special WSL drivers and lib filesystems. Everything else works here via either a mount of the actual filesystem into the chroot path or via a mount --bind ("bind mount") of an existing path from WSL into the chroot path.

  • The Windows path is not populated into that of the chroot (which WSL normally does via /init. This means that you will have to use the fully-qualified path to run any .exes. Populating the path isn't all that difficult to script, but this answer is long enough as it is, so I'll leave the as an exercise to the reader (or a separate question).

Not Tested

  • Audio: If it doesn't work, then it's probably just a matter of finding the right environment variables, or perhaps one more socket to mount if needed.

  • VSCode: May have issues due to "default user" expectation on VSCode's part)

  • Lots of other stuff

One-time prep

There are a few tasks to prep the chroot filesystem for the first time.

  • From inside WSL (not in the chroot), create mountpoints and copy over some WSL items:

    cd <your_chroot_mountpoint_root>
    # Create mount points
    sudo mkdir mnt/c
    sudo mkdir run/WSL
    sudo mkdir mnt/wslg
    sudo mkdir mnt/wsl
    sudo mkdir -p usr/lib/wsl/drivers usr/lib/wsl/lib
    # Copy WSL generated config files - Currently doesn't work, but there for future reference/use
    # sudo cp /etc/ etc/
    # Delete existing resolv.conf and use the one generated by WSL
    sudo rm etc/resolv.conf
    sudo ln -rs mnt/wsl/resolv.conf etc/
    # Delete existing X socket (if exists) and use the one generated by WSL
    [ -S tmp/.X11-unix ] && sudo rm tmp/.X11-unix
    [ -f tmp/.X11-unix ] && sudo rm tmp/.X11-unix
    [ -L tmp/.X11-unix ] && sudo rm tmp/.X11-unix
    sudo ln -rs mnt/wslg/.X11-unix/ tmp/.X11-unix
    # Set up fstab for recurring mount points.
    # (0) Make sure you are in the root of the chroot
    #     (the mounted drive, in your case) before
    #     running each command.
    # (A) I suggest running these lines one-by-one to make sure
    #     they work since ...
    # (B) They are not idempotent
    # (C) Check /etc/fstab after each one.  They should be 
    # pointing to the appropriate directory in your chroot
    # Set up bind mounts for the WSL generated sockets and files:
    sudo sh -c 'echo "/mnt/wsl $PWD/mnt/wsl none bind 0 0" >> /etc/fstab'
    sudo sh -c 'echo "/mnt/wslg $PWD/mnt/wslg none bind 0 0" >> /etc/fstab'
    #sudo sh -c 'echo "/run/WSL $PWD/run/WSL none bind 0 0" >> /etc/fstab' # Currently causes issues
    # Create fstab entries for the necessary filesystems.  For
    # the most part, we do this by finding the entry in 
    # /etc/mtab that WSL generated, copying that over to
    # /etc/fstab, and substituting the chroot path.
    sudo sh -c "grep '^drvfs[[:space:]]\+/mnt/c\W' /etc/mtab | sed \"s-\(/mnt/c\)-${PWD}\1-\" >> /etc/fstab"
    sudo sh -c "grep '^none[[:space:]]\+/dev[[:space:]]' /etc/mtab | sed \"s-\(/dev\)-${PWD}\1-\" >> /etc/fstab"
    sudo sh -c "grep '^proc[[:space:]]\+/proc[[:space:]]' /etc/mtab | sed \"s-\(/proc\)-${PWD}\1-\" >> /etc/fstab"
    sudo sh -c "grep '^devpts[[:space:]]\+/dev/pts[[:space:]]' /etc/mtab | sed \"s-\(/dev/pts\)-${PWD}\1-\" >> /etc/fstab"
    sudo sh -c "grep '^sysfs[[:space:]]\+/sys[[:space:]]' /etc/mtab | sed \"s-\(/sys\)-${PWD}\1-\" >> /etc/fstab"
    sudo sh -c "grep '^binfmt_misc[[:space:]]\+/proc/sys/fs/binfmt_misc[[:space:]]' /etc/mtab | sed \"s-\(/proc/sys/fs/binfmt_misc\)-${PWD}\1-\" >> /etc/fstab"
    # Mount these newly added entries in `/etc/fstab`.  Only needed once -- From here on out, they will automount when you restart the WSL instance:
    sudo mount -a
  • There's one thing that doesn't quite work here. We can't seem to bind mount /run/WSL via /etc/fstab. I believe this is due to a timing issue -- WSL probably hasn't completed mounting the original /run/WSL, so we can't yet bind mount it. Attempting to do so will result in an error at WSL start-up. This error is not fatal.

    You have several options. You can either: * Run the commented-out line above to generate the fstab entry, deal with the error, and then run sudo mount -a after you restart WSL (or add it to a startup file) * Just run sudo mount --bind /run/WSL/ $PWD/run/WSL/ (from inside the chroot root directory) after a WSL restart (Or add it to a startup file).

Starting the chroot:


This populates the environment with the necessary environment variables before starting the shell. There may be additional variables that you want to map, and that's easy enough.

I recommend an apt update to start. This will at least tell you if DNS resolution is working. If not, check the /etc/resolv.conf symlink.

Other startup alternatives include creating a user with the same name as in your WSL instance and then:


Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.