Skip to content

Conversation

obrobrio2000
Copy link

@obrobrio2000 obrobrio2000 commented Oct 2, 2025

Summary

This PR implements support for portable WSL distributions that can run directly from removable media (USB drives, external disks, etc.) without requiring local disk installation. This addresses feature request #12804 and enables true portability for WSL environments.

Problem Statement

Currently, WSL forces all distributions to be installed on local disks, creating two major limitations:

  1. Lack of true portability - Developers cannot maintain self-contained WSL environments on removable drives
  2. Host system contamination - Temporary usage on foreign computers leaves persistent installations and user data traces

Solution Overview

This PR introduces a complete portable WSL workflow with three new commands and supporting infrastructure:

New Commands

1. wsl --mount-removable <path> [options]

Mount a portable WSL distribution from removable media.

Options:

  • --distro <name> or -d <name>: Override distribution name
  • --temporary or -t: Mark as temporary (registry-tracked for future auto-cleanup)
  • --allow-fixed or -f: Allow mounting from fixed drives (for development/testing)

Examples:

# Mount from USB drive (default behavior)
wsl --mount-removable E:\wsl\ --distro PortableUbuntu

# Mount from fixed drive for testing (requires explicit flag)
wsl --mount-removable C:\dev\wsl\ --distro TestPortable --allow-fixed

2. wsl --import <name> <location> <file> --portable [--allow-fixed]

Create a new portable distribution on external storage.

Examples:

# Create on USB drive (default behavior)
wsl --import UbuntuPortable F:\wsl\ubuntu ubuntu-22.04.tar.gz --portable --vhd

# Create on fixed drive for testing (requires explicit flag)
wsl --import TestPortable C:\dev\wsl\test ubuntu-22.04.tar.gz --portable --vhd --allow-fixed

3. wsl --unmount-removable <distro-name>

Cleanly unmount a portable distribution and remove system traces.

Example:

wsl --unmount-removable PortableUbuntu

Technical Implementation

Architecture

[USB Drive]
├── wsl-portable.json     # Distribution metadata
└── distro.vhdx           # Distribution filesystem

Metadata Format

The wsl-portable.json file contains distribution configuration:

{
    "Name": "PortableUbuntu",
    "FriendlyName": "Ubuntu 22.04 Portable",
    "VhdxPath": "ubuntu.vhdx",
    "Version": 2,
    "DefaultUid": 1000,
    "IsPortable": true
}

Key Components

  1. PortableDistribution.h/cpp

    • Core portable WSL functionality
    • Metadata read/write operations
    • Security-focused path validation (removable media by default)
    • Distribution mounting/unmounting logic
    • allowFixed parameter for development/testing flexibility
  2. Enhanced WslClient.cpp

    • Command routing for new options
    • Integration with existing WSL infrastructure
    • Proper localization using Localization::MessagePortable*() calls
    • Portable distribution tracking
    • --allow-fixed flag support
  3. Localization (Resources.resw)

    • 7 new localized message strings
    • Replaced temporary inline messages with proper localization
  4. Registry Integration

    • Portable distributions marked in registry
    • Base path stored for cleanup
    • Temporary flag tracking (IsTemporary DWORD)
    • Transient registration support

Path Handling

  • Supports standard paths: E:\wsl\
  • Supports Volume GUID paths: \\?\Volume{UUID}\wsl\
  • Automatic drive type detection using Windows GetDriveTypeW() API
  • Security-focused validation: Restricts to DRIVE_REMOVABLE by default
  • Explicit opt-in for fixed drives: --allow-fixed flag required
  • Helpful error messages guide users to correct flag usage

Benefits

True Portability: Carry complete Linux environments on USB drives
Zero Local Footprint: No contamination of host system
Clean Removal: Automatic cleanup on unmount
Easy Sharing: Share pre-configured environments
Secure by Default: Removable media only; fixed drives require explicit flag
Developer Flexibility: --allow-fixed enables testing without USB drives
Temporary Mounts: Registry-tracked for future auto-cleanup features

Usage Workflow

Creating a Portable Distribution

# Method 1: Import from tar file as portable (USB drive)
wsl --import MyPortable E:\wsl\ ubuntu-22.04.tar.gz --portable --vhd

# Method 2: Export existing, then import as portable
wsl --export Ubuntu ubuntu-backup.tar.gz
wsl --import PortableUbuntu F:\wsl\ ubuntu-backup.tar.gz --portable --vhd

