Skip to content

Self-host Mastodon

updated Sep 2026prices checked · Jul 2026
We earn commissions when you shop through the links below. Full disclosure →

A decentralized microblogging server built on ActivityPub. Each server runs its own community and federates with other Mastodon and Fediverse servers.

Key facts

LicenseAGPL-3.0
StackRuby, Rails, Node.js, PostgreSQL, Redis
Min RAM2048 MB
Official imageyes
Difficulty

What you need

  • Any VPS with at least 2048 MB of RAM
  • A domain you control — most self-hosted setups need HTTPS in front of them
  • About an afternoon — budget time for troubleshooting
Where to host itaffiliate disclosure
Hetzner Cloudrun it on
From $23.59/mo · 2 vCPU / 4 GB / 80 GB · EU + US
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
From $4/mo · 1 vCPU / 1 GB / 20 GB · US + EU + Asia
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
From $6/mo · 1 vCPU / 1 GB / 25 GB · US + EU + Asia
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install

Run these commands on your server:

# Mastodon — the repo's docker-compose.yml (web + streaming + sidekiq + PostgreSQL + Redis), pinned to the release
mkdir mastodon && cd mastodon
wget https://raw.githubusercontent.com/mastodon/mastodon/v4.7.2/docker-compose.yml
mkdir -p public/system && sudo chown -R 991:991 public/system
# LOCAL_DOMAIN is permanent: it is the domain in every handle (@you@social.example.com)
cat > .env.production << EOF
LOCAL_DOMAIN=social.example.com
REDIS_HOST=redis
DB_HOST=db
DB_USER=postgres
DB_NAME=mastodon_production
SECRET_KEY_BASE=$(openssl rand -hex 64)
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=$(openssl rand -hex 32)
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=$(openssl rand -hex 32)
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=$(openssl rand -hex 32)
EOF
docker compose run --rm web bundle exec rails mastodon:webpush:generate_vapid_key >> .env.production
docker compose up -d db redis && sleep 15
docker compose run --rm web bundle exec rails db:setup
docker compose up -d
# web listens on 127.0.0.1:3000 and forces HTTPS: put nginx/Caddy with a TLS cert for LOCAL_DOMAIN in front

Head-to-head

More self-hosted tools

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.