Oh no! This site works best on Firefox. It looks like you are using a Chromium-based browser (Chrome, Edge, Opera, etc.) 😭
To help save the open web and protect your privacy, you should give Firefox a try!

Get a Custom Mastodon Domain-Alias Without Hosting a Mastodon Server

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.)

  1. 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.
  2. 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.
  3. 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).
  4. Check whether you get the JSON response from example.org/webfinger and to be on the safe side also from example.org/webfinger?resource=acct=your@mastodon.handle, using a web browser.
  5. 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.

Do you have any questions or thoughts on this post? Send me a message!