# Method 3: Create on fixed drive for testing (explicit opt-in)
wsl --import TestPortable C:\dev\wsl\ ubuntu-22.04.tar.gz --portable --vhd --allow-fixed

Using a Portable Distribution

# Mount the portable distribution
wsl --mount-removable E:\wsl\ --distro MyPortable

# Use it like any other distribution
wsl -d MyPortable

# When done, clean unmount
wsl --unmount-removable MyPortable

Sharing Portable Distributions

Simply copy the entire portable directory (containing wsl-portable.json and .vhdx file) to another USB drive or share with others.

Implementation Details

Files Modified

  • src/windows/inc/wsl.h - Added command constants including --allow-fixed flags
  • src/windows/common/WslClient.cpp - Command handlers, routing, localization integration
  • src/windows/common/WslClient.h - Function declarations
  • src/windows/common/CMakeLists.txt - Added new source files
  • localization/strings/en-US/Resources.resw - Added 7 new localized message strings

Files Added

  • src/windows/common/PortableDistribution.h - Portable WSL API
  • src/windows/common/PortableDistribution.cpp - Implementation

Backward Compatibility

  • All existing WSL commands and functionality remain unchanged
  • New commands are opt-in via explicit flags
  • No impact on non-portable distributions
  • Existing registry structure preserved

Testing Recommendations

  1. Basic Functionality

    • Create portable distribution on USB drive
    • Mount and use portable distribution
    • Unmount and verify cleanup
  2. Security & Path Validation

    • Verify removable media works without flags
    • Confirm fixed drives are blocked by default
    • Test --allow-fixed flag enables fixed drives
    • Test standard paths (E:\wsl)
    • Test Volume GUID paths (\?\Volume{...})
    • Verify error messages guide users to --allow-fixed
  3. Localization Testing

    • Verify all 7 new messages display correctly
    • Confirm error messages are properly localized
  4. Temporary Flag Tracking

    • Mount with --temporary flag
    • Verify IsTemporary=1 in registry
    • Confirm cleanup removes temporary flag
  5. Multi-Device Testing

    • Create on one machine, use on another
    • Test drive letter changes
    • Verify portability across Windows versions
  6. Edge Cases

    • Mount already-mounted portable distribution
    • Unmount non-portable distribution
    • Handle missing metadata file
    • Handle corrupted VHDX
    • Test fixed drive without --allow-fixed (should fail with helpful message)
  7. Registry Cleanup

    • Verify portable flag in registry
    • Verify temporary flag when used
    • Confirm cleanup after unmount
    • Test multiple portable distributions

Future Enhancements (Out of Scope)

  • Automatic cleanup on drive ejection (foundation laid with temporary flag tracking)
  • Auto-cleanup on reboot/logout for temporary distributions
  • Encryption support for portable distributions (BitLocker integration)
  • Compression options for smaller footprint
  • GUI integration in WSL Settings app
  • Auto-mount on drive insertion
  • Service-side temporary flag monitoring

Documentation Updates Needed

  • User documentation for new commands
  • Examples in WSL documentation
  • Troubleshooting guide for portable distributions
  • Document --allow-fixed flag behavior and security rationale

Examples

Creating a Portable Distribution

PS C:\> wsl --import PortableUbuntu E:\wsl\ ubuntu.tar.gz --portable --vhd
Installing: 100.0%
Portable distribution 'PortableUbuntu' created successfully at 'E:\wsl\'.
The operation completed successfully.

Mounting a Portable Distribution

PS C:\> wsl --mount-removable E:\wsl\ --distro PortableUbuntu
Portable distribution 'PortableUbuntu' successfully mounted from 'E:\wsl\ext4.vhdx'.
The operation completed successfully.

PS C:\> wsl -d PortableUbuntu
user@DESKTOP-ABC:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdc       1007G  123G  833G  13% /

Unmounting a Portable Distribution

PS C:\> wsl --unmount-removable PortableUbuntu
Portable distribution 'PortableUbuntu' successfully unmounted.
The operation completed successfully.

Checklist

  • Code follows WSL coding standards
  • New functionality is properly abstracted
  • Error handling implemented
  • Backward compatibility maintained
  • No breaking changes to existing functionality
  • Commit message follows convention
  • Documentation updated
  • Tests added

