When you set up a Mastodon relay to boost federation across instances, the relay server must authenticate itself to your instance before it can deliver public posts. Without proper authentication, the relay connection fails silently or produces a 401 Unauthorized error in the logs. This authentication relies on HTTP Signatures, a cryptographic handshake that proves the relay server is who it claims to be. This article explains what HTTP Signatures are for Mastodon relays, why they are required, and how to configure both the relay server and your Mastodon instance to establish a working signature setup.
Key Takeaways: Mastodon Relay HTTP Signature Setup
- HTTP Signatures (RFC 9421): A cryptographic method that attaches a signed header to every ActivityPub request sent by the relay.
- Relay public key registration: The relay server must expose its public key via its own Actor object so your instance can verify incoming signatures.
- WHITELIST_MODE and AUTHORIZED_FETCH: Two Mastodon server settings that can block relay connections if not configured to allow relay traffic.
Why Mastodon Relays Require HTTP Signatures
Mastodon relays are ActivityPub actors that collect public posts from subscribed instances and redistribute them to all other subscribed instances. When a relay sends a post to your instance, it makes an HTTP POST request to your instance’s inbox endpoint. Mastodon verifies every incoming ActivityPub request by checking the HTTP Signature header. If the signature is missing, invalid, or signed with a key your instance does not recognize, the request is rejected with a 401 or 403 status code.
The root cause of relay authentication failures is almost always one of three issues:
- The relay server does not generate HTTP Signatures at all.
- The relay server uses a private key that does not match the public key advertised in its Actor profile.
- Your Mastodon instance cannot fetch the relay’s Actor object to obtain the public key.
HTTP Signatures work by having the relay server create a string of header values from the request (such as the date, digest, and request target), sign that string with its private key, and attach the resulting signature in the Signature header. Your instance then fetches the relay’s public key from the relay’s own ActivityPub Actor endpoint, decrypts the signature, and compares the result. If the decrypted hash matches the headers, the request is authenticated.
The Role of the Relay Actor Object
Every Mastodon relay must expose an Actor object at a URL such as https://relay.example.com/actor. This Actor object contains a publicKey field with a publicKeyPem property. Mastodon reads this public key to verify signatures. If the Actor object is not accessible, returns a 404, or contains an invalid PEM string, authentication fails.
Steps to Configure HTTP Signatures for a Mastodon Relay
Method 1: Configure the Relay Server to Generate HTTP Signatures
Most Mastodon relay software, such as the official mastodon-relay Ruby gem or Pub-Relay, supports HTTP Signatures natively. You need to ensure the relay server has a valid private key and that its Actor object is served correctly.
- Generate a dedicated RSA key pair for the relay
On the relay server, runopenssl genrsa -out relay-private.pem 2048andopenssl rsa -in relay-private.pem -pubout -out relay-public.pem. Store the private key in a location the relay software can read, such as/etc/relay/keys/. - Point the relay software to the private key
In the relay configuration file, set theprivate_key_pathto the full path of the private key file. For Pub-Relay, this is typically thePRIVATE_KEYenvironment variable. For the Ruby relay, it is theprivate_keysetting inconfig.yml. - Verify the Actor object is served at the correct URL
Accesshttps://relay.example.com/actorin a browser or withcurl. The response must be JSON with apublicKeyobject containingid,owner, andpublicKeyPem. ThepublicKeyPemvalue must match the contents ofrelay-public.pemexactly. - Test the signature generation from the relay CLI
Many relay tools include a test command. For the Ruby relay, runruby bin/test_signature. Look for output that says “Signature valid” or shows a successful HTTP 200 response from a test instance.
Method 2: Configure Your Mastodon Instance to Accept Relay Signatures
Your Mastodon instance must be able to fetch the relay’s Actor object and trust its public key. If your instance runs behind a firewall or uses restrictive fetch policies, you must adjust those settings.
- Ensure outbound HTTPS connections are allowed to the relay domain
Check your server firewall rules. Mastodon must be able to make an HTTP GET request tohttps://relay.example.com/actor. If you use a proxy like Nginx or Apache, verify that the proxy does not block or modify the response headers. - Disable AUTHORIZED_FETCH on your instance if it is blocking relay traffic
In your.env.productionfile, setAUTHORIZED_FETCH=falseand restart Mastodon. WhenAUTHORIZED_FETCHis true, Mastodon requires HTTP Signatures on all outgoing requests, including those from relays. This setting can cause a circular dependency where the relay cannot fetch your Actor because your instance demands a signature from a relay that has not yet been authenticated. - Add the relay domain to WHITELIST_MODE if you use that feature
IfWHITELIST_MODE=truein your environment, only instances listed in thewhitelisttable are allowed to federate. Add the relay’s domain by runningRAILS_ENV=production bin/tootctl domain add relay.example.comon your Mastodon server. - Monitor the Mastodon logs for signature errors
Runjournalctl -u mastodon-sidekiq -fand look for lines containingHTTP Signatureorsignature_verification_failure. These logs tell you whether the signature check passed or failed and often include the relay’s key ID.
If the Relay Still Fails Authentication
Relay Actor Object Returns a 404 or 500 Error
If https://relay.example.com/actor does not return a valid JSON response, Mastodon cannot obtain the public key. Check the relay server’s web server configuration. The Actor endpoint is often served by a separate web server like Caddy or Nginx. Ensure the reverse proxy is configured to pass requests to the relay software’s internal port. For Pub-Relay, the default internal port is 8080. Add a location block in Nginx that proxies /actor to http://127.0.0.1:8080/actor.
Signature Header Contains a Wrong Key ID
The HTTP Signature header includes a keyId parameter that points to the public key URL. Mastodon uses this URL to fetch the key. If the keyId is an absolute URL that does not match the relay’s Actor URL, the fetch fails. For example, if the relay sends keyId="https://relay.example.com/actor#main-key" but the actual Actor endpoint is https://relay.example.com/actor, Mastodon may fail to parse the key. Many relays use the fragment #main-key to identify the key. Verify that the Actor JSON includes a publicKey object whose id field matches the keyId exactly.
Clock Skew Between Servers
HTTP Signatures include a date header that Mastodon compares to its own system clock. If the relay server’s clock is more than 30 seconds off, the signature is rejected. Synchronize both servers to the same NTP pool. Run timedatectl set-ntp true on both the relay and Mastodon servers. Then check the offset with timedatectl show --property=NTPSynchronized.
| Item | Relay Server Configuration | Mastodon Instance Configuration |
|---|---|---|
| Private key | 2048-bit RSA key stored in a file the relay software can read | Not needed; Mastodon only needs the relay’s public key |
| Public key exposure | Served via the Actor JSON endpoint | Fetched automatically from the keyId URL in the Signature header |
| Signature algorithm | rsa-sha256 as specified in the algorithm field of the Signature header |
Verifies using the same algorithm |
| Clock sync | NTP enabled, offset under 30 seconds | NTP enabled, offset under 30 seconds |
| Fetch policy | None required | AUTHORIZED_FETCH=false or relay domain allowed in authorized fetch list |
With both sides configured correctly, the relay can send signed ActivityPub payloads and your Mastodon instance will accept them. After setting up HTTP Signatures, subscribe to the relay from your instance by navigating to Preferences > Administration > Relays and entering the relay’s inbox URL. Then watch the Sidekiq dashboard for successful delivery of federated posts. For advanced troubleshooting, use curl -v to manually replay a relay request and inspect the Signature header format.