Mastodon development environments on Release and AWS
Twitter users are flying the coop in droves and many are turning to Mastodon, an open-source federated social network.
Unlike Twitter’s centralized architecture, a federated social network consists of thousands of individual social networks, called instances, each with its own users.
Federation is sometimes described as being similar to email in the sense that email users can send each other messages, even if they have different email hosts and use different domains.
Mastodon instances fetch content from other instances, which allows a user on one server to follow a user on a different server, thereby creating one big network.
To the DevOps-minded among us, the most compelling thing about the fastest-growing Twitter alternative is figuring out how to host and scale this exciting new platform.
At Release, we enable teams to create development, staging, and production environments for their apps. If you intend to add new features or otherwise modify your Mastodon instances, Release can provide the environment you need to move your project forward. Whether you want to just take Mastodon for a spin to see what it’s all about, or run a production Mastodon instance that can scale up as you need, using Release means you don’t have to trade off simplicity for power. You can easily collaborate with your colleagues, preview the latest features, and upgrade to the latest builds.
In this post, we’ll put Mastodon’s welcoming community and complex federation protocols aside so that we can focus on the nuts and bolts of hosting a Mastodon instance.
What makes a Mastodon instance
A Mastodon instance consists of seven services:
- A web server, which runs on Ruby on Rails.
- A streaming server that enables the instance’s local users to send and receive real-time updates to the server.
- Sidekiq, a job scheduler that runs background tasks, polls other instances’ web servers, and sends data to other instances’ web servers.
- A Redis server that stores jobs for Sidekiq and caches data such as feeds for local users.
- A PostgreSQL database that stores posts, user profiles, and instance settings.
- File storage to store and serve media such as images and videos.
An SMTP email server to send messages to local users’ email accounts.
How we’ll run a Mastodon instance on Release and AWS
Release creates Kubernetes clusters in your AWS account.
Although all seven of Mastodon’s services could be hosted on Kubernetes, we’ll use a few AWS-provided services to host supporting systems.
We’ll create containers to run Mastodon’s web server, streaming server, and Sidekiq in Kubernetes.
From AWS, we’ll use:
- Amazon ElastiCache for Redis
- Amazon RDS to host a PostgreSQL server
- Amazon S3 as a file store
- Amazon SES to send emails to local users
Prepare your Release account
Before we get started, you’ll need to create a Release account and upgrade to a paid account.
Next, verify your domain in Release, and create a cluster using the AWS integration.
Configuration details to save
In this guide, configuration details to note down will be pointed out with the heading: Configuration details to save.
While in Release, navigate to your cluster, and note down the following:
- The cluster context.
- Your cluster region.
Your node group.
Prepare your local machine
On your local system, you’ll need to install Git and Docker.
Keep a text editor handy to take notes. We’ll gather configuration details as we go along, and saving these in a central file will make setting up your environment much easier later.
Fork the Mastodon repository on GitHub
Fork the Mastodon repository from GitHub to your GitHub, Bitbucket, or GitLab account. We’ll use GitHub in this guide.
- Log into your GitHub account.
- Fork the Mastodon repository.
GitHub creates a public fork by default. Since Mastodon is AGPL-licensed, keeping your fork public is a good way to make sure you adhere to licensing requirements from the start.
Configuration details to save
Make a note of your repository name from GitHub.
Clone your Mastodon fork to your local machine
- On the main page of your repository on GitHub.com, click <>Code.
- Copy the URL for the repository.
- Open your terminal and navigate to where you want to clone your repository.
- Clone your repository using the URL you copied
- Change your current working folder to the new repository and keep your terminal open to use again later.
Generate Mastodon secret keys and VAPID keys
Mastodon needs three secret keys and one public key to run. We’ll generate these using the tootsuite/mastodon Docker image on our local machine.
- Set a local environment variable SECRET_KEY_BASE. In your terminal, run:
- Set a local environment variable OTP_SECRET, by running the following in your terminal:
- Generate VAPID keys, using the SECRET_KEY_BASE and OTP_SECRET as inputs, and print our new keys to the terminal.
Configuration details to save
Copy and save VAPID_PRIVATE_KEY, VAPID_PUBLIC_KEY, SECRET_KEY_BASE, and OTP_SECRET values from the output, which should look something like this:
AWS Step 1: Create a PostgreSQL database using Amazon RDS
Log in to your AWS account and navigate to RDS.
Make sure your AWS region is set to the same region as your Release cluster.
Create a new PostgreSQL 14 database:
- Click on create database.
- Select standard create.
- Select PostgreSQL as the engine type.
- Pick PostgreSQL 14.5-R1 as the engine version.
- Select Free tier if you’re only setting up a small/test instance.
- Set the DB instance identifier to mastodon-1. We’ll need to refer to this again later.
- To make sure you don’t use more space than needed, change the allocated storage to 20 GiB.
- Disable autoscaling.
- Under the connectivity section, select the virtual private cloud (VPC) that Release created for your cluster. This will enable services running in the cluster to reach your new database.
- Choose to allow an existing security group.
- Under Existing VPC security groups, pick the security group that starts with eks-cluster-sg- followed by your cluster context, then close the dropdown.
- Click Create database.
Your database will take a few minutes to launch.
Configuration details to save
Once the database is ready, click on view connection details and note down the database endpoint and database password.
AWS Step 2: Create a Redis cache using Amazon ElastiCache
Before we create a Redis cache, we’ll need to get the VPC ID for our Release cluster (Amazon ElastiCache does not show the full VPC name when creating a Redis cluster).
In AWS, navigate to VPC, then note down the VPC ID for your Release cluster.
With the VPC ID at hand, we can create a Redis cluster. In your AWS account, navigate to ElastiCache.
- Click on create cluster.
- Select create Redis cluster.
This opens up the cluster settings page, where we’ll configure our Redis cluster.
Under cluster info, set a name for this Redis cluster, for example, mastodon-redis.
In the connectivity section:
- Set a name for the Redis cluster’s subnet, for example, mastodon-redis-subnet.
- Select your Release cluster’s VPC ID from the dropdown.
Click Next.
Under selected security groups, click Manage.
- Filter the security groups to find one that starts with eks-cluster-sg-.
- Select the security group that starts with eks-cluster-sg- followed by your Release cluster’s context.
- Click choose.
Screenshot of Redis advanced settings page
Scroll down to the bottom of the page and click next.
Scroll down the page to review your Redis settings, then click on create.
AWS will take a moment to create your Redis cluster.
Configuration details to save
Open the Redis cluster’s details and copy the Redis cluster’s endpoint (you can omit the port number).
AWS Step 3: Create an Amazon S3 bucket for user media
In your AWS account, navigate to S3.
Click on create bucket.
Enter a unique bucket name, for example, mastodon-media-example.
Uncheck Block all public access.
Check “I acknowledge that the current settings might result in this bucket and the objects within becoming public”.
Click create bucket.
AWS will take a moment to create your new S3 bucket.
AWS Step 4: Create an IAM user to write to S3
In your AWS account, navigate to Identity and Access Management (IAM).
Click on Users, then on Add users.
- Enter a username, for example, mastodon-s3-writer.
- Under Select AWS credential type, select only Access key - Programmatic access.
- Click Next: Permissions.
On the Set permissions page:
- Select Attach existing policies directly.
- Filter for s3 policies.
- Check AmazonS3FullAccess.
- Click Next: Tags.
Click Next: Review.
Finally, click Create user.
Configuration details to save
Note down the access key ID and secret access key. Keep in mind that you won’t be able to see this secret again, so you’ll need to save it now and keep it secure.
AWS Step 5: Create an Amazon SES identity
In AWS, navigate to Amazon Simple Email Service (SES).
Click Create identity.
- Select Email address as the identity type.
- Enter an email address where you can receive emails.
- Click Create identity.
You’ll need to log in to the inbox for the email address you entered and verify the SES sending identity by clicking a link. Look for an email with the subject “Amazon Web Services – Email Address Verification Request”.
Back in AWS, you should now see that the identity status has changed to verified. If not, reload the page.
Send a test email to see whether the sending identity works.
Click on SMTP settings in the left sidebar, then on Create SMTP credentials.
Click Create.
Configuration details to save
Toggle Show User SMTP Security Credentials, then copy and save the SMTP username and password. You won’t have access to the password again after this step, so keep it secure.
After saving the credentials, click Close.
Create an application in Release
Log in to your Release account, then click on create new app.
- Enter a name for your Mastodon app, for example, mastodon.
- Pick your forked repository.
- Click Next step.
Pick your services in Release
- Select Analyze the repository
- Select the branch you would like to run.
- Select the root docker-compose.yml file.
- Click Start Analysis.
Release will now find services in your docker-compose.yml file.
Pick only the following services:
- sidekiq
- streaming
- web
Click Next Step.
Edit the generated template
Release generates a template from the services we selected in the previous step.
This template is a YAML file that Release uses to generate new environments. It specifies the services, ingress rules, and workflows required to set up your app.
Double-check the template context and domain
Make sure the context in your application template matches your Release cluster’s context and that the domain matches the verified domain you’d like to use for this application.
Replace hostnames with rules
Release automatically generates hostname templates for services that have node ports and adds them to a hostnames section in your Application Template.
On a Mastodon server, the public services web and streaming share a hostname but are served at different paths.
Release configures a Kubernetes ingress controller to route traffic to your applications, based on the hostnames or rules settings, but only one of these settings can be used per environment. We’ll use only rules.
Update the template to replace hostnames with the following rules:
The changes should look like this:
This instructs Release to create two Nginx location blocks on the Kubernetes ingress controller for your application, to direct requests to either web or streaming, depending on the path in the request.
Update the readiness_probe for Sidekiq
In the sidekiq service, replace the readiness_probe with the following:
Update the readiness_probe for the webserver
In the web service, replace the readiness_probe with the following:
Update the readiness_probe for the streaming server
In the streaming server, replace the readiness_probe with the following:
Add database migrations as jobs
Release can run jobs in your environments to handle once-off or repeat tasks. These can be triggered by steps in an environment’s workflows.
For example, when Release first creates an environment for Mastodon, a db:setup job needs to be run to create Mastodon’s database schema. Release calls this stage in the workflow setup.
Mastodon also needs to run database migrations during version upgrades, so that the database schema is updated along with the code. We can use Release’s patch stage for this job.
During version upgrades, Mastodon splits pre-deployment and post-deployment database migrations. We’ll add two migration jobs, dbmigratepre and dbmigrate.
Add the following jobs to your template:
Add an admin user as a job
After our services are live and the database is ready, we’ll use the Mastodon CLI to create an admin user.
Add the following job to the jobs you created earlier:
Add jobs to workflows
Let’s update the workflows section to run these jobs during setup and patch stages.
Because the order in which our new jobs are run is important, we’ll update the parallelize sections in these stages to create new steps.
Replace the workflows section of the template with the following:
Save your changes to the template
Click Next Step to save your template, and move on to your environment variables.
Edit the default environment variables
For this step, you’ll need to retrieve the following information that we saved previously:
Generated on your local machine using Docker
- SECRET_KEY_BASE
- OTP_SECRET
- VAPID_PRIVATE_KEY
- VAPID_PUBLIC_KEY
PostgreSQL endpoint and password from Amazon RDS
- DB_HOST
- DB_PASS
Redis cluster endpoint from Amazon ElastiCache
- REDIS_HOST
SMTP credentials from Amazon Simple Email Service
- SMTP_LOGIN
- SMTP_PASSWORD
- SMTP_SERVER: Get the SES endpoint for your region from AWS docs
- SMTP_FROM_ADDRESS: This is the verified email address Mastodon will send emails from
S3 bucket details and IAM access keys
- S3_BUCKET
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- S3_REGION
Mastodon user details
- MASTODON_OWNER_USERNAME: Some names, such as admin, owner, and user, are reserved. Use something unique.
- MASTODON_OWNER_EMAIL: Use an email address you can receive your sign-up email at. Keep in mind that Amazon SES can only send messages to verified email addresses while in sandbox mode.
In Release, paste the following environment variables file in the default environment variables YAML editor, then update any values that are empty with the values we saved previously.
Click Next Step to save your default environment variables.
Deploy the app
You can skip over the build arguments step because we’re not adding any build arguments to this application.
Finally, click Deploy your app!
Follow the deployment
Release will now build Docker images for our services and deploy an environment.
The deployment information page shows all of the steps involved, from building the Docker images, through database migrations, and finally adding your admin user.
Click the mastodonuser job step to reveal the output, and copy the password Mastodon generated for your user.
If you miss this password, you can use the Mastodon web interface to request a password reset.
Log in and start posting
With your Mastodon instance up and running, log in and start posting.
You can find the public URL for your instance by navigating to the Environment Info page in Release. Click the web URL in the right sidebar to visit your instance.
What to do next: create more environments
Release really shines when you create environments for different branches in your codebase.
Test this by creating a feature branch with a small change, and follow Release’s guide on creating a new environment for your new branch.
Further reading
Even if Mastodon doesn’t replace Twitter, it will likely only grow in popularity. If you plan to host a public instance for your organization, you may want to make sure you focus on two important aspects: moderation and scaling.
Running any community on the internet is notoriously hard to get right. Keeping users, the public, and your servers happy might seem impossible, but many have gone before us and shared their experiences.
Here’s a quick overview of recent writing on these topics:
- Scaling up your server: The official Mastodon documentation on scaling your server, which might not be as suited to a Kubernetes-hosted instance.
- Moderation actions: The official Mastodon documentation on available moderation tools. These are invaluable if you plan to allow public content on your instance.
- Mastodon Server Covenant: A covenant which can also inform your moderation and hosting decisions.
Learn more about Release
Of course, you aren't limited to hosting Mastodon. If you want to learn more about how Release can help you host your own software or other third party packages, book a demo.
About Release
Release is the simplest way to spin up even the most complicated environments. We specialize in taking your complicated application and data and making reproducible environments on-demand.
Speed up time to production with Release
Get isolated, full-stack environments to test, stage, debug, and experiment with their code freely.