Federation
How federation works
What ActivityPub means in practice for an Omicron instance — identity, delivery, and the boundaries of your control.
Federation is implemented with Fedify, which handles
HTTP signatures, delivery, and retries. The entire federation/ tree — and the
Fedify dependency itself — is imported only when FEDERATION_ENABLED=true,
so a standalone blog carries none of it at runtime.
Identity
With federation on, each local account becomes an ActivityPub actor:
handle: @alice@your-domain
actor: https://your-domain/users/alice
inbox: https://your-domain/users/alice/inbox
outbox: https://your-domain/users/alice/outbox
profile: https://your-domain/@alice
The actor URI is the identity other servers store and address. The profile is
where the actor sends people — it is the actor’s url, and the page a Mastodon
user reaches by clicking a byline. See
two addresses for how each one answers for the
other.
Discovery starts at WebFinger: a remote server asked to find
@alice@your-domain queries
/.well-known/webfinger?resource=acct:alice@your-domain, gets back the actor URI,
and fetches the actor document from there.
Every one of those URIs is built from your domain, which is why the domain must be settled before you federate and must not change afterwards.
Inbound
Other servers POST activities to an actor’s inbox, or to the shared inbox at
/inbox when one activity is addressed to many of your users at once.
| Incoming | What Omicron does |
|---|---|
Follow |
Auto-accepts (or holds for approval if the account requires it) and replies with Accept |
Create (Article) |
Stores the post and shows it in the appropriate feed |
Create (Note) |
Stores it as a response when it replies to one of your posts (or to a known response) — see Compatibility. Any other microblog Note is ignored |
Announce |
Records a recommendation: caches the boosted Article if not already fetched, and notifies its local author. Surfaces on the booster’s local followers’ For you feed — see Recommending |
Undo |
Reverses the referenced Follow or Announce |
Update |
Refreshes the cached copy of a remote post or response, when the editor wrote it |
Delete |
Removes the referenced remote content |
Inbound requests are signature-verified by Fedify, rate-limited per source IP,
and capped in body size — twice, once by declared Content-Length and again
while buffering, so a spoofed or missing length cannot stream an unbounded
payload into the parser.
Outbound
Publishing a post enqueues a Create activity for delivery to each remote
follower’s inbox. Delivery is asynchronous: a slow or unreachable remote server
never blocks the user’s request, and Fedify retries.
The same path carries Accept, Announce (recommending a post fans it out to
your own remote followers as a boost), Undo, Delete, and profile updates.
Responses travel the same way: a comment on a public post goes out as a Note
threaded under it, and each public post advertises a Replies collection so
remote servers render the whole thread. Replies on a private author’s posts
stay local-only. See Compatibility.
See Delivery and queues.
Author attribution on link cards
The bare actor document has Mastodon’s attributionDomains spliced in, so when
one of your articles is shared, the link preview card renders an author byline
instead of an anonymous card.
What federation does not give you
- No retroactive history. A new follower receives what you publish from then on, not your archive.
- No delivery guarantee. A remote server may be down, may have blocked you, or may simply drop activities. Fedify retries; it cannot compel.
- No takedown power. A
Deleteis a request other servers choose to honour. - No read visibility. You learn about likes, boosts, replies, and follows because they are sent to you. Reads on other servers are invisible, by design — see Writer dashboard.
Standalone mode is a first-class choice
Running with federation off is fully supported, not a degraded state: you get a clean, self-hosted blog with no ActivityPub surface exposed to the internet at all. You can turn federation on later, once your domain is settled.
Found a mistake?Edit this page on GitHub.