LittleWebFinger: A tiny webfinger server

3 minute read Published: 2025-07-21

I've been recently switching to European services in favor of US-related ones. Yesterday brought home how hard it is to boycott US services in the tech industry. It was GitHub time, and to cease using it, I had to disconnect every service I use that leverages the GitHub authentication provider.

I use Tailscale to access my servers and services, and I use GitHub for authentication there. And since I've migrated to Codeberg, I thought about using Codeberg as my authentication provider for Tailscale.

Doing what everybody does when searching how to do something, I've searched the internet and found this excellent article by Kenny Qin about doing exactly that: using Codeberg authentication with Tailscale.

Configuring the WebFinger

When I first tried to use it, I misconfigured my HTTP server IPv6 stack and stumbled upon a strange issue on Tailscale's side. The IPv6 issue is not important, but the stacktrace it showed was interesting:

GET "https://elyvi.me/.well-known/webfinger?rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer&resource=acct%3Acontact%40elyvi.me": context deadline exceeded

Wait, what are those query parameters? WebFinger isn't just a stupid file?

Badly photoshoped adios meme with Elyvi's avatar
Accurate representation of Elyvi falling inside another rabbit hole

I went to check the RFC, and it was more complicated than I first thought while reading Kenny Qin's blog. I realized that maybe I should not put a static file at this URL. But I don't want to deploy a complex thing just to forward OAuth to Codeberg for a single email address. Also, since I use aliases between different services, maybe in the future I'll want to put OIDC on another email with another provider.

I could also have created more rules in my Caddyfile, but that sounded like a seriously awful thing to do. I thought about creating a caddy plugin for this use case, but that sounded way harder than just spinning up a simple HTTP service using Rust for instance.

It was time to develop this little thing.

Introducing LittleWebFinger

I've created this little service, and called it LittleWebFinger (reference to Petyr Baelish in Game of Thrones). The source is available on Codeberg.

What took me the longest was to read the RFC and to sort out what's required and what's nice to have, but I ended up with a basic little webfinger service that can be reverse-proxied easily on a single path.

The service can be used as a read-only provider or can support POST and DELETE requests to create, update, and delete resources from the inventory. It's stored in a little SQLite file that can be easily backed up.

It's developed in Rust, with Axum for the web framework and sqlx to interact with the SQLite database. Check the readme for more information if you're interested. It's made to be simple to deploy and simple to use, and it currently serves my webfinger file.