← Blog

Hospede seu próprio servidor Mastodon

Railyard

1 de setembro de 2026 · 8 min de leitura

Siga isso no seu próprio servidor. Comece grátis, sem cartão

Rodar seu próprio canto do fediverso significa rodar cinco coisas que precisam estar de acordo entre si: um processo web Rails, um servidor de streaming separado para a timeline em tempo real, um worker Sidekiq para federação e notificações, Postgres e Redis. Erre o domínio em qualquer uma delas e você tem uma instância que carrega pela metade ou para de federar em silêncio. No final deste guia, você vai ter uma instância Mastodon de verdade, num único servidor, rodando as cinco, atrás de HTTPS, com backups e uma visão honesta do que de fato custa para rodar bem.

O que você vai precisar

  • Um servidor com pelo menos 4 vCPUs e 8 GB de RAM para uma instância pequena; este guia usa os cinco serviços numa única máquina, o que é mais do que o processo web por si só precisa. Um Hetzner CX33 (4 vCPUs, 8 GB de RAM, 80 GB NVMe, €8,99/mês sem VAT) é o ponto de partida realista quando o Postgres, o Redis, o servidor de streaming e o Sidekiq estão todos competindo por recursos na mesma máquina; crescer além de algumas centenas de usuários ativos é quando separar o Postgres num servidor próprio começa a importar.
  • Um domínio no qual você possa apontar um registro A. O Mastodon amarra os identificadores de conta a esse domínio para sempre; não existe um jeito suportado de mover uma instância existente para um novo domínio depois sem começar do zero.
  • Um provedor de SMTP. Isso não é opcional: o Mastodon exige entrega de e-mail funcionando para confirmação de conta, redefinição de senha e avisos de moderação, e não vem com nenhum configurado por padrão. Qualquer provedor de e-mail transacional funciona.
  • Acesso SSH ao servidor.

Etapa 1: Aponte o DNS e abra o firewall

ufw allow OpenSSH
ufw allow 80
ufw allow 443
ufw --force enable

Crie um registro A para o seu domínio apontando para o IP público do servidor. Dê tempo para propagar antes da Etapa 6.

Etapa 2: Gere todos os segredos de antemão

O Mastodon precisa de seis valores secretos distintos antes de conseguir iniciar: uma secret key base do Rails, chaves VAPID para notificações push, e três chaves de criptografia do Active Record. Cada uma tem seu próprio comando gerador, rodado através da própria imagem depois de baixada:

mkdir -p /opt/mastodon && cd /opt/mastodon
docker pull ghcr.io/mastodon/mastodon:v4.7.3
docker run --rm ghcr.io/mastodon/mastodon:v4.7.3 bundle exec rails secret
docker run --rm ghcr.io/mastodon/mastodon:v4.7.3 bundle exec rake mastodon:webpush:generate_vapid_key
docker run --rm ghcr.io/mastodon/mastodon:v4.7.3 bundle exec rake db:encryption:init

O primeiro comando imprime SECRET_KEY_BASE. O segundo imprime um par VAPID_PRIVATE_KEY e VAPID_PUBLIC_KEY. O terceiro imprime os três valores ACTIVE_RECORD_ENCRYPTION_* de uma vez. Salve todos eles:

cat > .env <<'EOF'
POSTGRES_PASSWORD=generate-with-openssl-rand-hex-24
REDIS_PASSWORD=generate-with-openssl-rand-hex-24
SECRET_KEY_BASE=paste-from-rails-secret
VAPID_PRIVATE_KEY=paste-from-generate-vapid-key
VAPID_PUBLIC_KEY=paste-from-generate-vapid-key
AR_ENCRYPTION_PRIMARY_KEY=paste-from-db-encryption-init
AR_ENCRYPTION_DETERMINISTIC_KEY=paste-from-db-encryption-init
AR_ENCRYPTION_KEY_DERIVATION_SALT=paste-from-db-encryption-init
SMTP_SERVER=smtp.your-provider.com
SMTP_LOGIN=your-smtp-username
SMTP_PASSWORD=your-smtp-password
EOF
chmod 600 .env

Etapa 3: Escreva o arquivo Compose

services:
  mastodon:
    image: ghcr.io/mastodon/mastodon:v4.7.3
    restart: unless-stopped
    command: bash -c "bundle exec rails db:prepare && bundle exec puma -C config/puma.rb"
    env_file: .env
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    environment:
      LOCAL_DOMAIN: social.yourdomain.com
      DB_HOST: db
      DB_PORT: "5432"
      DB_NAME: mastodon
      DB_USER: mastodon
      DB_PASS: ${POSTGRES_PASSWORD}
      REDIS_HOST: redis
      REDIS_PORT: "6379"
      REDIS_PASSWORD: ${REDIS_PASSWORD}
      STREAMING_API_BASE_URL: wss://social.yourdomain.com
      SMTP_FROM_ADDRESS: notifications@yourdomain.com
    volumes:
      - mastodon_system:/mastodon/public/system
    expose:
      - "3000"

  streaming:
    image: ghcr.io/mastodon/mastodon-streaming:v4.7.3
    restart: unless-stopped
    command: node ./streaming/index.js
    env_file: .env
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    environment:
      PORT: "4000"
      LOCAL_DOMAIN: social.yourdomain.com
      DB_HOST: db
      DB_PORT: "5432"
      DB_NAME: mastodon
      DB_USER: mastodon
      DB_PASS: ${POSTGRES_PASSWORD}
      REDIS_HOST: redis
      REDIS_PORT: "6379"
      REDIS_PASSWORD: ${REDIS_PASSWORD}
    expose:
      - "4000"

  sidekiq:
    image: ghcr.io/mastodon/mastodon:v4.7.3
    restart: unless-stopped
    command: bundle exec sidekiq
    env_file: .env
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    environment:
      LOCAL_DOMAIN: social.yourdomain.com
      DB_HOST: db
      DB_PORT: "5432"
      DB_NAME: mastodon
      DB_USER: mastodon
      DB_PASS: ${POSTGRES_PASSWORD}
      REDIS_HOST: redis
      REDIS_PORT: "6379"
      REDIS_PASSWORD: ${REDIS_PASSWORD}
      SMTP_FROM_ADDRESS: notifications@yourdomain.com
    volumes:
      - mastodon_system:/mastodon/public/system

  db:
    image: postgres:16.4-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: mastodon
      POSTGRES_DB: mastodon
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - mastodon_db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mastodon"]
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7.2.5-alpine
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}
    env_file: .env
    volumes:
      - mastodon_redis_data:/data

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - mastodon
      - streaming

volumes:
  mastodon_system:
  mastodon_db_data:
  mastodon_redis_data:
  caddy_data:
  caddy_config:

Este guia fixa a v4.7.3 nas três imagens do Mastodon, a release estável atual no momento em que isso foi escrito. O comando do serviço mastodon roda rails db:prepare antes do Puma iniciar, o mesmo padrão que apps Rails usam em geral, então a configuração do schema acontece automaticamente no primeiro boot e em cada upgrade posterior. O streaming é de fato um processo Node.js separado, não uma thread dentro do app Rails, e é por isso que ele tem a própria imagem e o próprio STREAMING_API_BASE_URL apontado a partir do serviço principal. mastodon_system é um volume compartilhado entre mastodon e sidekiq especificamente, já que o Sidekiq é quem de fato processa os uploads de mídia em segundo plano; os dois precisam ver os mesmos arquivos.

Confira se o arquivo é interpretado corretamente:

docker compose config

Etapa 4: Adicione o Caddy, incluindo o caminho de streaming

social.yourdomain.com {
	@streaming path /api/v1/streaming*
	reverse_proxy @streaming streaming:4000

	reverse_proxy mastodon:3000
}

O cliente web do Mastodon chama /api/v1/streaming para a timeline em tempo real, que precisa chegar ao serviço streaming separado, não ao processo Rails principal; tudo o resto vai para mastodon:3000. Valide se o Caddyfile está correto antes de depender dele:

docker run --rm -v "$PWD/Caddyfile:/etc/caddy/Caddyfile" caddy:2 caddy validate --config /etc/caddy/Caddyfile

Etapa 5: Inicie a stack e crie uma conta de admin

docker compose up -d
docker compose ps
curl -I https://social.yourdomain.com

Você deve ver todos os serviços Up (db como healthy) e o curl retornando HTTP/2 200. Crie a primeira conta pela linha de comando, com privilégios de administrador:

docker compose exec mastodon bin/tootctl accounts create admin \
  --email admin@yourdomain.com --confirmed --role Owner

Isso imprime uma senha gerada; faça login com ela e troque imediatamente pela UI web.

Etapa 6: Faça backup do Postgres e do volume de mídia

cat > /opt/mastodon/backup.sh <<'EOF'
#!/bin/sh
cd /opt/mastodon
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
docker compose exec -T db pg_dump -U mastodon mastodon | gzip > backups/db-$TIMESTAMP.sql.gz
find backups -mtime +14 -delete
EOF
mkdir -p /opt/mastodon/backups
chmod +x /opt/mastodon/backup.sh
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/mastodon/backup.sh") | crontab -

O volume mastodon_system guarda todo anexo de mídia enviado e cresce sem limite conforme as pessoas postam; faça backup dele separadamente com qualquer ferramenta de snapshot de disco ou de volume que o seu provedor de servidor ofereça, um pg_dump sozinho não cobre isso. Rode o script uma vez à mão e confira que ls -lh backups mostra o arquivo de hoje.

Etapa 7: Faça upgrade

docker compose pull
docker compose up -d

O db:prepare no comando do serviço mastodon roda de novo em cada restart, aplicando qualquer migração que tenha vindo com a nova versão. Leia as release notes do próprio Mastodon antes de um salto de várias versões; o projeto ocasionalmente indica uma versão intermediária obrigatória para mudanças maiores de schema.

O caminho curto: faça com o Railyard

