One of our key design features in Takahē is that we support multiple different domains for ActivityPub users to be under.
As a server administrator, you do this by specifying one or more Domains on your server that users can make Identities (posting accounts) under.
We have two terms for domains:
Display Domains are the domains that appear in handles (for example,
Service Domains are the domains that actually route to Takahē and let you access all its pages and APIs.
There’s then two ways of running domains given those definitions:
A domain acting as both display and service domain. This is for when you’re OK giving over a whole domain to Takahē (e.g.
A separate display domain from the service domain, for when you still want to run a website on the display domain (e.g.
jointakahe.org) but also want to use it for handles.
Let’s look at how to set each type up.
In this case, you want to set up a domain that only runs Takahē and doesn’t have any other website to host - an example of this is our own takahe.social.
To do this, you should set the domain up in Takahē as follows:
Domain: Set this to the domain you’re using
Service Domain: Leave this blank (as the one domain is doing both jobs)
In this case, you want to allow users to have handles that include a domain
that is already serving another website - for example, our own
jointakahe.org serves our main webpage, but we also
have our main account as
To make this work, you need to have a service domain - a place where Takahē (and the Actor URIs) for your users live, but which is different to your main domain you’d like the account handles to contain.
Service domains must be unique - they are how we identify what domain the
request that is coming in is for. It doesn’t matter what it is, as long as it’s
unique and it serves Takahē. For example,
jointakahe.org has a service
jointakahe.takahe.social, but we could also have chosen
fedi.jointakahe.org as long as we served Takahē through there too.
To set this up, you need to:
Choose a service domain specifically for this display domain and point it at Takahē. You cannot change this domain later without breaking everything, so choose very wisely.
On your display domain, proxy the URLs
/.well-known/host-metato your service domain (or anything that’s serving the same Takahē install).
You can also do a HTTP redirect rather than proxying if you like, though it may be slightly less compatible with all Fediverse server software.
Set up a domain with:
Domain: Set this to the display domain (the one that doesn’t point at Takahē)
Service Domain: Set this to the service domain (the one that serves Takahē)
Let’s say that we want to serve three domains from the same Takahē installation:
takahe.social, which will just serve Takahē directly
jointakahe.org, which has an existing website that needs to keep working
aeracode.org, which also has a website that needs to work
We set them up in the following way:
Service Domain: (left blank)
Then, we need to make sure Takahē is accessible via
fedi.aeracode.org, as these are our
Finally, we need to ensure the
.well-known paths are proxied from
aeracode.org to Takahē, as these are the display
domains that have separate service domains.
At its core, ActivityPub is a system built around URIs; the
@firstname.lastname@example.org format is actually based on Webfinger, a different
standard, and merely used to discover the Actor URI for someone.
Making a system that allows any Webfinger handle to be accepted is relatively easy, but unfortunately this is only how users are discovered via mentions and search; when an incoming Follow comes in, or a Post is boosted onto your timeline, you have to discover the user’s Webfinger handle from their Actor URI and this is where it gets tricky.
Mastodon, and from what we can tell most other implementations, do this by
preferredUsername field from the Actor object, the domain from
the Actor URI, and webfinger that combination of username and domain. This
means that the domain you serve the Actor URI on must uniquely map to a
Webfinger handle domain - they don’t need to match, but they do need to be
translatable into one another.
Takahē handles all this internally, however, with a concept of Domains. Each domain has a primary (display) domain name, and an optional “service” domain; the primary domain is what we will use for the user’s Webfinger handle, and the service domain is what their Actor URI is served on.
We look at
HOST headers on incoming requests to match users to their
domains, though for Actor URIs we ensure the domain is in the URI anyway.