Automated provisioning script for creating reproducible WSL Ubuntu Jammy environments with gui-dotfiles.
This script provides a fully automated, reproducible way to:
- Test dotfiles changes - Quickly spin up fresh Ubuntu instances to test your dotfiles configurations
- Ensure idempotence - Verify that installation scripts can run multiple times safely
- Maintain consistency - Create identical development environments across machines
- Rapid iteration - Nuke and recreate distros in minutes during development
- Clean slate testing - Start from a minimal Ubuntu Core image without cruft
Instead of manually configuring WSL distros and hoping scripts work, this approach lets you:
# Destroy and recreate in one command
wsl --unregister UbuntuTest
.\wsl\run.ps1 -DistroName "UbuntuTest" -TargetDirectory "D:\linux\test-ubuntu"- Windows 11 or Windows 10 with WSL2 enabled
- WSL installed: Run
wsl --versionto verify - PowerShell 5.1+ (comes with Windows)
- Internet connection for downloading Ubuntu image and packages
# Run as Administrator
wsl --installRestart your computer after installation.
.\wsl\run.ps1 -DistroName "UbuntuTest" -TargetDirectory "D:\linux\test-ubuntu"This creates:
- User:
guinetik - Password:
123 - Sudo: NOPASSWD enabled (no password needed for sudo)
.\wsl\run.ps1 `
-DistroName "UbuntuDev" `
-TargetDirectory "D:\linux\dev-ubuntu" `
-UserName "myuser" `
-UserPassword "mypassword"| Parameter | Required | Default | Description |
|---|---|---|---|
DistroName |
✅ Yes | - | Name for the WSL distro |
TargetDirectory |
✅ Yes | - | Where to store the WSL filesystem |
UserName |
❌ No | guinetik |
Username to create in WSL |
UserPassword |
❌ No | 123 |
Password for the user |
ImageUrl |
❌ No | Ubuntu Jammy Core | URL to Ubuntu cloud image |
The provisioning process follows these steps:
- Downloads minimal Ubuntu 22.04 (Jammy) cloud image (~50MB)
- Saves to target directory for import
- Imports the Ubuntu image as a new WSL distro
- Creates isolated filesystem in
<TargetDirectory>/rootfs
- Creates specified user with bash shell
- Adds user to sudo group
- Configures NOPASSWD sudo access
- Sets user password
- Updates apt package lists
- Installs essential packages:
sudo,curl,wget,gitca-certificates,dos2unixlocales(fixes Perl warnings)
- Generates
en_US.UTF-8locale - Verifies all installations
- Creates
/etc/wsl.confwith default user - Enables systemd (for Docker, etc.)
- Restarts distro for changes to take effect
- Verifies sudo access works
- Creates symlink from Windows path to
~/gui-dotfilesin WSL - Enables direct editing from Windows while running in WSL
- Runs
dos2unixon all.shfiles - Ensures scripts run correctly in Linux environment
- Executes
distros/ubuntu/install.sh - Installs all configured tools and settings
- Creates installation tracking files
After provisioning, you'll have:
<TargetDirectory>/
├── rootfs/ # WSL filesystem (managed by WSL)
│ ├── home/
│ │ └── <username>/
│ │ └── gui-dotfiles -> (symlink to Windows path)
│ ├── etc/
│ └── ...
└── jammy-wsl.tar.gz # Downloaded Ubuntu image (can be deleted)
Inside WSL:
~/gui-dotfiles/ # Symlinked to Windows repository
~/.local/share/gui-dotfiles/ # Installation tracking files
├── .installed # Master tracking file
├── docker.info
├── zoxide.info
└── ...
wsl -d UbuntuTestwsl -d UbuntuTest -u guinetikwsl -d UbuntuTest bash -c "cd ~/gui-dotfiles && git status"wt -d UbuntuTestProblem: WSL is not enabled on your system.
Solution:
# Run as Administrator
wsl --install
# Restart computerProblem: A distro with that name already exists.
Solution: The script will prompt to unregister. Or manually:
wsl --unregister UbuntuTestProblem:
- Not enough disk space
- Target directory is invalid
- Downloaded image is corrupted
Solutions:
- Check available disk space
- Delete the
.tar.gzfile and re-run - Try a different target directory
- Verify download completed (should be ~50MB)
Problem: User doesn't have NOPASSWD sudo access.
Solution: This should not happen with the script. If it does:
# Inside WSL as root
echo "guinetik ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/guinetik
sudo chmod 0440 /etc/sudoers.d/guinetikProblem: Symlink path is incorrect.
Solution: Check the symlink inside WSL:
ls -la ~/gui-dotfiles
# Should show: gui-dotfiles -> /mnt/d/Developer/gui-dotfilesIf broken, recreate:
ln -sf /mnt/d/Developer/gui-dotfiles ~/gui-dotfilesProblem: Windows line endings (CRLF) instead of Unix (LF).
Solution: The script runs dos2unix automatically. If you still see issues:
cd ~/gui-dotfiles
find . -type f -name "*.sh" -exec dos2unix {} \;Problem: Some installers prompt for password even with NOPASSWD sudo.
Solution: The user password is set (default: 123). Enter it when prompted:
# When prompted for password
Password: 123Or pass a custom password to the script:
.\wsl\run.ps1 -DistroName "Test" -TargetDirectory "D:\test" -UserPassword "mysecurepass"Problem: Essential tools not installed during system initialization.
Solution: Re-run as root inside WSL:
# Access distro as root
wsl -d UbuntuTest -u root
# Update and install essentials
apt-get update
apt-get install -y sudo curl wget git dos2unix localesProblem: Docker installer may explicitly request password.
Solution: This is expected behavior for some installers. Use the password you set:
- Default:
123 - Custom: Whatever you passed to
-UserPassword
Problem: Locale not properly configured.
Solution: The script generates locales automatically. If you still see warnings:
sudo locale-gen en_US.UTF-8
sudo update-locale LANG=en_US.UTF-8Restart your WSL session after this.
Problem: If you have Windows sudo (Scoop/Chocolatey) in PATH, it may conflict.
Solution:
- Remove Windows sudo from PATH temporarily
- Or the scripts use
/usr/bin/sudoexplicitly to avoid this
# 1. Make changes to your dotfiles
git commit -am "Test new configuration"
# 2. Nuke existing test distro
wsl --unregister UbuntuTest
# 3. Recreate from scratch
.\wsl\run.ps1 -DistroName "UbuntuTest" -TargetDirectory "D:\linux\test-ubuntu"
# 4. Test your changes
wsl -d UbuntuTestCreate separate distros for different purposes:
# Minimal test
.\wsl\run.ps1 -DistroName "UbuntuMinimal" -TargetDirectory "D:\linux\minimal"
# Full development environment
.\wsl\run.ps1 -DistroName "UbuntuDev" -TargetDirectory "D:\linux\dev"
# Production-like setup
.\wsl\run.ps1 -DistroName "UbuntuProd" -TargetDirectory "E:\linux\prod"List all distros:
wsl -l -v# Remove a distro
wsl --unregister UbuntuTest
# Remove distro and delete files
wsl --unregister UbuntuTest
Remove-Item -Recurse -Force "D:\linux\test-ubuntu"# Export to tar file
wsl --export UbuntuDev D:\backups\ubuntu-dev-backup.tar
# Restore later
wsl --import UbuntuDev D:\linux\dev-restored D:\backups\ubuntu-dev-backup.tarIf an installation step fails, you can manually enter the distro and debug:
# Enter as your user
wsl -d UbuntuTest
# Enter as root
wsl -d UbuntuTest -u rootCheck installation logs:
# View tracking files
cat ~/.local/share/gui-dotfiles/.installed
# Check which tools are tracked
ls ~/.local/share/gui-dotfiles/Manually run specific installation scripts:
cd ~/gui-dotfiles/common
./install_zoxide.sh
./install_starship.shIf downloads fail due to network issues, you can:
-
Download image manually:
- Download from: https://partner-images.canonical.com/core/jammy/
- Place in target directory as
jammy-wsl.tar.gz - Re-run script (it will skip download if file exists)
-
Use corporate proxy:
# Set proxy before running $env:HTTP_PROXY="http://proxy.corp.com:8080" $env:HTTPS_PROXY="http://proxy.corp.com:8080" .\wsl\run.ps1 ...
If you only want to set up the distro without running the full installation:
When prompted with:
Continue with installation? (Y/n)
Answer n to skip. You can run it manually later:
wsl -d UbuntuTest
cd ~/gui-dotfiles/distros/ubuntu
./install.shThe installation scripts support these environment variables:
YOLO_MODE=true- Auto-answer "yes" to all promptsINSTALL_TRACKER_DIR- Custom location for tracking filesPATH- Automatically updated with~/.local/bin,~/.cargo/bin, etc.
- Main README - Overview of gui-dotfiles
- Ubuntu Install Script - Ubuntu-specific setup
- Common Scripts - Shared installation scripts
When modifying provisioning scripts:
- Test with fresh distro: Always test by nuking and recreating
- Check idempotence: Run scripts twice to ensure they handle re-runs
- Use tracking system: Leverage
is_app_installed()and tracking files - Document changes: Update this README with any new features or gotchas
Same as gui-dotfiles repository.