Saivo

Run a relay

Saivo is built to be self-hosted. One relay can serve a family, a team or a community. This page is for the person who runs it.

Turn the panel on

The panel is a second, private listener. It is never reachable through the public relay port or through Caddy.

Docker Compose (deploy/relay/compose.yaml): put these in .env next to it, then docker compose up -d:

SAIVO_ADMIN_TOKEN=<32 or more letters, digits, - or _>
SAIVO_REGISTRATION=invite        # or open (the default)

Open an SSH tunnel from your own computer and browse to it:

ssh -L 8766:127.0.0.1:8766 you@your-server

Then open http://127.0.0.1:8766/ and enter the token. Without Docker, run saivo-server with SAIVO_ADMIN_TOKEN set; it listens on 127.0.0.1:8766 (SAIVO_ADMIN_BIND_ADDR changes the port; anything other than loopback is refused outside a container).

What you can do

TabWhat it does
OverviewConnected clients, people known, waiting mail and attachments, whether calls (TURN) are set up. Switch between anyone may join and invited people only. Run expiry now.
PeopleEvery mailbox that has signed in: online or not, last seen, waiting mail, push on or off. Add a private label ("Anna"), disconnect, block (deletes waiting mail, refuses sign-in and mail), unblock, or remove.
InvitesCreate a single-use code (optionally expiring in 1, 7 or 30 days) and hand it to one person. Only a hash is stored; the code is shown once. Revoke unused codes.
ActivityWho created, used or deleted what, newest first (the last 5000 entries).
ConnectionsOpen connections per address against the per-address limit.

A person enters their invite code under Settings → Relay Server Gateway → Relay URL in the app. The code is used once; after the relay admits that mailbox, the app forgets it. Someone who already joined does not need a code again.

With invited people only, mail for a mailbox that never joined is refused, so strangers cannot fill your disk by writing to made-up mailbox ids.

What the relay cannot do, on purpose

Saivo is end-to-end encrypted. The relay knows pseudonymous mailbox ids, not names, contact lists, groups or message text. So the panel manages who may use the relay, not what they say or which groups they are in:

  • Group membership, names and content are known only to group members, and only the group's creator can add or remove members. They cannot be listed or edited from the relay.
  • Blocking or removing someone stops their traffic through your relay. It does not remove them from a group, and they can use another relay.
  • Labels are yours alone; nobody else sees them.

If you want the operator to see or control groups, that would mean giving up end-to-end encryption for them, which Saivo does not do.

Other settings (environment)

VariableMeaning
SAIVO_MAX_CONNS_PER_IPOpen connections one address may hold (default 64)
SAIVO_TRUST_PROXY=1Use the last X-Forwarded-For entry as the client address (only behind your own proxy). It is honoured only when the connection comes from loopback or from SAIVO_TRUSTED_PROXIES
SAIVO_TRUSTED_PROXIESComma-separated proxy addresses or CIDR ranges allowed to set X-Forwarded-For besides loopback (the Compose file lists the private ranges)
SAIVO_PUBLISH_IP_BURST, SAIVO_PUBLISH_IP_PER_SECMessages one address may send (default 100 at once, then 20 a second)
SAIVO_PUBLISH_MAILBOX_BURST, SAIVO_PUBLISH_MAILBOX_PER_SECMessages one mailbox may receive (default 100 at once, then 20 a second)
SAIVO_REGISTRATION_IP_BURST, SAIVO_REGISTRATION_IP_PER_SECNew accounts from one address (default 10, then one a minute)
SAIVO_MAX_MEMBERSAccounts open registration may create in total (default 100000). Invite codes you issue are not limited by it
SAIVO_MAX_VAULTS_PER_MAILBOXAccount copies one account may create (default 2)
SAIVO_VAULT_CREATE_IP_BURST, SAIVO_VAULT_CREATE_IP_PER_SECNew account copies from one address (default 2, then one per 10 minutes)
SAIVO_MAX_CONCURRENT_UPLOADSAttachment and account-copy uploads handled at the same time; more wait up to 30 s, and each upload must arrive within 4 minutes (default 8)
SAIVO_PUSH_ALLOW_LOCAL=1Allow push endpoints on private addresses or plain http (test networks only)
SAIVO_TURN_URLS, SAIVO_TURN_SECRETYour TURN server, for calls across restrictive networks