This commit implements support for portable WSL distributions that can run
directly from removable media (USB drives, external disks) without requiring
local installation. This feature enables users to carry their complete
development environments on external storage and use them across different
Windows machines without leaving traces on the host system.

Key Changes:

1. New Portable Distribution API (PortableDistribution.h/cpp)
   - Metadata management with JSON-based configuration (wsl-portable.json)
   - Mount/unmount operations for portable distributions
   - Drive type validation with security-focused restrictions (removable media by default)
   - --allow-fixed flag for development/testing on fixed drives
   - Registry-based tracking for portable distribution state and temporary flags

2. Command-Line Interface Extensions
   - wsl --mount-removable <path> - Mount a portable distribution from external media
   - wsl --unmount-removable <distro> - Unmount and cleanup portable distribution
   - wsl --import <name> <path> <file> --portable - Create new portable distribution
   - --allow-fixed flag for both mount and import commands

3. Command-Line Arguments (wsl.h)
   - --mount-removable with -d/--distro, -t/--temporary, and -f/--allow-fixed options
   - --portable flag for import command with optional --allow-fixed
   - --unmount-removable for cleanup operations

4. Localization (Resources.resw)
   - Added 7 new localized message strings for portable operations
   - Proper multi-language support for all user-facing messages
   - Removed temporary inline message helpers

5. Integration (WslClient.cpp)
   - Command routing for new portable operations
   - Proper localization integration with Localization::MessagePortable* calls
   - Error handling for portable-specific scenarios
   - --allow-fixed flag support in command handlers

6. Build System (CMakeLists.txt)
   - Added PortableDistribution.cpp and PortableDistribution.h to build

Technical Implementation:

- Metadata Format: JSON-based storage of distribution configuration including
  name, version, VHDX path, and portable flag
- Drive Validation: Uses Windows GetDriveTypeW() API to verify removable media
  by default, supports Volume GUID paths
- Security: Restricts to DRIVE_REMOVABLE by default; --allow-fixed explicitly
  required for fixed drives
- Transient Registration: Distributions are registered only during active use,
  cleaned up on unmount
- Registry Tracking: Portable flag, base path, and temporary flag stored in
  LXSS registry for state management
- Localization: Full multi-language support using WSL's localization infrastructure
- Error Handling: Comprehensive validation and cleanup on failure scenarios

Benefits:

- True Portability: Run complete Linux environments from any USB drive
- Zero Host Footprint: No local installation or registry traces after unmount
- Cross-Machine Compatibility: Same distribution works on any Windows 10/11
  machine with WSL
- Secure by Default: Restricts to removable media; fixed drives require
  explicit opt-in
- Developer Flexibility: --allow-fixed flag enables testing without removable media
- Temporary Mounts: Support for ephemeral distributions with automatic cleanup tracking

Testing Notes:

- Test on actual removable media (USB 3.0+ recommended)
- Verify Volume GUID path support for drive-letter-agnostic mounting
- Test cross-machine portability with different Windows versions
- Verify proper cleanup leaves no registry artifacts
- Test --allow-fixed flag behavior for development scenarios
- Verify all localized messages display correctly in different languages

Closes microsoft#12804

Signed-off-by: Giovanni Magliocchetti <[email protected]>
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements support for portable WSL distributions that can run directly from removable media without requiring local disk installation. It introduces a complete portable WSL workflow with three new commands and supporting infrastructure to address the lack of true portability and host system contamination issues.

Key changes:

  • Adds three new WSL commands: --mount-removable, --unmount-removable, and --import with --portable flag
  • Implements security-focused path validation restricting to removable media by default with --allow-fixed override
  • Provides comprehensive localization support with 7 new message strings

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/windows/inc/wsl.h Adds command constants and option flags for portable distribution functionality
src/windows/common/WslClient.cpp Implements command handlers, argument parsing, and localization integration for portable operations
src/windows/common/PortableDistribution.h Defines API and data structures for portable WSL distribution management
src/windows/common/PortableDistribution.cpp Core implementation of portable distribution functionality including validation, mounting, and metadata handling
src/windows/common/CMakeLists.txt Adds new portable distribution source files to build system
localization/strings/en-US/Resources.resw Adds 7 new localized message strings for portable distribution operations

// Unregister immediately as we only wanted to create the VHDX
try
{
service.UnregisterDistribution(&guid);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't unregistering the distribution delete the VHDX as well on this code path ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants