Mastodon relays let instances share public posts from one server to many others without each server manually following every user. Without a relay, each instance admin must subscribe to remote users individually, which becomes impractical as the federation grows. The Activity-Relay project provides an open-source, self-hosted solution that acts as a central hub for forwarding public timelines. This article explains how to deploy Activity-Relay on a Linux server, configure it with your Mastodon instance, and manage relay subscriptions effectively.
Key Takeaways: Deploying Activity-Relay for Mastodon Federation
- Activity-Relay project on GitHub: A Node.js application that relays public posts from subscribed Mastodon instances to all other subscribers.
- Server prerequisites: A Linux VPS with Node.js 16+, PostgreSQL 12+, and a domain name pointed to the server IP.
- Relay subscription URL format:
https://relay.yourdomain.com/inbox— used by instance admins to subscribe their server.
What Activity-Relay Does and Why You Need It
Activity-Relay is a lightweight Node.js server that implements the ActivityPub relay pattern. When an instance sends a public post to the relay, the relay forwards that post to every other instance subscribed to it. This eliminates the need for instance admins to manually follow users on dozens of remote servers.
The relay does not store posts permanently. It acts as a stateless forwarder. Each post is received, checked for validity, and sent to all subscribers. The relay also handles subscription requests and removals via standard ActivityPub Follow and Undo activities.
Before you begin, you need a Linux server (Ubuntu 22.04 LTS recommended) with at least 1 GB of RAM and 10 GB of storage. You must have root or sudo access. You also need a domain name that points to the server IP address. A reverse proxy like Nginx is required for TLS termination.
Step-by-Step Guide to Build and Run Activity-Relay
- Prepare the server environment
Connect to your server via SSH. Update the package list and install Node.js 16 or later, npm, and PostgreSQL. Run:sudo apt update && sudo apt upgrade -y. Then install Node.js from NodeSource:curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -followed bysudo apt install -y nodejs. Install PostgreSQL:sudo apt install postgresql postgresql-contrib -y. Verify Node.js version:node --versionshould return v16.x or higher. - Create the PostgreSQL database and user
Switch to the postgres user:sudo -i -u postgres. Create a database user for the relay:createuser relayuser -P. Enter a strong password when prompted. Create the database:createdb relaydb -O relayuser. Exit the postgres shell:exit. Test the connection:psql -U relayuser -d relaydb -h localhostand enter the password. Type\qto quit. - Clone the Activity-Relay repository
Navigate to a directory where you want the relay code to live, such as/opt:cd /opt. Clone the official repository:git clone https://github.com/trwnh/activity-relay.git. Change into the cloned directory:cd activity-relay. Install npm dependencies:npm install. This may take a few minutes. - Configure the relay environment file
Copy the example environment file:cp .env.example .env. Open the .env file with a text editor:nano .env. Set the following values:DOMAIN=relay.yourdomain.comDATABASE_URL=postgres://relayuser:yourpassword@localhost:5432/relaydbPORT=3000NODE_ENV=production
Replacerelay.yourdomain.comwith your actual domain. Replaceyourpasswordwith the password you set for the PostgreSQL user. Save and exit. - Initialize the database schema
Run the database migration command:npm run migrate. This creates the required tables in the relaydb database. If you see errors, double-check the DATABASE_URL in your .env file. The migration script runs knex.js internally. - Run the relay server
Start the relay for testing:npm start. The server listens on port 3000. Press Ctrl+C to stop it. For production, use a process manager like pm2:npm install -g pm2. Then start the relay with pm2:pm2 start npm --name "activity-relay" -- start. Save the pm2 process list:pm2 save. Enable pm2 to start on boot:pm2 startupand follow the displayed command. - Set up Nginx as a reverse proxy with TLS
Install Nginx:sudo apt install nginx -y. Create a new site configuration:sudo nano /etc/nginx/sites-available/relay. Add the following content:server { listen 80; server_name relay.yourdomain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name relay.yourdomain.com; ssl_certificate /etc/letsencrypt/live/relay.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/relay.yourdomain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }Enable the site:
sudo ln -s /etc/nginx/sites-available/relay /etc/nginx/sites-enabled/. Test the configuration:sudo nginx -t. Obtain a TLS certificate using Certbot:sudo apt install certbot python3-certbot-nginx -yand runsudo certbot --nginx -d relay.yourdomain.com. Follow the prompts. Reload Nginx:sudo systemctl reload nginx. - Configure firewall and test the relay
Allow HTTPS traffic:sudo ufw allow 443/tcp. Also allow SSH:sudo ufw allow 22/tcp. Enable the firewall:sudo ufw enable. Now open a browser and visithttps://relay.yourdomain.com. You should see a JSON response with{"message":"ActivityRelay running"}. This confirms the relay is operational. - Subscribe a Mastodon instance to your relay
Log in to your Mastodon instance as an admin. Go to Preferences > Administration > Relays. Click the Add relay button. Enter the relay inbox URL:https://relay.yourdomain.com/inbox. Click Save. The instance sends a Follow request to the relay. After a few seconds, the relay status shows Enabled. Repeat this step for any other instances you manage.
Common Setup Problems and How to Avoid Them
Relay Shows “Pending” Status After Adding
If the relay status in Mastodon stays Pending, the relay did not receive the Follow activity. Check the relay logs: pm2 logs activity-relay. Common causes include a missing or incorrect DOMAIN in the .env file, a firewall blocking port 443, or Nginx not forwarding the request correctly. Verify that relay.yourdomain.com resolves to the server IP. Also ensure that the Mastodon instance can reach the relay over the internet.
Posts Not Being Forwarded to All Subscribers
When an instance sends a post, the relay forwards it to every subscriber. If some instances do not receive posts, check that those instances have an active relay subscription. The relay does not store messages, so if an instance was temporarily offline, it misses posts. The relay also does not forward posts to instances that block the originating instance. Review the Mastodon moderation logs on the subscriber instance.
Relay Server Crashes Under Heavy Load
Activity-Relay is single-threaded. If many instances subscribe and traffic spikes, the server may run out of memory. Increase the server RAM to at least 2 GB. You can also limit the number of concurrent connections by adding proxy_buffering off; in the Nginx location block. Monitor resource usage with htop and set up log rotation for pm2 logs.
Activity-Relay vs Built-in Mastodon Relay Feature
| Item | Activity-Relay (Self-Hosted) | Mastodon Built-in Relay |
|---|---|---|
| Deployment | Requires a separate Node.js server | Managed within the Mastodon application |
| Customization | Full control over code and settings | Limited to admin UI options |
| Performance | Dedicated resources, no impact on Mastodon | Shares resources with the Mastodon process |
| Subscription management | Manual via API or admin UI | Built into Mastodon admin panel |
| Maintenance | You handle updates and uptime | Updated with Mastodon itself |
Your relay is now live and accepting subscriptions from any Mastodon instance. To add more instances, repeat the subscription step. You can also remove a relay by clicking Delete in the Mastodon relays admin panel. For advanced management, the Activity-Relay project provides an API endpoint at /api/v1/relays for listing subscribers and checking relay status.