NixOS WSL on Corporate Networks
Abstract
Last year I started exclusively using Guix System on my personal computers and fell in love with it. Since then I’ve started to grow a bit “bored” with more traditional GNU/Linux system, and whenever I have to use one I quickly start missing the declarative nature of configuring guix/nix systems.
Until very recently I’ve been stuck using openSUSE Tumbleweed via WSL2 on my work laptop (since I have no option for anything other than Windows). It’s worked well and I still think Tumbleweed is a great distro, but like I said, I was just a bit bored of it.
At first I obviosuly looked into using Guix System on WSL2, which is possible via the “WSL2” image type that guix offers. But, I deemed it a bit of a hassle, mostly because there are no pre-built images available. If you didn’t know, you can see available image types by running:
guix system image --list-image-types
Anyway, around the same time I saw that there are community built WSL2 NixOS images available via the NixOS-WSL project. Not only that, but they also provide WSL-related configuration options for NixOS. So, this was the easier starting point. I think most of my colleagues would be more interested in Nix over Guix, anyhow.
Challanges
The main challanges on my corporate network are these:
- A corporate HTTP proxy for all outgoing traffic.
- The proxy handles authentication via NTLM.
- The proxy serves a TLS certificate signed by an in-house CA.
Installation
The Proxy
First of all, setting HTTP_PROXY and HTTPS_PROXY in Linux, as per usual, doesn’t work very well with NTLM.
To get around this I installed a proxy on the Windows host that handle authentication with the upstream proxy, then
I just use that one via HTTP_PROXY and HTTPS_PROXY in Linux.
My proxy of choice is Px, because it’s very easy to setup. We just need to download it and change one line in the config file (px.ini).
[proxy]
; NTLM server(s) to connect through. IP:port, hostname:port
; Multiple proxies can be specified comma separated. Px will iterate through
; and use the one that works
server = http://proxy.example.com:8080
...
Then start it with:
.\px.exe
Now Px should be running and is listening on the default host and port.
Install NixOS
- Download the latest release image of NixOS-WSL.
- Install the image with:
wsl --install --from-file nixos.wsl - Start NixOS with:
wsl -d NixOS
Now that NixOS is started we can finally start configuring it.
We’ll start by (temporarily) telling NixOS to use our proxy (documentation).
# Set HTTP proxy to the Px proxy we installed earlier
proxy_url="http://localhost:3128/"
export http_proxy="$proxy_url"
export HTTP_PROXY="$proxy_url"
export https_proxy="$proxy_url"
export HTTPS_PROXY="$proxy_url"
Before continuing, you’ll need to check if your upstream corporate HTTP proxy serves a custom TLS certificate. This can easily be done by just checking if you get any SSL/TLS issues when requesting a regular website.
curl https://duckduckgo.com
If you get any errors with the previous command, you’ll have to fetch a copy of whatever public CA certificate is used to trust your proxy’s TLS certificate.
From here I’ll assume you have all CA certificates you need in a file called ca.pem.
Now we need to update NixOS.
# Let's temporarily trust our CA certificate
# https://nix.dev/manual/nix/2.28/installation/env-variables.html?highlight=certi#nix_ssl_cert_file
export NIX_SSL_CERT_FILE=/path/to/ca.pem
# Update NixOS
# We'll use 'sudo -E' to preserve the environment variables we just set
sudo -E nix-channel -v --update
Note: If your upstream proxy has any kind of malware scanning (like mine does), the update can potentially take a very long time. For me it took about ~60 minutes.
Configure NixOS
Now it’s time to configure NixOS for real. I’ll provide you with a simple NixOS and home-manager configuration that you can build upon later.
I’ve based these configs on the excellent minimal nix-starter-config provided by Misterio77 on GitHub.
The structure:
.
├── flake.nix # The "init" file
├── home-manager
│ └── home.nix # Home configuration
└── nixos
└── configuration.nix # System configuration
I’ll assume the hostname is nixos and the user account is nixos, which are both default in NixOS-WSL.
flake.nix:
{
description = "NixOS config for WSL2";
inputs = {
# Nixpkgs
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
# NixOS WSL
nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
# Home manager
home-manager.url = "github:nix-community/home-manager/release-25.11";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = {
self,
nixpkgs,
nixos-wsl,
home-manager,
...
} @ inputs: let
in {
# NixOS configuration entrypoint
# Available through 'nixos-rebuild --flake .#nixos'
nixosConfigurations = {
nixos = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = {inherit inputs;};
modules = [
./nixos/configuration.nix
nixos-wsl.nixosModules.default
{
system.stateVersion = "25.11";
wsl.enable = true;
}
];
};
};
# Standalone home-manager configuration entrypoint
# Available through 'home-manager --flake .#nixos@nixos'
homeConfigurations = {
"nixos@nixos" = home-manager.lib.homeManagerConfiguration {
# Home-manager requires 'pkgs' instance
pkgs = nixpkgs.legacyPackages.x86_64-linux; # FIXME replace x86_64-linux with your architecture
extraSpecialArgs = {inherit inputs;};
modules = [./home-manager/home.nix];
};
};
};
}
home.nix:
# This is your home-manager configuration file
# Use this to configure your home environment (it replaces ~/.config/nixpkgs/home.nix)
{
inputs,
lib,
config,
pkgs,
...
}: {
nixpkgs = {
config = {
# Disable if you don't want unfree packages
allowUnfree = true;
};
};
home = {
username = "nixos";
homeDirectory = "/home/nixos";
};
programs.home-manager.enable = true;
# https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
home.stateVersion = "25.11";
}
configuration.nix:
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
# NixOS-WSL specific options are documented on the NixOS-WSL repository:
# https://github.com/nix-community/NixOS-WSL
{ config, lib, pkgs, ... }:
{
wsl.enable = true;
wsl.defaultUser = "nixos";
wsl.startMenuLaunchers = true;
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It's perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "25.11"; # Did you read the comment?
networking.proxy.default = "http://127.0.0.1:3128";
# FIXME replace with your actual no_proxy settings
networking.proxy.noProxy = "localhost,127.0.0.1,mycompany.com";
security.pki.certificates = [
# FIXME replace with your actual company CA certificate
# The certificate(s) for your corporate proxy
''
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
''
];
}
Now that we have the configuration files we can configure evertyhing.
I’ll assume your configuration files are in a directory called /home/nixos/.dotfiles, with the exact directory structure I showed above.
# We'll enable experimental nix features (only needs doing once)
export NIX_CONFIG="experimental-features = nix-command flakes"
# Configure the system
sudo -E nixos-rebuild switch --flake /home/nixos/.dotfiles#nixos
# Bootstrap home-manager (only needs doing once)
nix shell nixpkgs#home-manager
# Configure home
home-manager switch --flake /home/nixos/.dotfiles#nixos@nixos
Alright, now it’s all done! Assuming you correctly setup the proxy config and TLS config in configuration.nix, you should now have a working NixOS container in WSL.
In the future you can just build upon configuration.nix and home.nix for further configuration.
You should also preferably put everything in a version controlled git repository, for safe-keeping.
Conclusion
As you can see, and depending on your companys networking, it’s not just plug-and-play with NixOS for WSL. But, it’s not exactly rocket science either.
I’ve been using NixOS on WSL based on this setup for a while now, and I love using it.
Of course, I would still want to try out Guix System for WSL as well, but it looks like it’s a fair amount of extra work to get it working. Mostly because I’ll have to write a working config (proxy/TLS and all that) and then build an image based on it before I can even install it in WSL. But that will probably be a future blog post. 🙂
Enjoy NixOS!