Knowledgebase › Mastodon on a LYLIX VPS — sidekiq scaling, S3-compatible storage, federation traffic

Mastodon on a LYLIX VPS — sidekiq scaling, S3-compatible storage, federation traffic

Mastodon is the most-self-hosted Fediverse server. It works fine for a single user; it scales reasonably to a few hundred active users on a single VPS with attention. This article covers the architecture and the production tuning.

Sizing

  • Solo instance (just you, federation with the broader Fediverse): 2 GB RAM, 2 CPU, 40 GB disk. Disk is the surprise — media caching from federated servers accumulates.
  • Small community (20-100 active users): 4 GB RAM, 4 CPU, 100 GB disk + S3 for media.
  • Larger (500+ active): multiple VPSes or scaling tier — beyond a single-box recipe.

The components

  • Rails web app — serves the UI and API.
  • Streaming server — Node.js, handles WebSocket connections for live updates.
  • Sidekiq workers — background jobs: federation delivery, notifications, scheduled posts.
  • PostgreSQL — primary data store.
  • Redis — queue, cache, rate limits.
  • nginx — reverse proxy + TLS.
  • Object storage — recommended for media attachments at scale.

Install

Mastodon's official docs walk the Ubuntu install in detail. Summarised:

# Dependencies
apt install postgresql redis-server ruby ruby-bundler \
            nodejs yarn nginx imagemagick ffmpeg libpq-dev \
            libxml2-dev libxslt1-dev file git-core \
            g++ libprotobuf-dev protobuf-compiler pkg-config \
            libidn11-dev libicu-dev libjemalloc-dev \
            libgdbm-dev libssl-dev libreadline-dev zlib1g-dev

Then clone Mastodon, configure, run the setup wizard, and register systemd units for web, streaming, and sidekiq.

The wizard generates .env.production with all the secrets. Back this file up — losing it loses signing keys, which breaks federation.

Sidekiq — the actually-important part

Sidekiq runs background jobs. The default config is one process with default concurrency. For a busy instance:

# /etc/systemd/system/mastodon-sidekiq.service
Environment="DB_POOL=25"
ExecStart=/path/to/bundle exec sidekiq -c 25

For larger instances, run multiple sidekiq processes with different queue weightings:

  • default — local actions.
  • push — outbound federation.
  • pull — inbound federation.
  • mailers — email notifications.
# Sidekiq-push.service
ExecStart=... sidekiq -c 20 -q push

# Sidekiq-pull.service
ExecStart=... sidekiq -c 20 -q pull -q default

The "push" queue can back up dramatically when posting to larger followers' federation. Dedicating a process to it prevents user-facing latency.

Object storage for media

Media uploads (images, videos, audio) plus media cached from remote instances will eat disk. Migrate to S3-compatible storage early.

In .env.production:

S3_ENABLED=true
S3_BUCKET=mastodon-media
S3_REGION=us-east-1
S3_ENDPOINT=https://s3.us-west-001.backblazeb2.com
S3_ALIAS_HOST=media.example.com   # public CDN endpoint
AWS_ACCESS_KEY_ID=<b2-key-id>
AWS_SECRET_ACCESS_KEY=<b2-key>

Backblaze B2 is significantly cheaper than AWS S3 for media storage. R2 (Cloudflare) is also competitive with no egress fees.

The S3_ALIAS_HOST is critical — set up a CNAME pointing at the bucket (or use the bucket's S3 endpoint directly). Mastodon uses this URL in posts; you don't want to change it later.

Cleanup tasks

Federation cache grows continuously. Schedule cleanup:

# /etc/cron.daily/mastodon-cleanup
#!/bin/bash
cd /home/mastodon/live
RAILS_ENV=production /home/mastodon/.rbenv/shims/bundle exec tootctl media remove --days=14
RAILS_ENV=production /home/mastodon/.rbenv/shims/bundle exec tootctl preview_cards remove --days=14
RAILS_ENV=production /home/mastodon/.rbenv/shims/bundle exec tootctl statuses remove

14 days is typical. Less aggressive means more storage but faster timeline loads for older posts. Tune to your storage budget.

nginx config notes

  • WebSocket upgrade required for the streaming endpoint (/api/v1/streaming).
  • Large client_max_body_size (40m+) for media uploads.
  • Buffering off on the streaming endpoint.

Mastodon's official nginx config example handles all this — use it.

Federation traffic

A solo instance with follows on a few popular accounts can generate surprising traffic. Inbound federation pulls all the posts from followed servers. Watch:

  • Disk I/O during federation processing (PostgreSQL).
  • Sidekiq queue depth — if pulls are backing up, add sidekiq capacity.
  • Outbound bandwidth — federation delivery to thousands of followers' servers.

Database tuning

  • shared_buffers = 25% of RAM (PostgreSQL default is too small).
  • effective_cache_size = 50-75% of RAM.
  • max_connections = match Sidekiq's needs (50+ usually works).
  • Enable pg_stat_statements for query analysis if you run into slowness.

Backups

  • .env.production — the most critical file. If you lose this, federation signing breaks permanently.
  • PostgreSQL — nightly pg_dumpall.
  • Local media (if not on S3).
  • system_avatars / system_headers — small but irreplaceable.

Common operational issues

  • "Sidekiq is way behind." Add workers and concurrency. Check Redis isn't hitting memory limit.
  • "Federation lags by hours." Push queue is backed up. Dedicate a sidekiq process to it.
  • "Disk filled overnight." Cleanup tasks not running, or run with too-long retention. Lower retention.
  • "Single bad federation peer making instance slow." tootctl can suspend or limit specific instances if they're degrading service.

Also Read

« « Back

Powered by WHMCompleteSolution