Dropserver Progress - February 2025
This is the progress report from Dropserver for February 2025. The previous report is here.
This month was extra-short thanks to a much-needed ski vacation, but I did manage to make some solid progress on integrating Tailscale into ds-host
.
Tailscale Users as Appspace Users
After grinding on Vue templates, DB calls and everything in between, it’s now possible to assign multiple auth credentials to a single user. This means an appspace user can access the appspace via Tailscale, or via the public network or local network interchangeably.
The UI needs some polish to say the least but the essence is there:
Create a new user or assign the Tailscale identity to an existing appspace user:

See who the peers are and the connected appspace user:

All this works while the Tailscale peers can change at any instant. The data is kept up-to-date on the frontend UI through a system of events inside of ds-host, and Server Sent Events to the browser (see September 2024 progress report). While I don’t love all-JS frontends, Vue reactivity is great for reflecting the latest state as soon as it shows up.
Commit: “feat(ds-host): implement multiple auths per appspace user, including tsnetid” 10f4770
Identifying Tailscale and Headscale Users
Tailscale users have a pretty solid looking ID that I understand is stable and unique. Using that to identify peers is natural, but there are a couple of gotchas.
Headscale user IDs are plain integers starting with 1. So user ids are 1, 2, 3, 4… There can be many Headscale instances in the world therefore there are many Headscale users with ID 1, ID 2, etc… If an admin changes / moves / rebuilds their instance, relying solely on the user ID like I do with Tailscale isn’t enough.
To mitigate this I am doing two things:
- ids in the appspace DB are stored as
<id>@<headscale-control-domain>
. If you change to a different Headscale instance at a different domain, this will ensure that user-1 in one instance is not the same as user-1 in a different instance. - I added an
extra_name
column in the DB, which stores the email address of the Headscale user. I haven’t implemented this part yet but it should help deal with situations where a Headscale user is not who the system thinks they are.
Commit: “add extra name to appspace user auth” b77fd83.
Tags, Key Expiry and Auth Keys
Tailscale expects non-user nodes to be “tagged” (see Tailscale docs.) As such appspace nodes should be tagged. This triggers the following do-list:
- UI to input tag when creating node
- read actual tags for the node
- disable use of appspace node if there are no tags
With the above done, I set up the UI to warn the user when the node has no tags, and point them to a remedy.

Auth Keys
If you try to create an appspace Tailscale node the ds-host
UI will display a link to click, which takes you to Tailscale (or your Headscale instance) where you authenticate to finish creating the node. It’s convenient and requires no prior steps to complete.
An alternative is to create an auth key in Tailscale (or Headscale). Conveniently you can select tags to set on nodes created with that auth key.
I added support for creating a node using an auth key. In many cases this will be a superior workflow for users, so long as they have the forethought of creating an auth key. It’s also possible to create multiple nodes with the same auth key.
Node key expiry
Tailscale nodes expire, but you can disable the expiry date of the node if it’s meant to run unattended like a server. In fact, if you create a node with a tag, key expiry is disabled automatically.
If in spite of the work above the appspace node is created without a tag and an expiry date is in effect, the UI points out the issue along with steps to resolve. (It’s easy to do, but if you don’t know you don’t know.)

With the above, the user should be able to create a node and get it to usable state even if things didn’t go according to plan the first time around. ds-host
detects all “gotcha” situations that I can think of and points the user in the right direction to resolve. This is key to get Tailscale working for users who may not be familiar with it.
Commits: “add tsnet tags input and key expiry date to status” 604d0e3 and “create tsnet node using AuthKey” 7f122d4.
Getting CLoser
It feels like Tailscale integration is finally getting closer to being done. I’m punting on a few things that are related but not critical: handling avatars, and better user management.
I am now working on making the ds-host
admin panel accessible from Tailscale as well. Naturally it’s not nearly as simple as I would like it to be.