When you run a Mastodon instance, the streaming API handles real-time updates like new posts and notifications. By default, this API runs on the same domain as your web interface. You can improve performance and security by moving the streaming API to a separate subdomain, such as streaming.yourinstance.com. This article explains how to configure Nginx and Mastodon to serve the streaming API from a dedicated subdomain.
Running the streaming API on a separate subdomain reduces load on the main web server and allows you to scale the streaming service independently. It also isolates the WebSocket connections from the main HTTP traffic, which can improve overall reliability. This setup requires access to your Mastodon server, a domain name, and the ability to edit Nginx configuration files.
This guide covers the prerequisites, the Nginx configuration changes, and the Mastodon environment variable updates needed to enable a separate streaming subdomain. It assumes you have a working Mastodon instance running on a single domain and are comfortable editing server configuration files.
Key Takeaways: Streaming API Subdomain for Mastodon
- STREAMING_API_BASE_URL environment variable: Set this to the full URL of your streaming subdomain to redirect WebSocket traffic.
- Nginx reverse proxy for streaming subdomain: Configure a separate server block that proxies requests to the Mastodon streaming service on port 4000.
- DNS A or CNAME record for streaming subdomain: Create a DNS record pointing the streaming subdomain to your server’s IP address.
Why Use a Separate Subdomain for the Streaming API
The streaming API in Mastodon is responsible for delivering real-time data to clients over WebSocket connections. This includes timeline updates, notifications, and other live events. When the streaming API runs on the same domain as the main web application, all HTTP and WebSocket traffic competes for the same Nginx worker processes and server resources.
By moving the streaming API to a separate subdomain, you achieve three benefits. First, you can scale the streaming service independently by running multiple streaming processes or even dedicating a separate server to it. Second, you reduce the risk of WebSocket connections interfering with regular HTTP requests, which can cause timeouts or slow page loads. Third, you can apply different security policies, such as rate limiting or firewall rules, specifically to the streaming subdomain.
Prerequisites for This Setup
Before you begin, ensure you have the following:
- A working Mastodon instance with administrative shell access
- Your own domain name with DNS management access
- Nginx installed and configured as the reverse proxy for Mastodon
- The ability to edit files in
/etc/nginx/sites-available/and/home/mastodon/live/.env.production - Root or sudo privileges on the server
Steps to Configure the Streaming API on a Separate Subdomain
The following steps assume your main Mastodon domain is social.example.com and you want to use streaming.social.example.com for the streaming API. Replace these with your actual domain names.
- Create a DNS record for the streaming subdomain
In your DNS provider’s control panel, add an A record forstreamingthat points to your server’s IP address. If you use a CNAME, point it to your main domain. Wait for DNS propagation, which usually takes a few minutes. - Open the Mastodon environment file for editing
Log into your server via SSH. Navigate to the Mastodon live directory:cd /home/mastodon/live. Open the.env.productionfile with a text editor such as nano:sudo nano .env.production. - Set the STREAMING_API_BASE_URL variable
Add or update the following line in the file:STREAMING_API_BASE_URL=https://streaming.social.example.com
This tells Mastodon to advertise the streaming API at the separate subdomain. Save the file and exit the editor. - Create a new Nginx server block for the streaming subdomain
Create a new configuration file:sudo nano /etc/nginx/sites-available/streaming. Paste the following server block, adjusting the server_name and proxy_pass as needed:server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name streaming.social.example.com; ssl_certificate /etc/letsencrypt/live/social.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/social.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:4000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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; } }If your SSL certificates are stored elsewhere, update the paths accordingly. Save and exit.
- Enable the new Nginx server block
Create a symbolic link to enable the site:sudo ln -s /etc/nginx/sites-available/streaming /etc/nginx/sites-enabled/. - Test the Nginx configuration
Runsudo nginx -tto verify the syntax is correct. If you see any errors, review the file for typos. - Restart Nginx
Apply the changes by restarting Nginx:sudo systemctl restart nginx. - Restart the Mastodon streaming service
Restart the streaming service to pick up the new environment variable:sudo systemctl restart mastodon-streaming.
After these steps, all streaming API requests will be served from streaming.social.example.com. You can verify this by checking your browser’s developer tools for WebSocket connections targeting the new subdomain.
Common Configuration Mistakes and How to Avoid Them
WebSocket Connections Fail After Changing the Subdomain
If clients cannot establish WebSocket connections, the most common cause is missing the Upgrade and Connection headers in the Nginx proxy configuration. Ensure your server block includes proxy_set_header Upgrade $http_upgrade; and proxy_set_header Connection "upgrade";. Without these headers, Nginx does not forward the WebSocket upgrade request to the Mastodon streaming process.
SSL Certificate Mismatch for the Streaming Subdomain
If you use a single wildcard certificate for social.example.com, it covers the streaming subdomain automatically. If you use separate certificates, you must obtain one for the streaming subdomain. A missing or expired certificate causes the browser to refuse the WebSocket connection. Use Certbot to issue a certificate for the streaming subdomain if needed.
Environment Variable Not Taking Effect
After editing .env.production, you must restart the mastodon-streaming service. A simple reload does not apply the new variable. Run sudo systemctl restart mastodon-streaming to ensure the service reads the updated configuration.
Comparison: Streaming API on Main Domain vs Separate Subdomain
| Item | Main Domain | Separate Subdomain |
|---|---|---|
| Configuration complexity | Low – no extra DNS or Nginx blocks | Medium – requires DNS record, Nginx block, and env variable |
| Resource isolation | None – streaming shares resources with web app | Full – can scale streaming independently |
| WebSocket stability | May degrade under high HTTP load | Isolated from HTTP traffic, more stable |
| Security policy granularity | Same policies for all traffic | Can apply rate limiting or firewall rules per subdomain |
| Maintenance effort | Minimal | Requires updating two configurations if domain changes |
With the separate subdomain configuration, your Mastodon instance can handle more concurrent users and real-time updates without affecting the performance of the main web interface. The trade-off is a slightly more complex setup that you must maintain when updating the instance or changing domains.
You can now serve the streaming API from a dedicated subdomain, which improves scalability and isolation. Next, consider setting up a dedicated streaming process with multiple workers by adjusting the STREAMING_CLUSTER_NUM environment variable. For advanced setups, you can even host the streaming service on a separate server entirely by pointing the proxy_pass to a remote IP address.