NixOS-WSL
Modules for running NixOS on the Windows Subsystem for Linux
Documentation is available here
Quick Start
- Enable WSL if you haven't done already:
-
wsl --install --no-distribution
-
Download
nixos-wsl.tar.gz
from the latest release. -
Import the tarball into WSL:
-
wsl --import NixOS $env:USERPROFILE\NixOS\ nixos-wsl.tar.gz
- You can now run NixOS:
-
wsl -d NixOS
For more detailed instructions, refer to the documentation.
License
Apache License, Version 2.0. See LICENSE
or http://www.apache.org/licenses/LICENSE-2.0.html for details.
Installation
System requirements
NixOS-WSL is tested with the Windows Store version of WSL 2, which is now available on all supported Windows releases (both 10 and 11). Support for older "inbox" versions is best-effort.
Install NixOS-WSL
First, download the latest release.
Then open up a PowerShell and run:
wsl --import NixOS $env:USERPROFILE\NixOS\ nixos-wsl.tar.gz
Or for Command Prompt:
wsl --import NixOS %USERPROFILE%\NixOS\ nixos-wsl.tar.gz
This sets up a new WSL distribution NixOS
that is installed in a directory called NixOS
inside your user directory.
nixos-wsl.tar.gz
is the path to the file you downloaded earlier.
You can adjust the installation path and distribution name to your liking.
To get a shell in your NixOS environment, use:
wsl -d NixOS
If you chose a different name for your distro during import, adjust this command accordingly.
Post-Install
After the initial installation, you need to update your channels once, to be able to use nixos-rebuild
:
sudo nix-channel --update
If you want to make NixOS your default distribution, you can do so with
wsl -s NixOS
Design
Getting NixOS to run under WSL requires some workarounds:
- instead of directly loading systemd, we use a small shim that runs the NixOS activation scripts first
- some additional binaries required by WSL's internal tooling are symlinked to FHS paths on activation
Running on older WSL versions also requires a workaround to spawn systemd by hijacking the root shell and
spawning a container with systemd inside. This method of running things is deprecated and not recommended,
however still available as nixos-wsl-legacy.tar.gz
or via wsl.nativeSystemd = false
.
Building your own system tarball
This requires access to a system that already has Nix installed. Please refer to the Nix installation guide if that's not the case.
If you have a flakes-enabled Nix, you can use the following command to build your own tarball instead of relying on a prebuilt one:
sudo nix run github:nix-community/NixOS-WSL#nixosConfigurations.modern.config.system.build.tarballBuilder
Or, if you want to build with local changes, run inside your checkout:
sudo nix run .#nixosConfigurations.your-hostname.config.system.build.tarballBuilder
Without a flakes-enabled Nix, you can build a tarball using:
nix-build -A nixosConfigurations.mysystem.config.system.build.tarballBuilder && sudo ./result/bin/nixos-wsl-tarball-builder
The resulting tarball can then be found under nixos-wsl.tar.gz
.
How-To
How to configure NixOS-WSL with flakes?
First add a nixos-wsl
input, then add nixos-wsl.nixosModules.default
to your nixos configuration.
Below is a minimal flake.nix
for you to get started:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
};
outputs = { self, nixpkgs, nixos-wsl, ... }: {
nixosConfigurations = {
nixos = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
nixos-wsl.nixosModules.default
{
system.stateVersion = "24.05";
wsl.enable = true;
}
];
};
};
};
}
Troubleshooting
This section contains information on how to debug your NixOS-WSL installation.
Recovery Shell
A recovery shell can be started with
wsl -d NixOS --system --user root -- /mnt/wslg/distro/bin/nixos-wsl-recovery
This will load the WSL "system" distribution, activate your configuration,
then chroot into your NixOS system, similar to what nixos-enter
would do
on a normal NixOS install.
You can choose an older generation to load with
wsl -d NixOS --system --user root -- /mnt/wslg/distro/bin/nixos-wsl-recovery --system /nix/var/nix/profiles/system-42-link
(note that the path is relative to the new root)
wsl.enable
Whether to enable support for running NixOS as a WSL distribution.
Type: boolean
Default:
false
Example:
true
Declared by:
wsl.defaultUser
The name of the default user
Type: string
Default:
"nixos"
Declared by:
wsl.docker-desktop.enable
Whether to enable Docker Desktop integration.
Type: boolean
Default:
false
Example:
true
Declared by:
wsl.extraBin
Additional files to be added to /bin
Type: list of (submodule)
Declared by:
wsl.extraBin.*.copy
Whether or not the file should be copied instead of symlinked
Type: boolean
Default:
false
Declared by:
wsl.extraBin.*.name
The name the file should be created as in /bin
Type: string
Default:
baseNameOf src
Declared by:
wsl.extraBin.*.src
Path of the file that should be added
Type: string
Declared by:
wsl.interop.includePath
Include Windows PATH in WSL PATH
Type: boolean
Default:
true
Declared by:
wsl.interop.register
Explicitly register the binfmt_misc handler for Windows executables
Type: boolean
Default:
false
Declared by:
wsl.nativeSystemd
Use native WSL systemd support
Type: boolean
Default:
true
Declared by:
wsl.startMenuLaunchers
Whether to enable shortcuts for GUI applications in the windows start menu.
Type: boolean
Default:
false
Example:
true
Declared by:
wsl.tarball.configPath
Path to system configuration which is copied into the tarball
Type: null or path
Default:
null
Declared by:
wsl.usbip.enable
Whether to enable USB/IP integration.
Type: boolean
Default:
false
Example:
true
Declared by:
wsl.usbip.autoAttach
Auto attach devices with provided Bus IDs.
Type: list of string
Default:
[ ]
Example:
[
"4-1"
]
Declared by:
wsl.usbip.snippetIpAddress
This snippet is used to obtain the address of the Windows host where Usbipd is running. It can also be a plain IP address in case networkingMode=mirrored or wsl-vpnkit is used.
Type: string
Default:
"$(ip route list | sed -nE 's/(default)? via (.*) dev eth0 proto kernel/2/p')"
Example:
"127.0.0.1"
Declared by:
wsl.useWindowsDriver
Whether to enable OpenGL driver from the Windows host.
Type: boolean
Default:
false
Example:
true
Declared by:
wsl.wslConf.automount.enabled
Automatically mount windows drives under /mnt
Type: boolean
Default:
true
Declared by:
wsl.wslConf.automount.ldconfig
Wether to modify /etc/ld.so.conf.d/ld.wsl.conf
to load OpenGL drivers provided by the Windows host in /usr/lib/wsl/lib
with /sbin/ldconfig
.
This way of providing OpenGL drivers does not work with NixOS and wsl.useWindowsDriver
should be used instead.
Type: boolean
Default:
false
Declared by:
wsl.wslConf.automount.mountFsTab
Mount entries from /etc/fstab through WSL. You should probably leave this on false, because systemd will mount those for you.
Type: boolean
Default:
false
Declared by:
wsl.wslConf.automount.options
Comma-separated list of mount options that should be used for mounting windows drives.
Type: strings concatenated with “,”
Default:
"metadata,uid=1000,gid=100"
Declared by:
wsl.wslConf.automount.root
The directory under which to mount windows drives.
Type: string matching the pattern ^/.*[^/]$
Default:
"/mnt"
Declared by:
wsl.wslConf.boot.command
A command to run when the distro is started.
Type: string
Default:
""
Declared by:
wsl.wslConf.boot.systemd
Use systemd as init. There’s no need to enable this manually, use the wsl.nativeSystemd option instead
Type: boolean
Default:
false
Declared by:
wsl.wslConf.interop.enabled
Support running Windows binaries from the linux shell.
Type: boolean
Default:
true
Declared by:
wsl.wslConf.interop.appendWindowsPath
Include the Windows PATH in the PATH variable
Type: boolean
Default:
true
Declared by:
wsl.wslConf.network.generateHosts
Generate /etc/hosts through WSL
Type: boolean
Default:
true
Declared by:
wsl.wslConf.network.generateResolvConf
Generate /etc/resolv.conf through WSL
Type: boolean
Default:
true
Declared by:
wsl.wslConf.network.hostname
The hostname of the WSL instance
Type: string
Default:
"config.networking.hostName"
Declared by:
wsl.wslConf.user.default
Which user to start commands in this WSL distro as
Type: string
Default:
"root"
Declared by: