Prompted by Hollo's split-domain setup. Two parts:
- docs/ideas/split-domain-handles.md: offering split handle/server
domains to self-hosters is config-level work — Fedify's origin
option natively accepts { handleHost, webOrigin } — and handles are
permanent identity, so apex handles matter. Single-domain stays the
default (Decision #18); post-launch polish.
- Interop constraint pinned in social-federation task 6.1 and
route-federation's gating decision: the trails-to-trails NodeInfo
check must run against the actor IRI's host after WebFinger
resolution, never the handle's domain — split-domain remote
instances would otherwise be wrongly refused.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2.5 KiB
Split-domain handles for self-hosters
Pre-spec exploration (2026-06-07), prompted by Hollo's split-domain setup (https://docs.hollo.social/install/split-domain/).
What it is
Letting the handle domain differ from the server domain:
@bob@example.com while the journal runs at trails.example.com.
The apex only has to serve (or redirect) /.well-known/webfinger;
actor IRIs, inbox/outbox, and the web UI all live on the server
domain. Mastodon (WEB_DOMAIN/LOCAL_DOMAIN), GoToSocial
(host/account-domain), and Hollo all support this.
Why it matters for trails.cool specifically
- Fediverse handles are permanent identity — you cannot migrate
@bob@trails.example.comto@bob@example.comlater. Self-hosters who care about their handle want the apex in it from day one. - Most apexes are taken (a website, an existing service): the operator
case in this very project —
social.ullrich.isexists becauseullrich.iswas occupied; split-domain would have allowed@ullrich@ullrich.is. - A self-hosting-first platform that forces "handle = wherever you can host a Node app" is leaving its best identity feature on the table.
Why it's cheap for us
Architecture Resolved Decision #18 (single domain) was justified as
"avoids WebFinger complexity" — but Fedify natively supports the split:
the origin option we already pass to createFederation accepts
{ handleHost, webOrigin } instead of a string (since Fedify 1.5).
Our side would be roughly:
- Optional
HANDLE_DOMAINenv (defaults toDOMAIN— Decision #18 stays the default) - Pass
origin: { handleHost: HANDLE_DOMAIN, webOrigin: ORIGIN } - Audit the places that build handles vs URLs (
localActorIribuilds URLs — already correct; acct: construction,users.domaincolumn semantics, profile@user@domainrendering) - Self-hoster docs: one redirect rule on the apex
(
/.well-known/webfinger→ server domain), like Hollo's guide
Interop direction (already a constraint, not an idea)
Regardless of whether WE offer split domains, remote instances use
them — the trails-to-trails check must run against the actor IRI's
host after WebFinger resolution, never the handle's domain. Pinned in
social-federation task 6.1 and route-federation's gating decision.
Scope guess
Config + audit + docs + a two-domain test in the (future) two-instance integration environment. Post-launch self-hosting polish; pairs with the broader self-host packaging story.