Docs

Self-host the mail relay

Orbit Mail is the inbox and the calendar. The relay is the part that speaks SMTP to the rest of the internet, and seals every message to its reader's key before Orbit stores it. Orbit runs relays you can use as they are; this page is for running your own. One command installs it; the only thing it needs open is port 25.

The relay is open source under the MIT license: read its code on GitHub, including the part that seals your mail, before you run it.

What you need

  • A server running Ubuntu 24.04 or newer, or Debian 12 (bookworm), 13 (trixie) or newer, with a public IP address and port 25 reachable from the internet. Most cloud providers block port 25 by default and open it on request.
  • A hostname for it, such as mx1.example.com, with an A record pointing at the server and, ideally, a matching PTR record set by your provider.
  • A domain you want mail for, where you can edit DNS records.
  • An Orbit account with a mailbox in Orbit Mail, signed in at least once so your encryption key exists.

The installer sets the relay up on the host itself: the distribution's Postfix, the system Python and one systemd service. The host's Postfix becomes the relay, and on Debian installing Postfix replaces Exim, so use a host that runs no other mail server.

1. Issue a relay key

In Orbit Mail, open Settings, then Encryption, and press Issue a relay key. The key is shown once; the page then prints the exact install command with the server's address filled in. A relay running with your key delivers to your mailboxes, and sends your mail, and nothing else.

2. Run the installer

On the server, as root:

curl -fsSL https://mail.orbit.com.ai/relay/install.sh \
    | sudo bash -s -- --server https://mail.orbit.com.ai --key orbk_...

Options: --name relay-2 to name a second node, --hostname mx1.example.com to set the name the relay announces (it defaults to the host's full name). Encryption is not an option: every node seals mail, and the installer generates the node's own key in /etc/orbit-mail/relay.key; see end-to-end encryption.

The script carries no secrets. It installs Postfix and Python with apt, clones the relay source into /opt/orbit-relay, writes the server address and key to /etc/orbit-mail/relay.env (readable by root and the relay's own user only), configures Postfix to hand accepted mail to the relay and starts the orbit-relay service. Within a minute the node appears under Relays on the Encryption page.

3. Publish DNS

Your domain's page in Mission Control (Mail, then Domains) lists the records to publish. Point them at your own server's name instead of Orbit's relay:

  • MX pointing at your relay's hostname, so mail for the domain arrives at your relay.
  • SPF (a TXT record) authorising the relay to send for the domain.
  • DMARC telling receivers how to treat mail that fails checks.
  • DKIM, recommended: set up signing on the relay (the relay's README explains how), then paste the public key on the domain's page and the record appears there. Without it, more of your mail is treated as suspicious.

The name the relay announces should match the host's PTR record.

Running it

The relay keeps itself configured: every minute it checks in with Orbit Mail, downloads the list of domains and addresses it may serve, and configures Postfix to accept exactly those. Mail that arrives is sealed to its reader's key, fetched from Orbit Mail, and written to a durable queue on the server before the sender is told it was accepted, then posted to Orbit Mail with retries for up to three days. Mail you write in Orbit Mail is sealed to your relay's key in your browser, picked up by the relay, opened there and sent. A reader who has not signed in yet has no key, so their mail waits at the relay until they do.

curl -s http://127.0.0.1:8080/status | python3 -m json.tool   # queue, server reachability, counters
sudo orbit-relay dead                                          # parked messages, with the reason
journalctl -u orbit-relay -f                                   # the relay's log
journalctl -u 'postfix@*' -f                                   # Postfix's log

Its public address. The relay tells Orbit Mail its public IP address, and finds it out by asking api.ipify.org once an hour. To give it yourself, so nothing is asked, add ORBIT_RELAY_PUBLIC_IP=203.0.113.25 (your server's address) to /etc/orbit-mail/relay.env and run sudo systemctl restart orbit-relay. A re-run of the installer keeps lines it didn't write.

Updating. Re-run the install command. It pulls the latest source, rewrites the Postfix configuration and restarts both services; the queue in /var/lib/orbit-mail survives. A node installed with Docker (relay 3.0 or earlier) moves onto the host the same way, queue included.

Rotating the key. Rotate it where it was issued, then re-run the install command with the new key on each node. Until you do, the node keeps accepting and queueing mail; it just cannot deliver it.

More than one node. Install on a second server with --name relay-2. Nodes do not need to know about each other: each downloads the same configuration and claims outgoing mail from the same queue, and your browser seals outgoing mail to every node online. Point the domain's MX records at both with equal preference.

A real TLS certificate. The relay offers STARTTLS with a self-signed certificate out of the box. To present a certificate for the relay hostname, re-run the install command with --tls-cert and --tls-key pointing at it, such as Let's Encrypt's fullchain.pem and privkey.pem; they are remembered. After a renewal, systemctl reload postfix picks it up.

If something is wrong

  • The node never appears. Run journalctl -u orbit-relay. A wrong key shows as repeated 401 responses; a wrong server address as connection errors.
  • Mail is not arriving. Check the MX record resolves to the relay hostname and that port 25 is reachable from outside: nc -vz mx1.example.com 25 from another machine. Then check the domain is Active and the address exists as a mailbox.
  • The queue keeps growing. A growing pending count means Orbit Mail is unreachable or refusing messages. A growing dead count means messages were rejected for good, usually for an address that has no mailbox; sudo orbit-relay dead lists them with the reason.
  • Mail is deferred for one address. The log says the reader has no encryption key yet: they have not signed in to Orbit Mail since their mailbox was created. The mail is sealed and delivered as soon as they do.

Source

The relay is open source under the MIT license at https://github.com/Orbit-AI-LLC/Orbit-SMTP-Relay. The README there documents every setting, the on-disk queue and how to run it by hand without the installer. It is the same relay, with the same encryption, that Orbit runs for everyone who does not run their own. To report a security problem in it, follow its security policy.