Skip to main content
Version: 1.5.0

WSL Configuration Profiles

Status: ✅ Complete
Version: 1.5.0
Platform: Windows only

Overview

thresh includes a comprehensive WSL configuration system that solves common WSL development challenges, particularly the Plan9 filesystem permission issues that break databases like PostgreSQL, MySQL, and Redis.

Why This Matters

WSL's Plan9 filesystem doesn't support chmod operations, causing database permission errors. The database profile solves this completely by disabling Windows interop and automount, forcing workloads to run on native Linux filesystem only.

Key Benefits

  • 🗄️ Database Support - PostgreSQL, MySQL, MongoDB, Redis work without permission errors
  • Optimized Performance - Profile-specific configurations for different workloads
  • 🎯 Easy to Use - Apply profiles with a single blueprint property
  • 🔧 Flexible - Built-in profiles + custom files + inline configuration
  • Validated - Full validation against Microsoft WSL documentation

Built-in Profiles

Database Profile ⭐

Best for: PostgreSQL, MySQL, MongoDB, Redis, Cassandra

Solves Plan9 filesystem permission issues by disabling Windows interop and automount entirely.

[boot]
systemd=true

[interop]
enabled=false
appendWindowsPath=false

[automount]
enabled=false

[network]
generateResolvConf=true

Use this when:

  • Running any database server in WSL
  • Encountering chmod or permission errors
  • Need maximum performance for data-intensive workloads

Docker Profile 🐳

Best for: Docker development environments

Automatically starts Docker daemon when distro boots.

[boot]
systemd=true
command="service docker start"

Web Server Profile 🌐

Best for: Nginx, Apache, Node.js servers

Auto-starts Nginx web server on boot.

[boot]
systemd=true
command="service nginx start"

[network]
generateResolvConf=true
hostname=webserver

Systemd Profile 🚀

Best for: Services requiring systemd

Minimal systemd enablement only.

[boot]
systemd=true

Minimal Profile ⚡

Best for: CI/CD agents, lightweight containers

Fast startup with no systemd overhead.

[boot]
systemd=false

[interop]
enabled=true
appendWindowsPath=false

[network]
generateResolvConf=true

Development Profile 💻

Best for: Full-stack development

Maximum Windows integration for seamless development workflow.

[boot]
systemd=true

[interop]
enabled=true
appendWindowsPath=true

[automount]
enabled=true
root=/mnt/
options="metadata,umask=22,fmask=11"

[network]
generateResolvConf=true
hostname=dev-machine

Quick Start

Using Profiles in Blueprints

The simplest way to use WSL configuration profiles is through blueprints:

{
"name": "postgres-persistent",
"base": "ubuntu:22.04",
"wslConfig": "database",
"packages": ["postgresql-14"],
"volumes": [
{"name": "postgres-data", "mount": "/var/lib/postgresql/data"}
]
}

CLI Commands

thresh wslconf list

Shows all available built-in and custom profiles with descriptions.

Blueprint Integration Methods

thresh supports three ways to configure WSL settings in blueprints, with priority order:

Use a built-in profile by name:

{
"name": "mysql-dev",
"base": "ubuntu:22.04",
"wslConfig": "database",
"packages": ["mysql-server"]
}

2. Custom File

Reference a custom configuration file:

{
"name": "custom-env",
"base": "ubuntu:22.04",
"wslConfigFile": "C:\\Users\\burns\\.thresh\\profiles\\custom.wslconf"
}

3. Inline Configuration

Embed configuration directly in the blueprint:

{
"name": "inline-config",
"base": "ubuntu:22.04",
"wslConfigCustom": "[boot]\nsystemd=true\n\n[network]\nhostname=myhost"
}
Priority Order

If multiple methods are specified, thresh applies configurations in this order: wslConfigCustom (highest) → wslConfigFilewslConfig (lowest)

Auto-Restart Behavior

When thresh applies WSL configuration during provisioning:

  1. Writes configuration to /etc/wsl.conf inside the distro
  2. Stops the distro (wsl --terminate <distro>)
  3. Waits 8 seconds (Microsoft WSL requirement)
  4. Starts the distro (via thresh start)
