Mastodon on AWS: Host your own instance

Andreas Wittig – 17 Nov 2022

While Twitter seems to be in chaos, the free and decentralized alternative, Mastodon, is rising. At first glance, Twitter and Mastodon are similar. A toot is to Mastodon what a tweet is to Twitter. However, the decentralized nature of Mastodon makes a big difference. If you want to register with Mastodon, you first have to choose an instance (see instances.social). And it’s even possible to host your own Mastodon instance. That’s what we are up to: social.cloudonaut.io.

Speaking of Mastodon, don’t forget to connect with us in the fediverse: @andreas@social.cloudonaut.io and @michael@social.cloudonaut.io.

Mastodon on AWS

In the following, I will share details on how to deploy a Mastodon instance on AWS in case you want to host your own server as well.

AWS Architecture for Mastodon on AWS

The following figure shows our architecture to deploy Mastodon on AWS.

  • Route 53
  • Application Load Balancer (ALB)
  • ECS + Fargate
  • RDS for Postgres
  • ElastiCache for Redis
  • S3
  • SES
  • CloudWatch
  • VPC
  • IAM

Mastodon on AWS: Architeture

What’s missing? So far, I did not deploy Elasticsearch yet. Elasticsearch provides optional search capabilities for Mastodon, for example, to search through your toots. I also haven’t deployed CloudFront as a CDN yet in front of the static files hosted on S3 and maybe even for some files delivered by the web application itself.

Costs for running Mastodon on AWS

Estimating costs for AWS is not trivial. My estimation assumes a small Mastodon instance for 1-50 users. The architecture’s monthly charges are about $60 per month. The following table lists the details.

Service Configuration Monthly Costs (USD)
ECS + Fargate 3 Spot Tasks x (0.25 CPU + 0.5 GB) $8.66
RDS for Postgres t4g.micro (Multi-AZ) $23.61
ElastiCache for Redis t4g.micro (Single-AZ) $11.52
ALB Load Balancer Hours $16.20
S3 25 GB + requests $0.58
Route 53 Hosted Zone $0.50
Total $61.08

Please note that my cost estimation is not complete. For example, the estimation does not include network traffic, CloudWatch, SES, or domain.

Isn’t there a cheaper way to host Mastodon on AWS?

Why not run Mastodon on a single EC2 instance?

Of course, you could also run Mastodon, the Postgres database, the Redis in-memory database, and even Elasticsearch on a virtual machine. Assuming all that fits on an EC2 instance of type t4g.medium, you are paying about $25 per month. That’s a simple and cost-effective way to run Mastodon on AWS. However, you get the following benefits by outsourcing data storage to services like RDS, ElastiCache, and S3:

  1. You are able to scale the application layer horizontally by adding virtual machines or containers.
  2. You reduce maintenance effort. For example, managed services like RDS come with automated patching and backups.
  3. You increase the resilience and availability as the managed services spread the storage layer among multiple availability zones out of the box.
  4. You enable 0-downtime deployments, as you can spin up virtual machines or containers with the new version before terminating the old ones.

Deploying Mastodon containers

Luckily, Mastodon maintains a container image tootsuite/mastodon that we can use to deploy the three services a Mastodon instance consists of:

  • web delivers the web application consisting of a frontend and backend (Ruby on Rails).
  • streaming allows clients to subscribe to server-sent events for real-time updates via a long-lived HTTP connection or WebSocket.
  • sidekiq orchestrates and executes background jobs.

As all three services are bundled into a single container image, it is necessary to use different commands when starting the containers.

  • bundle exec rails s -p 3000 to start the web application.
  • node ./streaming to start the streaming API.
  • bundle exec sidekiq to start sidekiq.

Configuring Mastodon is simple. All parameters are configurable via environment variables. See Configuring your environment for a list of all parameters.

What I learned from running Mastodon on AWS

  1. Aurora Serverless v1/v2 is not a good choice for Mastodon, as there is load on the database even if no users are actively using the instance. So Aurora Serverless v1 cannot pause. In general, Aurora Serverless is quite expensive, a minimal RDS for Postgres instance reduces costs.
  2. Mastodon stores the Home timeline in Redis. I replaced an ElastiCache instance which resulted in an empty Home timeline that Mastodon backfills asynchronously.
  3. The following configuration files from the Mastodon repository help understand how to deploy Mastodon containers: Dockerfile, docker-compose.yml, and nginx.conf.
  4. As we are currently running a minimal Mastodon instance, I could not verify it, but it should be possible to scale Mastodon horizontally (except the Postgres database).
  5. Updating from version v3.5.3 to v4.0.2 worked by replacing the container image tags in my CloudFormation template.

Launch a Mastodon instance on AWS in 30 minutes

We started working on an Infrastructure as Code project about a week ago: widdix/mastodon-on-aws. The project allows you to deploy Mastodon on AWS with a few clicks in about 30 minutes.

First, you need an AWS account.

Second, a top-level or subdomain where you can configure an NS record to delegate to the Route 53 nameservers is required. For example, you could register a domain with Route 53 or use an existing domain and add an NS record to the hosted zone.

Third, click here to deploy Mastodon on AWS to your AWS account.

To generate the required secrets and keys, use the following commands.

# Start Docker container locally
$ docker run -it tootsuite/mastodon:latest sh

# Generate SECRET_KEY_BASE
$ bundle exec rake secret
758a3b431265776b9ab55910890162bb84aec0617724ca611475c3a774965f2d0aca183091d3c1a84ff3640cf7cc438c559034a2735253ee895b7a2308ac450c

# Generate OTP_SECRET
$ bundle exec rake secret
c528b5cbb0236e4b0c2fe38a6d7ed1edc5fa12608c67a45690e225f005bad8bfbabfa99f7b83cb9c0981ba8fcc5fd76c68918d9bc854bd158c2c23fd6df89abc

# Generate VAPID_PRIVATE_KEY and VAPID_PUBLIC_KEY
$ bundle exec rake mastodon:webpush:generate_vapid_key
VAPID_PRIVATE_KEY=am3vlPBGQGv7Rl3xOKXSv7lRYyWfZITItb88FXX9IOs=
VAPID_PUBLIC_KEY=BMGkIr1PaK4v7Kut7q7eoHtWxu9gEBQ5BeV28xOIR9c9VIvDWvOViTn1SV5G2LIEFGWo0f1dQka-UynR58WMn2Y=

Summary

I’m curious to see if Mastodon catches on as an alternative to Twitter for us. Running your own Mastodon instance under your domain is a plus. And with AWS and our Infrastructure as Code project widdix/mastodon-on-aws, it’s not hard at all.

Andreas Wittig

Andreas Wittig

I’ve been building on AWS since 2012 together with my brother Michael. We are sharing our insights into all things AWS on cloudonaut and have written the book AWS in Action. Besides that, we’re currently working on bucketAV,HyperEnv for GitHub Actions, and marbot.

Here are the contact options for feedback and questions.