Skip to content

Federation ​

Connect your node to the wider Dissent network.

What federation does ​

When two nodes federate, users on different nodes can join the same servers and exchange messages across nodes. Node A and Node B relay messages, presence, and events using Ed25519-signed packets.

What works without federation ​

Everything on your own node: chat, DMs, voice/video, E2EE, plugins, roles, moderation. Federation only matters when you want users from different nodes to share a space.

For most community admins, federation isn't needed — your users register on your node and everything works.

Your node's identity is its key, not its domain ​

The first time your node starts it generates an Ed25519 keypair and writes the private half to data/node_key.pem. That key is who your node is. Your domain is an address — something other nodes record about you, and something that is allowed to change.

Back up data/node_key.pem

Lose it and your node can never prove it is the same node again. Peers that trusted you no longer do, and outstanding federated invites pointing at you stop resolving. There is no reissue and no recovery — the key is the identity.

It is a small file. Keep a copy wherever you keep .env; the archive produced by Backups & Restore already includes it.

Enabling federation ​

Set FEDERATION_ENABLED=true in your .env file:

bash
# In .env
FEDERATION_ENABLED=true

Then restart the stack:

bash
docker compose -f docker-compose.prod.yml up -d

Requirements ​

  • Your node must be reachable over HTTPS at a public address
  • Port 443 must be open and TLS must be working
  • NODE_URL in .env must be that public HTTPS URL (e.g. https://node.example.com)

Connecting to other nodes ​

Nodes discover each other by gossip — you do not add peers by hand.

Gossip still needs somewhere to start. BOOTSTRAP_NODES in .env is a comma-separated list of node URLs used only while your node knows no peers at all; after the first successful round, gossip keeps the list current on its own. setup.sh writes https://node.dissent.chat, which is enough to reach the rest of the network. Clear it if you want an isolated node that talks to nobody.

Discovery is not trust, and trust is not mutual until both sides grant it — trusting a peer does not make that peer trust you.

Once federation is on, open Node Admin → Federation:

  • Known Peers lists the nodes gossip has told you about. Click a row to see its details.
  • In the drawer, Trust this node grants it the right to relay messages to your users; Revoke Trust takes it back.
  • Trusted Nodes shows what you have granted — each node's address, the start of its public key, and when it was last seen.

Trust is always a decision a human makes. Being discovered, being reachable, and holding a valid signature grant none of it.

Moving your node to a new domain ​

Supported, and it does not break your peers.

  1. Point the new domain at your server and update NODE_URL and CADDY_DOMAIN in .env
  2. Restart the stack

Your node re-announces under the same key. Peers that already know that key follow the address change automatically and keep trusting you — trust is attached to the key, not the hostname.

Rules that make that safe rather than reckless:

SituationWhat peers do
Address changed, key already knownApplied automatically
Address change not signed by the key it claimsRefused
Signature does not verifyRefused
Address claimed for a key nobody knowsRefused — a stranger's announce never creates a trust record
Key changed for a node they already knowRefused, recorded, and surfaced to the admin as a Peer key change

The asymmetry in that last row is deliberate. An address is a routing detail and may move freely. A key change means the node is, as far as anyone can prove, a different node — so it waits for a human instead of healing itself.

Federated invites ​

An invite to a server on another node is one opaque token beginning with dsnt1_. It carries the home node's key, plus a last-known address as a hint — so the invite still resolves after that node has moved.

Invites in the older CODE@host form are no longer accepted; pasting one returns an error telling the user to ask for a new link. Ordinary invites to servers on your own node are unaffected — those are plain codes and always have been.