Alex Guyot shared an awesome trick today! This post is mostly a reiteration of the steps he described, adapted to Codeberg pages, in order to preserve the trick from getting lost in the fast-moving timeline.
(Mis?)Using Webfinger
Mastodon uses webfinger to discover information about users on remote servers. So when a server looks up a username like @user-part@domain-part
for search or mentions, it will send a webfinger request to the remote server at .well-known/webfinger?resource=acct:<user-part>@<domain-part>
to get information on where to find the profile page of that user.
The response for querying my account on mastodon.online, for example, looks like this:
{
"subject": "acct:jfkimmes@mastodon.online",
"aliases": [
"https://mastodon.online/@jfkimmes",
"https://mastodon.online/users/jfkimmes"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://mastodon.online/@jfkimmes"
},
//...
So for other servers to find you under your your custom domain, something on that custom URI needs to respond to the webfinger request and point/redirect the inquiring server to your actual account.
Step-by-Step Instructions for Codeberg Pages et al.
Since this blog is hosted on Codeberg pages and I'd rather not have a reverse proxy running only for handling and redirecting some .well-known
requests, I tried the obvious solution of simply serving a static file from within pages. You can follow these steps on any service or webserver that handles static files at arbitrary paths/URLs (e.g, Github/Gitlab pages, Apache/NGINx, etc.)
- In my static file generator, I added an exception for the
.well-known
directory. This prevents my generator from overwriting my manually added static JSON files in there the next time I create a blog post. This step is very much dependent on how you generate/add the static files that pages should serve. - Get a JSON response from your regular mastodon instance, at:
.well-known/webfinger?resource=acct:your@mastodon.handle
(note the missing@
in front of the username). The result should look similar the one shown above. - Store the JSON response as a file called
webfinger
in a directory called.well-known/
in the root of your pages repository (or in the webroot of your webserver). - Check whether you get the JSON response from
example.org/webfinger
and to be on the safe side also fromexample.org/webfinger?resource=acct=your@mastodon.handle
, using a web browser. - Profit! If this works, you should now be able to find your profile using
anything@example.org
from any Mastodon client.
In step 3 you could, of course, be more specific if you want to simulate a real webfinger response more granularly. At the moment any request parameter is of course completely ignored and for any username the same file will be returned. This leads to a kind of catch-all situation where foo@example.org
is valid for all foo
. If you want to register multiple accounts from your domain, you'd have to name the files appropriately (e.g., webfinger?resource=acct:acc1@example.org
and webfinger?resource=acct:acc2@example.org
. This might break, however, if different implementations have slight variations in the webfinger requests.
Problems?
Since webfinger is not specified in the ActivityPub protocol itself, but merely an implementation detail of Mastodon (and others) it remains to be seen if this is robust across AcvitivityPub implementations. If even only one client has a different discovery mechanism then this "hack" should, of course, not be used, as it breaks the assumption that ActiviyPub implementations are fully compatible. If someone has insights into how this is handled across servers/clients, let me know!
Additionally, serving a static file with the request URI as the name is fragile. Different server implementations might use different request parameters or a different parameter order. Maybe it would make sense to start a public collection of requests that different ActivityPub servers use to find remote user profiles.