Mastodon instances store user-uploaded images, videos, and other media files. Local storage can fill up quickly and become expensive to scale. Cloudflare R2 offers an S3-compatible object storage service with no egress fees, making it a cost-effective option for Mastodon admins. This article explains how to configure Cloudflare R2 for your Mastodon instance and breaks down the expected costs.
Key Takeaways: Cloudflare R2 Setup and Cost Overview for Mastodon
- Cloudflare R2 bucket configuration: A public bucket with S3-compatible credentials is required for Mastodon media storage.
- Mastodon environment variables: S3_ENABLED, S3_BUCKET, S3_REGION, S3_ENDPOINT, and S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY must be set correctly.
- No egress fees: R2 charges only for storage and API operations, not for data transfer out of Cloudflare.
Why Cloudflare R2 for Mastodon Media Storage
Mastodon’s default local storage uses the server’s hard drive. As users upload media, disk space runs out. Admins must either resize the server disk or offload files to external storage. Traditional S3 providers like Amazon S3 charge egress fees when media is served to users. Cloudflare R2 eliminates egress fees entirely. This means you only pay for the storage your media occupies and the API requests used to read and write files. For Mastodon instances with moderate to high traffic, R2 can reduce monthly costs significantly compared to other object storage services.
Prerequisites for Using R2 with Mastodon
Before starting the setup, you need a Cloudflare account with billing enabled. Create an R2 bucket in the Cloudflare dashboard. The bucket must be set to public access so Mastodon can serve media directly from it. You also need an S3-compatible API token with read and write permissions for that bucket. Mastodon supports S3-compatible storage natively since version 3.1. Verify your Mastodon version before proceeding.
Steps to Configure Cloudflare R2 for Mastodon
The configuration involves two parts: creating the R2 bucket and setting the correct environment variables in your Mastodon deployment. Follow these steps exactly.
- Create an R2 bucket in Cloudflare Dashboard
Log in to your Cloudflare account. Go to R2 and click Create Bucket. Enter a unique bucket name, such as mastodon-media-yourinstance. Select the region closest to your server. Leave the default settings for object locking and versioning. After creation, click on the bucket name and enable Public Access under the Settings tab. - Generate an R2 API token
In the R2 dashboard, go to Manage R2 API Tokens. Click Create API Token. Choose the permission level: Admin Read and Write. Select the specific bucket you just created. Copy the Access Key ID and Secret Access Key immediately. Cloudflare does not show the secret again. - Set Mastodon environment variables
Edit your Mastodon environment file. This file is usually located at /home/mastodon/live/.env.production or defined in your Docker Compose file. Add or update the following variables:S3_ENABLED=true
S3_BUCKET=mastodon-media-yourinstance
S3_REGION=auto
S3_ENDPOINT=https://youraccount.r2.cloudflarestorage.com
S3_ACCESS_KEY_ID=your_access_key_id
S3_SECRET_ACCESS_KEY=your_secret_access_keyReplace youraccount with your Cloudflare account ID. You can find this in the Cloudflare dashboard under R2 > Bucket > Settings > S3 API.
- Restart Mastodon services
Run the following commands to apply the changes:cd /home/mastodon/live
RAILS_ENV=production bin/tootctl cache clear
systemctl restart mastodon-web mastodon-sidekiq mastodon-streamingIf you use Docker, restart the containers instead.
- Verify media is stored in R2
Upload a test image in your Mastodon web interface. Then check the R2 bucket in the Cloudflare dashboard. The file should appear. Also confirm that the image loads correctly in the browser. If the image is broken, check the public access setting and the S3_ENDPOINT URL.
What to Avoid When Using R2 with Mastodon
Media Uploads Fail with 403 Forbidden
This usually happens when the API token lacks write permission for the bucket. Regenerate the token with Admin Read and Write permissions. Also ensure the bucket name is spelled exactly in the S3_BUCKET variable.
Images Load Slowly or Time Out
R2 serves media through Cloudflare’s global network. If your Mastodon instance is far from the selected R2 region, latency increases. Choose a region geographically close to your server. You can also enable Cloudflare’s cache rules to reduce repeated fetches from R2.
Existing Local Media Not Migrated
After switching to R2, previously uploaded media remains on the local disk. To move it, run the following command:
RAILS_ENV=production bin/tootctl media remove –days=0
This command deletes cached local copies after they have been uploaded to R2. Run it only after confirming R2 is working correctly.
Cloudflare R2 vs Amazon S3 for Mastodon Media Storage
| Item | Cloudflare R2 | Amazon S3 |
|---|---|---|
| Egress fees | None | $0.09 per GB after first 100 GB |
| Storage cost | $0.015 per GB per month | $0.023 per GB per month |
| Class A operations (write) | $4.50 per million requests | $5.00 per million requests |
| Class B operations (read) | $0.36 per million requests | $0.40 per million requests |
| Global network | Cloudflare CDN included | Requires CloudFront for CDN |
Cloudflare R2 is generally cheaper for Mastodon instances that serve a lot of media to users. The absence of egress fees alone can save hundreds of dollars per month for busy instances. Amazon S3 may still be a better choice if you already use other AWS services and want tighter integration. For most Mastodon admins, R2 provides the simplest and most cost-effective media storage solution.