heads or tails

For a long time I have been using OpenVPN to maintain a connection between my devices and my home network when away.

OpenVPN served me well, however an upgrade has been on my todo list for awhile. My intention was always to switch to WireGuard, then after hearing so many great reviews of Tailscale I decided to look into it.

According to their documentation Tailscale is based on the WireGuard protocol, creating a peer-to-peer mesh between the devices.

As I work from home and rarely travel I haven’t needed my VPN much recently. The main use case for this change was to set up mine and my wife’s mobile devices so that we can both use our Nextcloud instance and LocalSend when out of the house.

When the stars aligned and I finally got a chance to make the jump I was excited. Right up until I got to the Tailscale login screen.

I was presented with a choice of OpenID Connect (OIDC) options, only one of which I actually had, that being Github. I haven’t really used Github since I migrated to my own git server and Gitlab, I didn’t really want to start using it to login on my wife’s devices.

Instead I decided to look into Headscale which is “a self-hosted implementation of the Tailscale control server”. I created a Debian LXC container on my server and went about installing Headscale.

This is no substitute for the official docs, but look at how easy it is.

You will need a domain pointing to your Headscale instance. If you are running Headscale behind a firewall open port 443 and point it to your instance on your chosen port.

Download the latest .deb pack from the releases page and install

dpkg -i ./headscale_0.22.3_linux_amd64.deb

Edit the config file for your own use case

vim /etc/headscale/config.ymal

Apart from the server_url I didn’t change much. I did switch the ACME challenge type for Let’s Encrypt to TLS-ALPN-01 so I didn’t have to open port 80 on my external firewall.

Enable and start the service

systemctl enable headscale
systemctl start headscale

That’s it.

Then using the headscale command line tool create a new user

headscale users create <username>

To connect devices to Headscale you can use the normal Tailscale apps. On my Arch Linux system I installed Tailscale from the repo. Connecting is via the tailscale command (don’t forget to start the daemon), and I specified my Headscale domain as the login server

tailscale up --login-server https://<headscale_domain>.tld

This will generate a link to open in your browser, which shows the command to run on Headscale in order to authenticate the device.

Once succeeded confirm by looking at the list of nodes

headscale nodes list

If you want to add an LXC container, before installing Tailscale you have to allow TUN device creation otherwise the daemon will fail to start correctly. In your containers config file add the following

lxc.cgroup.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net dev/net none bind,create=dir

I was happy with everything so far. I connected my PC and my Nextcloud container to my Headscale instance. Using the DNS section in my Headscale config I set an extra_records block for Nextcloud, meaning I could navigate to http://nextcloud in my browser and connect to my instance.

Next I installed the Tailscale app on my Android device. I used FDroid and at the time of writing I installed v1.56.0. To change the login server in the app isn’t obvious, thankfully there are instructions on the Headscale site.

So I set my login server and selected Sign In, but the normal Tailscale login page showed up. Weird. I tried again, and again. Then I turned off my WiFi and switched to 4G, and it worked correctly i.e. opened up my domain Headscale with the same authentication command from before.

Finally. So now I have three devices and they can all connect whether I’m on the same WiFi or not.

Now for my wife’s devices. I installed the Tailscale app from the Play Store (v1.56.0) and followed the same steps as before to change the login server. This time, however, I couldn’t get it working. I turned off WiFi, still wouldn’t work. The Sign In button either opened the Tailscale login page or didn’t do anything. I uninstalled and installed the FDroid version, but it would still not work.

A bit frustrated I decided to look at my wife’s Windows laptop. According to the Headscale instructions the login server URL is added in the Windows Registry (yes, really) and then a reboot is required for the change to be picked up.

Again, nothing worked. The app is suppose to open the browser with the authentication command but it the browser did not open at all. I even tried running the command in PowerShell

tailscale.exe up --login-server https://<headscale_domain>.tld --unattended

Still nothing.

After two hours of digging through past issues and trying both Android and Windows again and again, I gave up. I was extremely frustrated.

I had been talking about getting Nextcloud setup for so long I reluctantly logged in to Tailscale with Github and added mine and my wife’s mobile devices, and the Nextcloud instance. I’m not happy that I had to resort to this, from what I can tell the feature to select a custom control server has broken a few times since being implemented.

LocalSend also doesn’t appear to work across the Tailscale network. It worked between my devices on Headscale. This added to my frustration.

From the (very) brief use of Headscale I thought it was fantastic. I am reluctantly going to leave my devices on Tailscale for now so that my wife can use it but as soon as I can get the apps logging in to Headscale I will be switching.