The title of the post says it all … this is how to run 2 (or more) instances of Mastodon on the same server instance. It’s actually not that hard!

The Basics

  1. Install [Instance1] as normal into [Folder1] using the normal instructions including all configs and nginx publish, enure that is working correctly as a standalone instance.
  2. Install [Instance2] into [Folder2] skipping any aspects that are server wide:

Postgres (we can just create a second database)
Ruby
Node.js
Yarn

You won’t actually break anything if you do, it will just skip and say things are already there.

Otherwise just step through the installation process as normal, remembering to create a second database and when you run through the setup to choose that second database.

After the setup and compilation is where things go a bit different.

The Second Instance

We will leverage the running instance and make changes to run the second instance.

.env.production

There is one change to add to the [Instance2] .env.production file for REDIS to ensure they don’t clash.

REDIS_NAMESPACE=[Instance2]

If you don’t add this you will find some little irregularities happen :)

System Templates

As we already have a running and working instance on the server, we will first duplicate the system templates from that instance.

sudo cp /etc/systemd/system/mastodon-sidekiq.service /etc/systemd/system/[Instance2]-sidekiq.service

sudo cp /etc/systemd/system/mastodon-streaming.service /etc/systemd/system/[Instance2]-streaming.service

sudo cp /etc/systemd/system/mastodon-web.service /etc/systemd/system/[Instance2]-web.service

Now we have duplicate service templates, we edit to point to our second instance.

In [Instance2]-web.service edit these lines:

Description=[nstance2]-web
WorkingDirectory=[path to second instance]
Environment=“PORT=3001” (the first one is 3000, you can use anything else not in use)
ReadWritePaths=[path to second instance]

In [Instance2]-sidekiq.service edit these lines:

Description=[Instance2]-streaming
WorkingDirectory=[path to second instance]
Environment=“PORT=4001” (the first is 4000, you can use anything else not in use)
ReadWritePaths=[path to second instance]

In [Instance2]-streaming.service edit these lines:

Description=[Instance2]-sidekiq
WorkingDirectory=[path to second instance]
ReadWritePaths=[path to second instance]

Then run

sudo systemctl daemon-reload

And enable the services

sudo systemctl enable --now [Instance2]-web [Instance2]-sidekiq [Instance2]-streaming

Check that they are running by typing

sudo systemctl status [each service name]

and you should be able to run a grep across each of the 4 ports and see they are running

sudo ss -lnpt | grep [3000|3001|4000|4001]

NGINX

We begin this part as we did with [Instance1] by copying the base nginx template

sudo cp /var/www/mastodon/dist/nginx.conf /etc/nginx/conf.d/[Instance2].conf

And updating per standard instructions for the server_name, root location and snakeoil SSL, and then this time we need to edit it further.

In [Instance2].conf, edit as follows:

Change backend to backend2 (or another name) and change the port to 3001

upstream backend2 {
server 127.0.0.1:3001 fail_timeout=0;

Change streaming to streaming2 (or another name) and change port to 4001

upstream streaming2 {
server 127.0.0.1:4001 fail_timeout=0;

Change the proxy_cache_path to a second location (path and keys_zone)

proxy_cache_path /var/cache/nginx2 levels=1:2 keys_zone=CACHE2:10m inactive=7d max_size=1g;

Under the “location ^~ /api/v1/streaming” block, change the proxy_pass to be the same as you used above

proxy_pass http://streaming2;

Under the “location @proxy” block, change the proxy_pass to be the same as you used above

proxy_pass http://backend2;

Create the second NGINX cache location:

sudo mkdir -p /var/nginx/cache2/

If you did everything right, you can run an nginx test and you should be good!

sudo nginx -t

Run a reload of nginx and then last step in SSL.

sudo systemctl reload nginx

SSL Certificate

This is no different, but the commands are

sudo apt install certbot python3-certbot-nginx

and then (replacing the email and domain name)

sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email you@example.com -d social.example.com

And Done

At this point you should have 2 fully functioning Mastodon servers operating independently. If you want to take a run at running with less resources (but more complexity in some ways like updating and having to run the same version/fork, take a look at at this post.

Final Notes

Remember to update your backup scripts for the second database and .env.production file.

Oh, and yes, you can run different versions and forks on each instance, I have a standard Mastodon 4.0.2 in one instance and a Glitch-soc on the other :)