Sometimes the little details are hard


I use Tailscale to connect all of my machines and devices together. I don't have open ports in my firewall, so it's one less thing to worry about from a security perspective. I can start the daemon on my iPad and then connect to any of my machines in my home network just as if I were at home (or stream games from my desktop via Steam Link).


The most powerful machine in the house is my desktop. It's got an i9-9900K processor, 64GB of DDR4 RAM, and an nVidia RTX 3090 graphics card. Generally speaking, the "primary" purpose of the machine is to play games. Because of "games", it runs Windows 11. I can concur that Linux is more than capable of running just about any game out there using Wine or Proton, I have a different experience with streaming.

For one thing, graphical displays are not exactly standardized on Linux. Some distributions use Wayland and some use Xorg. Wayland can handle mixtures of HiDPI and LoDPI screens somewhat better than Xorg, but Xorg can stream better. Streaming is a big deal for me, since my desktop is squirreled away in my office away from the rest of my family. If I want to play games and socialize, I have to stream.

In my experience, I can have a good desktop experience with using Wayland or I can have a good streaming experience (but a very wonky desktop) using Xorg. Thus, Windows.

Development Work

Using Windows isn't much of a problem these days. With WSL2, I can run any mainstream distribution I want and get pretty much the entire experience that I need for doing any sort of software development. I don't need a graphical environment in Linux to be productive; I primarily use the command-line interface. With recent WSL advances, you can even run systemd! This simple fact lets me run background processes in WSL: tailscaled.


To manage my machines, I use SSH-over-Tailscale. For Windows, though, I really don't need a CLI interface to Windows. I don't do any sort of Windows command line tomfoolery, so all I really want is to SSH to my primary WSL container. I found a Powershell script that would manually open firewall ports and forward all traffic from an arbitrary port on the machine to the WSL virtual machine, but if the VM ever changed IP addresses (which was frequently), I would have to run the script again. This would be troubling if I were anywhere outside the home. Once I adopted Tailscale, I changed all of my Ansible automation to rewrite my ~/.ssh/config files to use the new Tailscale-hosted DNS entries. Even on my hard-wired desktop machines, I use Tailscale to SSH around.


When I initially installed the daemon in WSL (Fedora 37 for anyone that cares) and templated my SSH config file again, I lost the ability to SSH to my normal hosts. I could SSH to specific private IP addresses okay, but not the new tailscale entries. The tailscale dashboard showed WSL in the list of instances correctly, but I couldn't pass any traffic, really.

Differences of opinion

When it came right down to it, I discovered that WSL was using an MTU (1280) that would not allow a Tailscale packet to be encoded and sent in a single packet. I am not the only person[0] to have noticed[1] this. The eventual solution[2] was to have WSL run a command on boot that is configured inside of the VM in /etc/wsl.conf.

All in all, there were a lot of ducks to get into a row in order to make this whole process feasible:

  1. WSL needed systemd support.
  2. Other people had to try and use SSH-over-VPN in WSL.
  3. WSL needs to be able to have arbitrary commands run on boot.