Skip to content
Omicron

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.

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 Delete is 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.