The 8-Second Rule

WSL requires at least 8 seconds after termination before reapplying configurations. thresh handles this automatically during provisioning.

Custom Profiles

Creating Custom Profiles

Create .wslconf files in your user profile directory:

Location: C:\Users\<YourName>\.thresh\profiles\

Example: team-standard.wslconf

[boot]
systemd=true
command="service postgresql start && service redis-server start"

[interop]
enabled=false
appendWindowsPath=false

[automount]
enabled=false

[network]
generateResolvConf=true
hostname=team-dev

Validation

Always validate custom configurations before use:

thresh wslconf validate C:\Users\burns\.thresh\profiles\team-standard.wslconf

Expected output:

✅ Configuration is valid

Invalid configurations show detailed errors:

❌ Failed to validate file: Arg_KeyNotFoundWithKey, invalidSection

Microsoft WSL Options Reference

Section: [boot]

OptionTypeDescription
systemdboolEnable systemd as init system
commandstringCommand to run at startup

Section: [automount]

OptionTypeDescription
enabledboolEnable automatic mounting of Windows drives
mountFsTabboolEnable /etc/fstab mounting
rootstringMount point for Windows drives (default: /mnt/)
optionsstringMount options (e.g., metadata,umask=22)

Section: [network]

OptionTypeDescription
generateHostsboolGenerate /etc/hosts file
generateResolvConfboolGenerate /etc/resolv.conf file
hostnamestringHostname for the distro

Section: [interop]

OptionTypeDescription
enabledboolEnable Windows interoperability
appendWindowsPathboolAdd Windows PATH to Linux PATH

Section: [user]

OptionTypeDescription
defaultstringDefault user for the distro

Section: [gpu]

OptionTypeDescription
enabledboolEnable GPU access (WSLg)

Section: [time]

OptionTypeDescription
synchronizeboolSync time with Windows host
Full Reference

For the complete Microsoft WSL configuration documentation, run:

thresh wslconf options

Real-World Examples

Example 1: PostgreSQL Development

{
"name": "postgres-dev",
"base": "ubuntu:22.04",
"wslConfig": "database",
"packages": ["postgresql-14", "postgresql-client-14"],
"volumes": [
{"name": "postgres-data", "mount": "/var/lib/postgresql/data"}
]
}

Why database profile?

  • Disables Plan9 filesystem (no chmod errors)
  • Removes Windows path pollution
  • Optimizes for data-intensive operations

Example 2: Full-Stack Web Development

{
"name": "fullstack-dev",
"base": "ubuntu:22.04",
"wslConfig": "development",
"packages": [
"nodejs",
"npm",
"python3-pip",
"git",
"curl"
],
"ports": ["3000:3000", "8080:8080"],
"volumes": [
{"name": "node-modules", "mount": "/workspace/node_modules"}
]
}

Why development profile?

  • Full Windows PATH integration
  • Can call Windows tools from Linux
  • Automatic Windows drive mounting at /mnt/c

Example 3: Docker Development Environment

{
"name": "docker-dev",
"base": "ubuntu:22.04",
"wslConfig": "docker",
"packages": [
"docker.io",
"docker-compose"
]
}

Why docker profile?

  • Auto-starts Docker daemon on boot
  • No manual service docker start needed

Example 4: Team-Specific Configuration

Custom profile: C:\Users\burns\.thresh\profiles\acme-corp.wslconf

[boot]
systemd=true
command="/opt/acme/startup.sh"

[network]
hostname=acme-dev
generateResolvConf=false

[user]
default=acmeuser

Blueprint:

{
"name": "acme-project",
"base": "ubuntu:22.04",
"wslConfigFile": "C:\\Users\\burns\\.thresh\\profiles\\acme-corp.wslconf",
"packages": ["custom-tools"]
}

Troubleshooting

Database Permission Errors

Problem: PostgreSQL/MySQL fails with permission errors like:

chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted

Solution: Use the database profile which disables Windows filesystem integration:

