This was easier than expected. For the most part, I followed the official "Installing from source" documentation. But there were some differences, too. Therefore writing this up might be useful for someone with a similar setup.
The Stack I Used
The Boring Stuff
Surprisingly deploying Mastodon is very similar to deploying a Django application. Which might explain why it took me less time than expected. For Django projects, I also often have to deploy NodeJS, because it's some SPA in front of a JSON API. And installing Ruby is also similar to how I install Python: build it from source.
Mastodon is deployed by an ansible playbook executing the following tasks:
- Install all required system packages like ImageMagick / libjemalloc-dev...
- Create a separate Unix user to isolate the instance
- Create a dedicated Postgres database and user
- Use nvm to install the latest v16 node version (maybe it's safe to use a newer one?)
- Use rbenv to install ruby 3.0.4 (maybe use a newer one?)
- Clone the mastodon repository and install all the required gems / run database migrations / build static assets
- Create a .env.production file from a template
- Create a dynamic config for traefik
- Create systemd unit files for sidekiq, web, and streaming
Then, there's a second playbook that removes all things the deploy playbook created. It's really useful to have a playbook like this to be able to test whether the complete deployment works from scratch after changes.
And then there are two playbooks dealing with backup / restore of the database. Restore is necessary because you don't know whether your backup works if you haven't tried to restore it yet 😁. In this case, it all worked pretty seamlessly using just the standard ansible community.general.postgresql_db module with backup and restore states.
As I said, this is all pretty standard, pretty boring stuff. And I'm bad at writing ansible playbooks so I'm a little bit hesitant to publish those. But if you want to see them: drop me a line via Email or Mastodon.
The traefik config is a little bit different from other web services usually deployed because there are two services to which traefik should load-balance to:
In the original documentation, Nginx was used to serve files like images or videos. But for an instance with not much traffic, it's probably fine to use the built-in file-serving capabilities of puma the application server that is used to run RoR. The only configuration parameter you have to set is:
In the systemd unit file for the Mastodon web (RoR) service.
Using a Vanity Username
My new Mastodon instance is running at fedi.wersdoerfer.de, but I'd like to have @firstname.lastname@example.org as my username. A little bit of configuration is needed to make that happen which I read about in Getting Mastodon running on a custom domain - a blog post by Simon Willison:
Need to be added to the
.env.production file. Then I had to make some redirects to make wersdoerfer.de/@jochen point to the right location. I did pretty much the same thing as Andrew Godwin described in his article The Fediverse, And Custom Domains.
Just a screenshot to remember how the result looked like 🙂: