Beyond the Microsoft Store: How to Build a Custom WSL Distribution from an Ubuntu 25.04 ISO

Installing a Custom Ubuntu WSL Distribution from an ISO

Installing a Custom Ubuntu WSL Distribution from an ISO

A comprehensive guide to extracting, packaging, and repairing a custom WSL image from scratch.

Ubuntu WSL Integration

Introduction

This document provides a comprehensive guide on how to install a Windows Subsystem for Linux (WSL) distribution using a downloaded ISO file. The target distribution in this guide is named Ubuntu-25.04.

Installing a WSL distribution from an ISO is not a direct process. You cannot simply point WSL to the .iso file. Instead, the process involves extracting the core Linux filesystem from the ISO, packaging it into a compressed tarball (.tar.gz), importing this tarball into WSL, and performing post-installation fixes to ensure core utilities function correctly.

This guide details the entire journey, including initial failed attempts and the final successful methodology, providing both the necessary commands and the theory behind why certain steps were taken.


Part 1: Preparation and Initial Extraction Attempts

This part covers the initial setup and the challenges encountered during the extraction of the root filesystem. Understanding these failures is key to understanding the successful method.

Step 1: Creating Necessary Directories

Before starting, we need to create two folders on the Windows host system:

  1. A temporary location to store the extracted filesystem and the final tarball.
  2. A permanent location where WSL will store the virtual hard disk (.vhdx) for the new distribution.

The following commands were used to create these directories:

mkdir C:\temp\ubuntu-rootfs
mkdir C:\WSL\Ubuntu-25.04

Step 2: The Challenge of Filesystem Extraction

The core of the Linux OS inside the Ubuntu ISO is stored in a compressed file named filesystem.squashfs (or similar, in our case it was minimal.squashfs). The main challenge is extracting this file while preserving Linux-specific attributes like symbolic links and file permissions.

First Attempt: Using 7-Zip on Windows

The most straightforward approach is to use a tool like 7-Zip to extract the minimal.squashfs file.

Command Attempted:

"C:\Program Files\7-Zip\7z.exe" x "C:\...\minimal.squashfs" -o"C:\temp\ubuntu-rootfs"

Result: Failure.

Theory: This method failed because 7-Zip, when running on Windows as a standard user, does not have the necessary privileges to create symbolic links, which are fundamental to a Linux filesystem. It also cannot create special device files (e.g., /dev/null). This resulted in numerous "Cannot create symbolic link" errors.

Second Attempt: Using `unsquashfs` in WSL to a Windows Directory

A more advanced approach is to use the unsquashfs utility from within an existing WSL instance, which is designed to understand Linux filesystems. The initial idea was to extract directly to the temporary directory on the Windows C: drive.

Command Attempted:

wsl unsquashfs -f -d /mnt/c/temp/ubuntu-rootfs /mnt/c/.../minimal.squashfs

Result: Failure.

Theory: This attempt also failed, but for a more subtle reason. While unsquashfs in WSL can create symbolic links, the target filesystem was NTFS (the Windows C: drive, mounted at /mnt/c/). NTFS has limitations in how it handles the sheer number and complexity of Linux-style symbolic links, leading to a "Too many levels of symbolic links" error. The process also failed because it couldn't create character device files without root privileges.


Part 2: The Successful Method: Isolate and Repair

The successful strategy involved isolating the extraction and packaging process entirely within the WSL native (ext4) filesystem and then fixing the permissions as a post-installation step.

Step 3: Extraction Inside the WSL Filesystem

To overcome the filesystem limitations of NTFS, the extraction was performed inside the home directory of the default WSL user, which resides on a native ext4 filesystem.

  1. Create a temporary directory inside WSL and copy the squashfs file into it:
    wsl -- bash -c "mkdir -p ~/wsl-temp && cp /mnt/c/Users/ManupaWickramasinghe/Downloads/ubuntu-25.04-desktop-amd64/casper/minimal.squashfs ~/wsl-temp/"
  2. Extract the filesystem without `sudo`: To avoid an interactive password prompt for sudo, the extraction was performed as a regular user. This required flags to bypass errors related to creating special files and attributes, which would be fixed later.
    wsl -- bash -c "cd ~/wsl-temp && unsquashfs -f -no-xattrs -ignore-errors minimal.squashfs"
    • -f: Force overwrite of any existing files in the destination.
    • -no-xattrs: Prevents the tool from trying to write extended attributes, avoiding a class of permission errors.
    • -ignore-errors: Ignores errors related to creating special device files, allowing the extraction to complete.

