4.4 KiB
| title | domain | category | tags | status | created | updated | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Mastodon Instance Tuning | selfhosting | services |
|
published | 2026-04-02 | 2026-04-29T22:45 |
Mastodon Instance Tuning
Running your own Mastodon instance means you control the rules — including limits the upstream project imposes by default. These are the tweaks applied to majortoot (MajorsHouse's Mastodon instance).
Increase Character Limit
Mastodon's default 500-character post limit is low for longer-form thoughts. You can raise it, but it requires modifying the source — there's no config toggle.
The process depends on your deployment method (Docker vs bare metal) and Mastodon version. The community-maintained guide covers the approaches:
Key points:
- The limit is enforced in both the backend (Ruby) and frontend (React). Both must be changed or the UI will reject posts the API would accept.
- After changing, you need to rebuild assets and restart services.
- Other instances will still display the full post — the character limit is per-instance, not a federation constraint.
- Some Mastodon forks (Glitch, Hometown) expose this as a config option without source patches.
Media Cache Management
Federated content (avatars, headers, media from remote posts, preview cards) gets cached in S3. On an active single-user instance federating with large servers, this grows fast — the majortoot bucket hit 648 GB with only ~7 GB of actual local content. The other ~620 GB was remote cache.
Check current usage
# Bare metal (rbenv)
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
cd /home/mastodon/live
RAILS_ENV=production bin/tootctl media usage
Output breaks down by type with local vs total — the gap between those two numbers is all purgeable remote cache.
Manual prune
Run these three commands to clear all remote cache types:
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
export RAILS_ENV=production
cd /home/mastodon/live
# 1. Remote media attachments older than 7 days
bin/tootctl media remove --days=7 --concurrency=5
# 2. Remote avatars and headers (accounts not followed/following locally)
bin/tootctl media remove --prune-profiles --remove-headers --days=7 --concurrency=5
# 3. Preview card thumbnails older than 30 days
bin/tootctl preview_cards remove --days=30 --concurrency=5
Note: On a large cache (hundreds of GB, millions of objects), each command can take 30–60+ minutes. Run in
tmuxto survive SSH disconnection.
Automate with weekly cron
Deploy via configure_mastodon_media_prune.yml Ansible playbook. It installs a wrapper script and cron entry for the mastodon user.
Manual crontab entry:
0 3 * * 0 /home/mastodon/media-prune.sh
Log output goes to /var/log/mastodon/media-prune.log.
Reduce S3 storage class costs
By default Mastodon uploads to S3 Standard ($0.023/GB/mo). Switching to Standard-IA halves the storage cost for infrequently accessed media:
# In /home/mastodon/live/.env.production
S3_STORAGE_CLASS=STANDARD_IA
Then restart Mastodon. New uploads will use Standard-IA ($0.0125/GB). Note the 30-day minimum charge per object — fine for media attachments, less ideal for very short-lived objects.
What is and isn't removed
- ✅ Removed: Cached copies of remote users' media, avatars, headers, preview card thumbnails
- ✅ Re-fetched on demand: Remote media is pulled again if someone views the post
- ❌ Never removed: Your local posts' media, your account's avatar/header, Mastodon account export backups (
/backups/) - ❌ Not affected: PostgreSQL database, local disk usage outside S3
Gotchas & Notes
- Character limit changes break on upgrades. Any source patch gets overwritten when you pull a new Mastodon release. Track your changes and reapply after updates.
tootctlis your admin CLI. It handles media cleanup, user management, federation diagnostics, and more. Runtootctl --helpfor the full list.- Monitor disk usage. Even with cache cleanup, the PostgreSQL database and local media uploads grow over time. Keep an eye on it.