Owning your social account is a nice idea until you realise the account lives on someone else's server, under their rules and uptime. Running your own Mastodon instance fixes that: your handle is @you@your-domain, and nobody can shut it down but you. The catch is that Mastodon is not a small app. It's worth knowing what you're signing up for.
Who this is for
- A single-user instance for yourself or your company's official account.
- A small community of friends or a project team — dozens of people, not thousands.
For anything bigger, you're running a service with moderation duties, abuse reports and real infrastructure. That's a different conversation.
What it really needs
Mastodon runs several processes at once: the Rails web app, Sidekiq background workers, a streaming server, PostgreSQL and Redis. Federation means your server keeps fetching posts and media from other servers even when you're asleep.
| Instance | Plan |
|---|---|
| Single user, few follows | Small-IP — 2 vCPU, 4 GB, $16/mo |
| Small community, active federation | Medium-IP — 4 vCPU, 6 GB, $20/mo |
4 GB works but runs tight; Sidekiq queues back up when a popular post you follow gets thousands of replies. 6 GB gives you room to breathe. Disk is the other constraint — see the media section below.
You also need a domain and a dedicated IP: other servers deliver to yours on port 443.
Setup with Docker
The official repository ships a docker-compose.yml. On a fresh Ubuntu 24.04 server with Docker installed:
git clone https://github.com/mastodon/mastodon.git
cd mastodon
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)
touch .env.production
docker compose run --rm -v $(pwd)/.env.production:/opt/mastodon/.env.production \
web bundle exec rake mastodon:setup
docker compose up -d
The setup task asks for your domain, database and Redis settings (the defaults match the compose file), email settings and the first admin account. It writes everything to .env.production. Read the release notes of the tag you checked out — the steps occasionally change between major versions.
Mastodon includes an nginx template at dist/nginx.conf. Copy it to /etc/nginx/sites-available/, replace the domain, and get a certificate with certbot. Our reverse proxy guide and domain guide cover both.
Email: use a relay
Mastodon sends confirmation and password-reset emails. Ports 25 and 465 are closed on our servers, so point Mastodon at an external transactional email provider over port 587:
SMTP_SERVER=smtp.your-provider.example
SMTP_PORT=587
SMTP_LOGIN=apikey
SMTP_PASSWORD=your-smtp-password
SMTP_FROM_ADDRESS=notifications@your-domain.example
Honestly, you'd want a relay anyway. Mail from a brand-new server IP tends to land in spam; a relay has the reputation you don't.
Media: the disk eater
Every image and video from accounts your server sees gets cached locally. On a busy instance that's gigabytes a week. Clean up old remote media on a schedule:
docker compose exec web tootctl media remove --days 7
docker compose exec web tootctl preview_cards remove --days 30
Put those in a daily cron job. If your instance grows, move media to S3-compatible object storage using the S3_* settings in .env.production — then the VPS disk only holds the database.
Upkeep
- Updates: fetch the new tag,
docker compose pull, run migrations as the release notes say, restart. Don't skip major versions. - Backups: dump PostgreSQL and keep
.env.productionsafe — without its secrets, a restore won't work. Our restic guide covers off-site copies, and Managed Backups add daily whole-server restore points. - The domain is permanent. It's baked into every account's address across the fediverse. Pick it before creating the first account.
Want something lighter for a team chat instead? A Matrix server might fit better.
Comments
No comments yet. Be the first.