Step 4: Packaging the Filesystem into a Tarball

With the filesystem successfully extracted to the squashfs-root directory inside ~/wsl-temp, it was then packaged into a compressed tarball.

wsl -- bash -c "cd ~/wsl-temp && tar -czvf ubuntu-25.04.tar.gz -C squashfs-root/ ."
  • -c: Create a new archive.
  • -z: Compress the archive with gzip.
  • -v: Verbose output (optional, shows files being added).
  • -f ubuntu-25.04.tar.gz: Specifies the output filename.
  • -C squashfs-root/: Changes to the squashfs-root directory before adding files. This is crucial to ensure the tarball does not contain an extra parent directory.
  • .: Specifies that all files in the current directory (now squashfs-root) should be added.

Step 5: Importing the Tarball into WSL

The final tarball was then moved from the WSL filesystem back to the Windows temporary directory and imported.

  1. Move the tarball:
    wsl -- bash -c "mv ~/wsl-temp/ubuntu-25.04.tar.gz /mnt/c/temp/"
  2. Import the distribution:
    wsl --import Ubuntu-25.04 C:\WSL\Ubuntu-25.04 C:\temp\ubuntu-25.04.tar.gz

    This command registers Ubuntu-25.04 as a new WSL distribution, storing its virtual disk in the previously created C:\WSL\Ubuntu-25.04 directory.


Part 3: Post-Installation Configuration and Repair

The extraction method, while successful, left critical system files with incorrect ownership and permissions because it was run without sudo. This required a final repair phase.

Step 6: Repairing `sudo` and `passwd`

The sudo and passwd commands were not working due to incorrect file permissions. They were fixed by using wsl -u root to run commands as the root user from outside the distribution, bypassing the broken sudo.

  1. Fix `sudo` executable and configuration files:
    wsl -d Ubuntu-25.04 -u root -- bash -c "chown root:root /etc/sudo.conf && chown root:root /usr/bin/sudo && chmod 4755 /usr/bin/sudo"

    Theory: /usr/bin/sudo must be owned by root and have the setuid bit (4...) set. This allows it to run with root privileges even when executed by a normal user.

  2. Fix `passwd` utility and shadow file:
    wsl -d Ubuntu-25.04 -u root -- bash -c "chown root:root /usr/bin/passwd && chmod 4755 /usr/bin/passwd && chown root:shadow /etc/shadow && chmod 640 /etc/shadow"

    Theory: Similar to sudo, passwd needs setuid to modify the protected /etc/shadow file, which stores user password hashes.

  3. Fix the `/etc/sudoers` file:
    wsl -d Ubuntu-25.04 -u root -- bash -c "chown root:root /etc/sudoers && chmod 0440 /etc/sudoers"
    wsl -d Ubuntu-25.04 -u root -- bash -c "chown -R root:root /etc/sudoers.d && chmod 0755 /etc/sudoers.d"

    Theory: /etc/sudoers is the main configuration file for sudo. It must be owned by root and be read-only for security reasons.

Step 7: Final User Configuration

With the system repaired, a user account was created and configured.

  1. Create a new user and add to the `sudo` group:
    wsl -d Ubuntu-25.04 useradd -m -G sudo -s /bin/bash manupawick
  2. Set the new user as the default for login:
    wsl -d Ubuntu-25.04 -u root bash -c "echo -e '[user]\ndefault=manupawick' > /etc/wsl.conf"
  3. Set the user's password non-interactively:
    wsl -d Ubuntu-25.04 -u root -- bash -c "echo 'manupawick:password12312' | chpasswd"
  4. Finalize the installation by shutting down WSL to apply all changes:
    wsl --shutdown

Conclusion

The installation was successful. The key takeaway is that extracting a Linux filesystem for WSL requires careful handling of file permissions and symbolic links. The most reliable method is to perform the extraction and packaging within a native Linux filesystem (like the one provided by WSL itself) and then perform targeted permission repairs as a post-installation step.

0 Comments