Tudo isso acima, Postgres e Redis ligados aos três processos baseados em Rails, o serviço de streaming separado com seu próprio roteamento, o Sidekiq compartilhando o volume de mídia, é também o que o template de stack do Mastodon no Railyard configura para você. Conecte um servidor e escolha Mastodon no catálogo de templates: app.railyard.run/deploy?stack=mastodon-stack. O Railyard gera cada segredo da Etapa 2 para você e liga automaticamente as URLs do banco de dados, do Redis e do streaming; você ainda adiciona seu próprio provedor de SMTP depois, da mesma forma que na Etapa 2 acima, o Railyard também não configura um para você, e a mídia enviada ainda usa por padrão um volume local compartilhado a menos que você aponte para object storage por conta própria.

Veja deploy with a button e databases and backups para entender como templates e dados persistentes funcionam na plataforma de forma mais geral.

Solução de problemas

A timeline em tempo real nunca atualiza, mas postar e navegar funcionam normalmente. O Caddyfile não está roteando /api/v1/streaming para o serviço streaming; confira a correspondência de caminho na Etapa 4 contra o que a aba de rede do seu navegador de fato requisita.

Nenhum e-mail de confirmação chega para um novo cadastro. O SMTP não está configurado ou as credenciais estão erradas; confira docker compose logs mastodon em busca de um erro de SMTP no momento em que o cadastro foi tentado. Não há como contornar essa exigência, o Mastodon não confirma uma conta sem isso.

O Sidekiq fica atrasado, posts de outras instâncias chegam tarde. Confira docker compose logs sidekiq em busca de falhas repetidas de job ou um restart por falta de memória; num CX33, isso geralmente é disputa de recursos com o Postgres e o processo web durante um pico de tráfego, que é o ponto em que separar o Postgres num servidor próprio começa a se pagar.

O HTTPS não é emitido. docker compose logs caddy mostrando erros repetidos de ACME quase sempre significa que o registro de DNS da Etapa 1 não propagou ainda ou aponta para o IP errado.

O disco enchendo por causa do volume de mídia. O Mastodon armazena em cache localmente, por padrão, a mídia remota (imagens e vídeos de outras instâncias); tootctl media remove --days 30 de dentro do container mastodon limpa a mídia remota em cache mais antiga que uma janela dada, sem tocar nos posts dos seus próprios usuários.

Perguntas frequentes

Posso trocar o domínio da minha instância depois? Não, os identificadores de conta estão amarrados ao domínio para sempre; isso é uma restrição de todo o fediverso, não algo que a própria configuração do Mastodon consiga contornar, decida o domínio real antes de convidar qualquer pessoa.

Eu realmente preciso de 8 GB de RAM para uma instância pequena com um punhado de usuários? O mínimo é mais baixo, mas depois que o Postgres, o Redis, o servidor de streaming e o Sidekiq rodam todos numa única máquina, 8 GB é o ponto em que as coisas deixam de ficar apertadas; um CX23 com 4 GB tecnicamente inicia essa stack, mas sobra muito pouca margem para picos de tráfego ou tempestades de federação.

Qual é a diferença entre isso e entrar numa instância Mastodon já existente? Rodar a sua própria te dá sua própria política de moderação, seu próprio domínio e controle total sobre retenção de dados; entrar numa instância existente troca esse controle por zero trabalho operacional.

O object storage pode substituir o volume de mídia local? Sim, o Mastodon suporta armazenamento compatível com S3 para mídia através da própria configuração; este guia mantém local para uma primeira configuração direta, vale revisitar depois que o volume de mídia se tornar o principal consumidor de disco.

A federação alguma vez vem desligada por padrão? Não, uma instância nova federa com a rede mais ampla assim que estiver acessível via HTTPS; existe um modo de allowlist separado se você quiser uma instância fechada, não coberto aqui.

Uma instância Mastodon rodando corretamente é cinco serviços de acordo sobre um domínio e um conjunto de credenciais, não uma coisa complicada só. Depois que o DNS, a rota de streaming e o SMTP estiverem certos, o trabalho contínuo é backup, o upgrade ocasional de versão e ficar de olho no Sidekiq sob tráfego real.

Por que escolhem o Railyard para isso

  • Sua própria conta de cloud. Faça deploy no DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, ou em qualquer servidor Linux via SSH, cobrado direto pelo seu provedor, sem markup.
  • Um preço fixo por equipe. O Free é grátis para sempre: um servidor mais um servidor de banco de dados, três apps, sem cartão. O Pro custa US$19 por mês para até cinco servidores e apps ilimitados. O Team custa US$49 por mês com servidores ilimitados. Sem cobrança por app, por deploy, por assento ou por gigabyte.
  • Templates de um clique. Faça deploy de apps open source, como bancos de dados, analytics e ferramentas de dev, no seu próprio servidor em um clique.
  • Bancos de dados gerenciados. Postgres, MySQL e Redis com backups programados, verificados por restauração, e recuperação point-in-time.
  • Push-to-deploy. Faça deploy a partir do GitHub, GitLab ou da CLI, com HTTPS automático e releases sem downtime.

Suba o Mastodon com um clique

Escolha Mastodon no catálogo de templates do Railyard e já tenha os processos web, streaming e Sidekiq ligados.

Plano grátis, sem cartão, e 14 dias de Pro para cada equipe nova. Um preço fixo por equipe.