Dropserver Progress - November 2024
This is the progress report for Dropserver for November 2024. Here is last month’s report. This month was all about Tailscale integration. Trying to get this stuff right isn’t easy! Dig in…
Config Conundrums
When I started Tailscale integration I reflexively put some configuration parameters in the ds-host
config file.
Silly idea. First, I should not be adding things to this config file. Nobody wants to write a config file before running a new service. I should work to eliminate it not add to it.
More à-propos of Tailscale, it turns out there are no configuration parameters that exist instance-wide. (Well, almost. There is one. More on that some other time.)
If you speedrun through my notes from the last couple of months, it’s a continuous process of moving config values for tsnet
nodes away from the instance level, to have them keyed by tailnet, and finally to have them attached to an appspace ID, if not to disappear entirely.
Implementing tsnet
is an exercise in completely reverting the flow of configuration from your config file, to have it fed to you by the state of a (running!) Tailscale node.
Take HTTPS for example. For the “normal” server, whether to use HTTPS is a value in the config file that is read at ds-host
startup, and is used to decide whether to start a TLS server.
I obviously thought there would be an equivalent config value for Tailscale nodes. Then I realized different users might use different tailnets for their nodes, so it became a per-tailnet setting. Then I realized that it shouldn’t even be a setting because you can’t even have a functioning HTTPS server on a tsnet
node unless the backend is set up to enabled this.
By the end of November there are very few configuration values, and they are all per-appspace. The ds-host
config file will have nothing related to Tailscale.
Trying Out Ionscale
As I integrate Tailscale into Dropserver, I want to make sure the open-source alternative backends also work. Ionscale is a self-hosted alternative backplane for Tailscale. It appears to have a good number of features, but unfortunately some docs are missing.
The installation docs are actually quite good. Concise, they got me to having an instance of Ionscale on a VM pretty quickly. Unfortunately, the usage docs are non-existent. It’s through trial and error that I was able to figure out how to make it work (I think).
Double unfortunately, as soon as I figured out the command needed, I got a panic. Not great! I filed an issue but after several days of not sharing from the dev, I deleted the VM.
Womp womp.
I’ll certainly revisit Ionscale at some point in the future and hopefully have better luck, but for now I need to move on to more familiar territory.
More Headscale
I had played with Headscale already. It’s more widely used than Ionscale even though it has fewer features (see below). Also it’s the closest thing to an officially supported open source backend for Tailscale. I think the dev even works at Tailscale.
One appspace on Tailscale and one on Headscale?
I wanted to know whether it was possible to have one node connected to the official Tailscale backplane and one connected to my own instance of Headscale. And have these nodes both connected simultaneously from one running Go program.
Knowing this would inform whether the ControlURL
for tsnet
is an instance-wide setting or not. So I made some experiments…
Turns out tsnet
can connect to different backplanes simultaneously. That means different appspaces can be connected to different Tailscale backends (which will be great for Tailscale users who want to experiment with alternative backends) and an instance-wide config for this is unnecessarily limiting.
Also poof! 🪄 one less config a the instance level.
Headscale HTTPS serve issue
One bummer about Headscale is that it does not yet support serving over HTTPS. This means that an appspace connected to a Headscale instance is only accessible over plain HTTP. Of course, the connection is encrypted since it’s running through a WireGuard Tunnel. But if you open the link in the browser, it tells you it’s not secure.
This is problematic because many advanced web features require a Secure Context to be available. Without that, no PWA, no notifications, no camera access, etc… The Leftovers app would lose a lot of usefulness without HTTPS.
I opened an issue to add this feature, unfortunately right now I don’t have the time to implement it.
MagicDNS, TLS, and User Experience
So far in my Tailscale experiments I assumed that MagicDNS was on and HTTPS enabled. But that’s not a given. Even if the likely outcome is that someone using Tailscale to serve Dropserver appspaces will have these features on, they may not be on at first.
If a user has just signed up to Tailscale, these features are off. They may not be reading my instructions carefully (a safe assumption to make). Dropserver should connect to the tailnet with what’s available, and make clear to the user that they can get HTTPS and a URL by going in and enabling MagicDNS and TLS certs.
What’s more, since tsnet
is good about forwarding network configuration changes to the client promptly (this is inherent to how Tailscale works) Dropserver should notice these changes and act accordingly.
The goal is that when a user makes changes to their Tailscale (or Headscale or Ionscale) configuration, the nodes managed by Dropserver instantly “do the right thing”. If HTTPS becomes available, then it starts ListenTLS()
and if it becomes unavailable it stops that listener.
This means the user just needs to flip a couple of switches in the Tailscale admin UI and the ds-host
admin panel updates to show them the full HTTPS URL for their appspace. No interaction required. No “…and then go restart your node” in the docs.
Commit 5d2114.
What’s Next
This month I will soon finish the config side of things (for appspaces at least) and I can move on to how to handle users, which should be fun.