{
"wslConfig": "database"
}

Configuration Not Applied

Problem: Changes to wsl.conf don't take effect.

Solution: WSL requires distro restart. thresh handles this automatically during provisioning, but for manual changes:

thresh stop <env-name>
# Wait 8 seconds
thresh start <env-name>

Or use Windows WSL command:

wsl --terminate <distro-name>

Invalid Configuration

Problem: Custom configuration not working.

Solution: Validate before using:

thresh wslconf validate my-config.wslconf

Common issues:

  • Invalid section names (must be: boot, automount, network, interop, user, gpu, time)
  • Invalid key names within sections
  • Boolean values must be true or false (not yes/no or 1/0)

Profile Not Found

Problem: Error: Profile 'xyz' not found

Solution: List available profiles:

thresh wslconf list

Ensure custom profiles are in: C:\Users\<YourName>\.thresh\profiles\

Technical Details

Platform Detection

The wslconf command is Windows-only and automatically hidden on Linux and macOS:

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
rootCommand.AddCommand(wslConfCommand);
}

Linux and macOS users won't see this command in help output.


Validation Engine

thresh validates configurations against all 7 Microsoft WSL sections:

  1. boot - systemd, command
  2. automount - enabled, mountFsTab, root, options
  3. network - generateHosts, generateResolvConf, hostname
  4. interop - enabled, appendWindowsPath
  5. user - default
  6. gpu - enabled
  7. time - synchronize

Type validation:

  • Boolean keys expect true or false
  • String keys accept any value
  • Unknown sections/keys are rejected

Embedded Resources

All 6 built-in profiles are embedded in the thresh Native AOT binary:

ProfileSizeLocation
systemd88 BProfiles/systemd.wslconf
docker188 BProfiles/docker.wslconf
database355 BProfiles/database.wslconf
web-server250 BProfiles/web-server.wslconf
minimal238 BProfiles/minimal.wslconf
development350 BProfiles/development.wslconf
Total1,469 B(1.5 KB)

No external files required - all profiles ship with the binary.


Provisioning Integration

WSL configuration is Step 6 of 7 in the provisioning flow:

Use Cases

✅ When to Use WSL Configuration

  • Running databases (PostgreSQL, MySQL, MongoDB, Redis)
  • Need systemd for services
  • Want auto-start services on boot
  • Optimizing performance for specific workloads
  • Team standardization across developers
  • CI/CD agents with minimal overhead
  • Fixing Plan9 filesystem permission errors

⚠️ When NOT to Use

  • Not on Windows (feature is Windows/WSL-specific)
  • Default settings work fine for your use case
  • Don't need any custom WSL behavior
  • Working with Docker on Linux (use container configs instead)

Best Practices

1. Use Built-in Profiles First

Start with a built-in profile and only create custom profiles if needed:

{
"wslConfig": "database" // ✅ Good - Use built-in
}

2. Validate Custom Configurations

Always validate before deploying:

thresh wslconf validate my-profile.wslconf

3. Document Custom Profiles

Add comments to explain your configuration:

# ACME Corp Standard Development Environment
# Owner: devops@acme.com
# Updated: 2026-02-27

[boot]
systemd=true
command="/opt/acme/startup.sh"

[network]
hostname=acme-dev # Standardized hostname for team

4. Version Control

Store custom profiles in your repository:

.thresh/
profiles/
team-standard.wslconf
production-db.wslconf
ci-agent.wslconf

5. Test Changes

After modifying configurations:

# Validate
thresh wslconf validate new-config.wslconf

# Test in isolated environment
thresh up test-env --wslConfigFile new-config.wslconf

# Verify
thresh exec test-env -- cat /etc/wsl.conf

# Clean up
thresh destroy test-env

Future Enhancements

Planned Features

  • 📋 Profile templates generator
  • 🔍 Configuration diff tool
  • 📊 Performance benchmarking per profile
  • 🌐 SaaS integration for team profile sharing
  • 📦 Profile marketplace

Additional Resources


Need Help?

For questions or issues with WSL configuration, please open an issue on GitHub.