-
-
Notifications
You must be signed in to change notification settings - Fork 52
Split-domain WebFinger handle #484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
427ea00
Add split-domain WebFinger support
dahlia df90b2d
Treat WEB_ORIGIN host as a local handle alias
dahlia 17e2c88
Tighten handle parsing in startup check
dahlia c8b5e7d
Strip leading @ from handle-like API input
dahlia c6be3f7
Validate WEB_ORIGIN URL syntax in env
dahlia 16b2d6d
Reuse handle canonicalization in /search
dahlia d1fc888
Tighten WEB_ORIGIN validation in env
dahlia 6c029c5
Match canonical handle in /search filter
dahlia 252b4b9
Normalize exported WEB_ORIGIN to its origin form
dahlia 1cd1494
Validate HANDLE_HOST is a bare hostname
dahlia 77ed649
Use hostname not host for local-handle comparison
dahlia a9cea99
Reject malformed hostnames in HANDLE_HOST
dahlia 1ddd002
Accept both host and hostname in isLocalHost
dahlia 1dc2068
Document the scope of isLocalHost
dahlia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| --- | ||
| title: Split-domain WebFinger | ||
| description: Run Hollo at one domain while addressing accounts under another. | ||
| --- | ||
|
|
||
| import { Aside, Code, Tabs, TabItem } from '@astrojs/starlight/components'; | ||
|
|
||
| Hollo supports a *split-domain WebFinger* setup: your fediverse handles | ||
| live under one domain (e.g. `@alice@example.com`) while the actual | ||
| ActivityPub server runs under another (e.g. `https://ap.example.com`). | ||
| This is the same pattern Mastodon documents under "[hosting WebFinger | ||
| at the root domain][mastodon-webfinger]" and that GoToSocial calls | ||
| *host-meta*-based host swapping. | ||
|
|
||
| This is implemented on top of [Fedify's `origin` configuration option]. | ||
|
|
||
| [mastodon-webfinger]: https://docs.joinmastodon.org/admin/config/#web_domain | ||
| [Fedify's `origin` configuration option]: https://fedify.dev/manual/federation#separating-webfinger-host-from-the-server-origin | ||
|
dahlia marked this conversation as resolved.
|
||
|
|
||
|
|
||
| Why split the domain? | ||
| --------------------- | ||
|
|
||
| The typical reason is that you already own a nice short domain | ||
| (`example.com`) and want your handles to look like | ||
| `@alice@example.com`, but you don't want to host Hollo at the apex of | ||
| that domain — the apex is reserved for a homepage, a different web app, | ||
| or an existing service. | ||
|
|
||
| In a split-domain setup: | ||
|
|
||
| - Users address you as `@alice@example.com` everywhere in the | ||
| fediverse. | ||
| - Hollo itself is served from `https://ap.example.com`. The web | ||
| UI, the Mastodon-compatible API, OAuth, and the actor URIs all | ||
| live there. | ||
| - The apex domain `example.com` only needs to handle one thing: | ||
| redirecting `/.well-known/webfinger` requests over to | ||
| `ap.example.com`. | ||
|
|
||
| <Aside type="caution"> | ||
| Pick the handle domain carefully — you can't change it after | ||
| federation has begun without breaking every remote follow. See the | ||
| warning at the bottom of this page. | ||
| </Aside> | ||
|
|
||
|
|
||
| Configuration | ||
| ------------- | ||
|
|
||
| Set both of these environment variables on your Hollo instance: | ||
|
|
||
| - [`HANDLE_HOST`](/install/env/#handle_host) — the bare hostname | ||
| used in handles (no scheme, no path), e.g. `example.com`. | ||
| - [`WEB_ORIGIN`](/install/env/#web_origin) — the scheme + host | ||
| where Hollo runs, e.g. `https://ap.example.com`. | ||
|
|
||
| Both must be set together; setting only one causes Hollo to refuse to | ||
| start. | ||
|
|
||
| ~~~~ env | ||
| HANDLE_HOST=example.com | ||
| WEB_ORIGIN=https://ap.example.com | ||
| ~~~~ | ||
|
|
||
| With this in place, Fedify takes care of the rest: | ||
|
|
||
| - WebFinger responses use `acct:alice@example.com` as the subject. | ||
| - Actor URIs are built under `https://ap.example.com/@alice`. | ||
| - The Mastodon-compatible `/api/v1/instance` and `/api/v2/instance` | ||
| endpoints report `example.com` as the instance domain, so clients | ||
| display the correct handle. | ||
|
|
||
|
|
||
| Reverse proxy redirect | ||
| ---------------------- | ||
|
|
||
| Hollo itself only listens on the `WEB_ORIGIN` host. Remote servers | ||
| that look up `@alice@example.com` will send their WebFinger query to | ||
| `https://example.com/.well-known/webfinger`, so you must configure | ||
| that domain's reverse proxy to redirect those requests to Hollo. | ||
|
|
||
| A 301 redirect that preserves the query string is enough. Send | ||
| `/.well-known/nodeinfo` and `/.well-known/host-meta` along as well, | ||
| since some implementations probe those during discovery. | ||
|
|
||
| <Tabs> | ||
| <TabItem label="nginx"> | ||
| ~~~~ nginx | ||
| server { | ||
| listen 443 ssl; | ||
| server_name example.com; | ||
| # … your normal site config … | ||
|
|
||
| location /.well-known/webfinger { | ||
| return 301 https://ap.example.com$request_uri; | ||
| } | ||
| location /.well-known/nodeinfo { | ||
| return 301 https://ap.example.com$request_uri; | ||
| } | ||
| location /.well-known/host-meta { | ||
| return 301 https://ap.example.com$request_uri; | ||
| } | ||
| } | ||
| ~~~~ | ||
| </TabItem> | ||
| <TabItem label="Caddy"> | ||
| ~~~~ caddy | ||
| example.com { | ||
| # … your normal site config … | ||
|
|
||
| redir /.well-known/webfinger* https://ap.example.com{uri} permanent | ||
| redir /.well-known/nodeinfo* https://ap.example.com{uri} permanent | ||
| redir /.well-known/host-meta* https://ap.example.com{uri} permanent | ||
| } | ||
| ~~~~ | ||
| </TabItem> | ||
| </Tabs> | ||
|
|
||
| You do **not** need to redirect the `/@username` path or any actor | ||
| URLs — those URLs live on `ap.example.com` and remote servers will go | ||
| straight there after resolving the WebFinger response. | ||
|
|
||
|
|
||
| Verifying the setup | ||
| ------------------- | ||
|
|
||
| After deploying, three quick checks confirm everything is wired up: | ||
|
|
||
| 1. WebFinger from the handle domain redirects: | ||
|
|
||
| ~~~~ sh frame="none" | ||
| curl -i "https://example.com/.well-known/webfinger?resource=acct:alice@example.com" | ||
| ~~~~ | ||
|
|
||
| should return a 301 to `https://ap.example.com/.well-known/webfinger?...`. | ||
|
|
||
| 2. WebFinger from the server domain responds: | ||
|
|
||
| ~~~~ sh frame="none" | ||
| curl "https://ap.example.com/.well-known/webfinger?resource=acct:alice@example.com" | ||
| ~~~~ | ||
|
|
||
| should return a JRD whose `subject` is `acct:alice@example.com` | ||
| and whose `self` link points at `https://ap.example.com/@alice`. | ||
|
|
||
| 3. The instance endpoint reports the handle domain: | ||
|
|
||
| ~~~~ sh frame="none" | ||
| curl https://ap.example.com/api/v2/instance | jq .domain | ||
| ~~~~ | ||
|
|
||
| should print `"example.com"`. | ||
|
|
||
| For a more thorough audit, point Julian Fietkau's [WebFinger Canary] | ||
| at your handle domain. Mastodon and Fedify-based servers handle | ||
| split-domain setups correctly today; Misskey and Pixelfed currently | ||
| do not. | ||
|
|
||
| [WebFinger Canary]: https://correct.webfinger-canary.fietkau.software/ | ||
|
|
||
|
|
||
| <Aside type="danger"> | ||
| **Configure `HANDLE_HOST` and `WEB_ORIGIN` before creating your | ||
| first account.** | ||
|
|
||
| Hollo stores each local account's full `@user@host` handle in the | ||
| database when the account is created. Other ActivityPub | ||
| implementations also cache your handle on first contact. Changing | ||
| the handle domain later means your existing followers can no longer | ||
| resolve you, and there is no migration path that keeps existing | ||
| follow relationships intact. | ||
|
|
||
| On startup, Hollo logs a warning if `HANDLE_HOST` disagrees with the | ||
| stored handle of the existing account. Treat that warning as a | ||
| problem to investigate before continuing to run the instance. | ||
| </Aside> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.