Vagrant WSL2 Provider
A Vagrant provider plugin for managing WSL2 distributions on Windows.
Features
- Create and manage WSL2 distributions through Vagrant
- Full snapshot support (save, restore, list, delete)
- Support for WSL2 configuration (memory, CPU, version)
- Integration with Vagrant's standard workflow
- Cross-platform compatible (Windows-focused)
Installation
Install the plugin using:
vagrant plugin install vagrant-wsl2-providerOr install from source:
git clone https://github.com/LeeShan87/vagrant-wsl2-provider.git
cd vagrant-wsl2-provider
gem build vagrant-wsl2-provider.gemspec
vagrant plugin install vagrant-wsl2-provider-0.4.0.gem
# Or
rake install_localUsage
Create a Vagrantfile with the WSL2 provider:
Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu" # Or any WSL2-compatible box
config.vm.provider "wsl2" do |wsl|
wsl.distribution_name = "my-dev-env"
wsl.version = 2
wsl.gui_support = true
end
endThen run:
vagrant up --provider=wsl2Supported Commands
Standard Vagrant Commands
-
vagrant up- Create and start the WSL2 distribution -
vagrant halt- Stop the WSL2 distribution -
vagrant destroy- Remove the WSL2 distribution -
vagrant ssh- Connect to the distribution (interactive shell) -
vagrant ssh -c "command"- Execute a single command and return output -
vagrant provision- Run provisioners -
vagrant reload- Restart the distribution
Example:
vagrant ssh -c "uname -a"
vagrant ssh -c "cat /etc/os-release"Snapshot Management
The WSL2 provider fully supports Vagrant's snapshot functionality:
# List all snapshots
vagrant snapshot list
# Save a snapshot
vagrant snapshot save <name>
# Restore a snapshot
vagrant snapshot restore <name>
# Delete a snapshot
vagrant snapshot delete <name>
# Quick save (auto-generated name)
vagrant snapshot push
# Quick restore last pushed snapshot
vagrant snapshot popExample workflow:
# Save current state before experimenting
vagrant snapshot save clean-install
# Make changes, install packages, etc.
# ...
# Restore to clean state if something breaks
vagrant snapshot restore clean-install
# Delete snapshot when no longer needed
vagrant snapshot delete clean-installSnapshots are stored as .tar files in .vagrant/machines/{name}/wsl2/snapshots/ and contain the complete distribution state.
Configuration
Provider Options
-
distribution_name: Name of the WSL2 distribution (default: auto-generated) -
version: WSL version (1 or 2, default: 2) -
memory: Memory limit in MB (default: 4096) -
cpus: Number of CPUs (default: 2) -
gui_support: Enable WSLg GUI support (default: false)
Requirements
- Windows 10/11 with WSL2 enabled
- Vagrant 2.2+
- WSL2 kernel installed
Development
Setup
After checking out the repo, run:
bundle install
rake install_local # Build and install pluginTesting
Integration tests use Pester 5.x, a PowerShell testing framework.
Prerequisites:
- PowerShell 5.1+ or PowerShell Core 7+
- Pester 5.x (5.0 - 5.7.1, not 6.x alpha)
Install Pester:
Install-Module -Name Pester -RequiredVersion 5.7.1 -Force -Scope CurrentUserOr let Rake handle it automatically:
rake ensure_pester # Check and install Pester if neededRun tests:
# Run all integration tests (auto-checks Pester)
rake test
# Ensure Pester is installed first
rake ensure_pester
# Run individual tests
rake test_basic
rake test_snapshot
rake test_data_disk
rake test_networking
rake test_multi_vm_networkSee test/integration/README.md for more details.
Examples
Example configurations are in the examples/ directory:
-
basic/- Minimal configuration -
snapshot/- Snapshot functionality demo -
provisioners/- Multiple provisioner examples -
docker-test/- Docker with systemd -
test-distros/- Various Linux distributions
See examples/README.md for usage.
Development with Live Reload
For active development, you can create junction points to your working directory so changes are immediately reflected without reinstalling the plugin:
# First, install the plugin once
gem build vagrant-wsl2-provider.gemspec
vagrant plugin install vagrant-wsl2-provider-0.1.0.gem
# Remove the installed lib and locales directories
rmdir "C:\Users\YourUsername\.vagrant.d\gems\3.1.3\gems\vagrant-wsl2-provider-0.1.0\lib"
rmdir "C:\Users\YourUsername\.vagrant.d\gems\3.1.3\gems\vagrant-wsl2-provider-0.1.0\locales"
# Create junction points to your development directories (no admin rights required)
mklink /J "C:\Users\YourUsername\.vagrant.d\gems\3.1.3\gems\vagrant-wsl2-provider-0.1.0\lib" "D:\Code\Github\vagrant-wsl2-provider\lib"
mklink /J "C:\Users\YourUsername\.vagrant.d\gems\3.1.3\gems\vagrant-wsl2-provider-0.1.0\locales" "D:\Code\Github\vagrant-wsl2-provider\locales"Now any changes to lib/ or locales/ in your working directory are immediately visible to Vagrant without reinstalling.
Cleanup Helper Commands
Clean up all WSL distributions (useful for testing):
wsl -l | Select-String -Pattern '\S' | ForEach-Object { $name = $_.Line -replace '\*', '' -replace '\s*\(.*\)', '' -replace '\0', ''; if ($name.Trim()) { wsl --unregister $name.Trim() } }Warning: This removes ALL WSL distributions on your system. Use with caution!
Remove vagrant prefixed distributions only:
wsl -l | Select-String -Pattern '\S' | ForEach-Object { $name = $_.Line -replace '\*', '' -replace '\s*\(.*\)', '' -replace '\0', ''; if ($name.Trim() -like 'vagrant-*') { wsl --unregister $name.Trim() } }Known Issues
Per-Distribution CPU/Memory Limits Not Supported
WSL2 does not support per-distribution CPU and memory limits.
Reference: Microsoft WSL Issue #8570
The memory and cpus configuration options in the Vagrantfile currently do nothing because:
- CPU/memory limits in WSL2 are configured globally in
%USERPROFILE%\.wslconfig - These limits apply to ALL WSL2 distributions simultaneously
- Microsoft has not implemented per-distribution resource limits
config.vm.provider "wsl2" do |wsl|
wsl.memory = 2048 # Currently has no effect
wsl.cpus = 2 # Currently has no effect
endWorkaround: Manually configure global limits in %USERPROFILE%\.wslconfig:
[wsl2]
memory=4GB
processors=2This affects all WSL2 distributions including Docker Desktop and other Vagrant VMs.
Legacy WSL Distributions
Some WSL distributions use the legacy registration system and are not fully supported:
Affected distributions:
- Ubuntu-20.04, Ubuntu-22.04
- OracleLinux_7_9, OracleLinux_8_10, OracleLinux_9_5
Issues:
-
--no-launchflag does not properly register the distribution - Distributions require interactive setup (username/password prompt)
- Provider cannot detect distribution after installation
SUSE Enterprise Distributions
SUSE Linux Enterprise distributions may have guest detection issues:
- SUSE-Linux-Enterprise-15-SP6
- SUSE-Linux-Enterprise-15-SP7
Bleeding Edge Distributions
Very recent distributions may have provisioning issues:
- AlmaLinux-10, AlmaLinux-Kitten-10 (Ansible provisioner fails due to missing EPEL repositories)
Minimal Distributions
Some distributions have minimal installations without common tools:
- archlinux (missing
sudoby default - Ansible provisioner fails)
Tested and Working Distributions
The following distributions are fully tested and working with shell/file/ansible provisioners:
- AlmaLinux-8, AlmaLinux-9
- Debian
- FedoraLinux-42
- Ubuntu, Ubuntu-24.04
- Kali-Linux
- openSUSE-Tumbleweed
Roadmap
v0.3 - Data Disk Support
- Mount VirtualBox data disks in WSL2
- VHD/VMDK to WSL2 format conversion
- Support for development backup workflows
v0.4 - Network Configuration
- Fixed network support for multiple WSL2 distributions
- Network isolation and custom IP configuration
- Port forwarding enhancements
v0.5 - Legacy Distribution Support
- Non-interactive setup for Ubuntu 20.04, 22.04
- Support for Oracle Linux distributions
- Improved compatibility with legacy WSL registration system
Contributing
Bug reports and pull requests are welcome on GitHub.
License
The gem is available as open source under the MIT License.
WSL2 Distribution Lifecycle
Important: WSL2 distributions behave differently from traditional VMs!
Automatic Sleep Mode
- WSL2 distributions automatically enter "stopped" state when no processes are running
- This is normal behavior, not a bug
- Unlike VMs, WSL2 distributions don't stay "running" idle
Vagrant Status Meanings
-
stopped= Distribution exists, no active processes (ready to use) -
running= Distribution has active processes -
not created= Distribution doesn't exist
Typical Workflow
vagrant up --provider=wsl2 # Creates distribution (shows "stopped")
vagrant ssh # Starts shell (shows "running")
exit # Shell closes (returns to "stopped")
vagrant status # Shows "stopped" - this is normal!