Свой Mastodon: инстанс на одного и модерация, которой вы не ждали
«Хочу свою альтернативу Twitter, только без рекламы и с полным контролем» — с этой мысли обычно начинается разговор про собственный инстанс Mastodon. И на первый взгляд всё выглядит как обычный self-hosted проект: скачал docker-compose, поднял, вбил домен, готово. На практике вы разворачиваете не блог-движок, а узел федеративной сети — со своей базой данных, очередями фоновых задач и, что удивляет почти всех, модерационной нагрузкой, которая начинается в день установки независимо от того, открыта у вас регистрация или нет. Разберём честно, что стоит за словом «instance», сколько инфраструктуры прячется за одной лентой и когда игра действительно стоит свеч.
Содержание
- Что вы получаете, а что перестаёте получать
- Инфраструктура: сколько сервисов скрывается за одной лентой
- Модерация, которую вы не выбирали: федерация не спрашивает разрешения
- Хранилище: как растут медиа даже у одного пользователя
- Sidekiq-очереди: что будет, если сервер не успевает
- Когда свой инстанс оправдан, а когда лучше присоединиться к существующему
Что вы получаете, а что перестаёте получать
Плюсы собственного инстанса реальны, и их стоит назвать прямо:
- Идентичность вида
@vy@vash-domen.ru— она принадлежит вам, а не платформе. Если крупный инстанс завтра сменит владельца или отключится, ваш аккаунт не исчезает вместе с ним. - Свои правила модерации. Никто не решает за вас, что можно постить и кого банить.
- Контроль над федерацией. Вы сами решаете, с какими инстансами дружить, какие ограничивать (silence), а какие блокировать полностью (suspend/defederate).
- Отсутствие алгоритмической ленты и рекламы — лента строго хронологическая, показывает то, на что вы подписаны.
Но вместе с этим вы забираете себе и то, что раньше делал за вас крупный инстанс незаметно:
- Патчи безопасности и обновления Rails-приложения — накатывать нужно самому и не откладывая: Mastodon принимает трафик от тысяч чужих серверов.
- Бэкапы базы данных и медиатеки — без них потеря сервера означает потерю не только постов, но и истории подписок.
- Ответственность за контент, физически лежащий на вашем диске — включая то, что вы не публиковали сами (об этом ниже).
- Модерационную очередь — да, даже у инстанса на одного человека.
«Инстанс на одного» (single-user instance) — легитимная и популярная практика именно ради контроля над идентичностью и правилами. Но она не освобождает от инфраструктурной и модерационной работы ниже — просто эта работа ложится на одного человека без команды, которая обычно есть у публичных инстансов.
Инфраструктура: сколько сервисов скрывается за одной лентой
Официальный образ Mastodon — это не один контейнер, а связка из нескольких сервисов, каждый со своей ролью:
| Компонент | Роль |
|---|---|
| PostgreSQL | Основная база: аккаунты, посты, подписки, уведомления, статусы федерации |
| Redis | Кэш, очередь заданий для Sidekiq, pub/sub для live-обновлений через ActionCable |
| Sidekiq | Фоновый воркер на Ruby: доставка и приём федеративных сообщений, рассылка писем, обработка медиа, плановые задачи |
| Puma (web) | Rails-приложение — отдаёт веб-интерфейс и REST/Streaming API |
| Streaming | Отдельный процесс для WebSocket-обновлений ленты в реальном времени |
| nginx | Обратный прокси, TLS-терминация, лимиты на размер загружаемых файлов, кэш статики |
| Хранилище медиа | Локальный диск по умолчанию либо S3-совместимое хранилище |
| Elasticsearch/OpenSearch (опционально) | Полнотекстовый поиск по чужим постам — без него поиск ограничен вашими постами и точным совпадением тегов |
Даже минимальный self-hosted docker-compose для персонального инстанса — это не «один сервис», а минимум пять контейнеров, которые должны договориться друг с другом:
services:
db:
image: postgres:16-alpine
restart: always
volumes:
- ./postgres:/var/lib/postgresql/data
environment:
POSTGRES_DB: mastodon
POSTGRES_USER: mastodon
redis:
image: redis:7-alpine
restart: always
volumes:
- ./redis:/data
web:
image: tootsuite/mastodon:latest
restart: always
env_file: .env.production
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
depends_on: [db, redis]
volumes:
- ./public/system:/mastodon/public/system
streaming:
image: tootsuite/mastodon:latest
restart: always
env_file: .env.production
command: node ./streaming/index.js
depends_on: [db, redis]
sidekiq:
image: tootsuite/mastodon:latest
restart: always
env_file: .env.production
command: bundle exec sidekiq
depends_on: [db, redis]
volumes:
- ./public/system:/mastodon/public/system
Обратите внимание: web, streaming и sidekiq — один и тот же образ, запущенный в трёх разных ролях. «Поднять Mastodon» с точки зрения ресурсов сервера — значит поднять три отдельных Ruby/Node-процесса плюс СУБД плюс Redis одновременно, а не по очереди. nginx перед этим стеком обязателен, а не опция: без client_max_body_size под видео и вложения и без правильного проксирования WebSocket на streaming-сервис лента у пользователей просто не обновляется в реальном времени.
server {
listen 443 ssl http2;
server_name mastodon.example.com;
client_max_body_size 99M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/v1/streaming {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 7d;
}
}
Подробный разбор настройки nginx как обратного прокси со всеми заголовками и таймаутами — в статье про nginx как reverse proxy. PostgreSQL и Redis для Mastodon разворачиваются так же, как для любого Rails-приложения — базовая установка описана в статье про PostgreSQL на Ubuntu 24.04 и в статье про установку Redis на VPS, разница только в параметрах подключения из .env.production.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть Mastodon на VPSМодерация, которую вы не выбирали: федерация не спрашивает разрешения
Вот главное, о чём не пишут в текстах про «свою альтернативу Twitter»: закрытая регистрация останавливает только один канал нагрузки — локальные спам-аккаунты. Всё остальное приходит независимо от того, кто может у вас зарегистрироваться.
Как именно это работает:
- Вы подписываетесь на кого-то с другого инстанса — и их посты, репосты, ответы и медиавложения начинают приходить на ваш сервер через ActivityPub и складываться в вашу базу и на диск, независимо от числа ваших пользователей.
- Кто угодно с любого инстанса может упомянуть или ответить вашему пользователю — это входящий федеративный трафик, который сервер обязан принять и обработать.
- Жалобы (Flag-активности) на контент, видимый на вашем инстансе, приходят в вашу очередь модерации — даже если автор поста зарегистрирован в другом месте: копия объекта у вас в базе, и репорт адресован именно вашему серверу.
- Медиавложения из чужих постов физически кэшируются на диске — аватары, обложки, картинки и видео всех, на кого вы подписаны или чьи посты попали в ленту через буст. Ответственность за то, что лежит в
public/system, — ваша, даже если контент создан не вами.
Практический вывод: даже инстанс на одного человека с закрытой регистрацией нуждается в ком-то, кто время от времени открывает /admin/reports и решает, что делать с жалобой на пост третьего инстанса, о существовании которого вы вчера не подозревали. В одиночку это не критично при небольшом числе подписок, но это принципиально другая модель нагрузки, чем «поставил и забыл».
Отдельная задача — списки блокировки доменов (domain blocks). Готового провалидированного списка «спам-инстансов» Mastodon из коробки не поставляет — сообщество ведёт открытые списки (например, курируемые проектами вроде IFTAS), и их нужно самостоятельно импортировать через admin/instances или tootctl domains. Без этого шага на маленький инстанс натекает спам, который крупные инстансы давно отфильтровали себе.
Хранилище: как растут медиа даже у одного пользователя
Самая частая неожиданность после первых недель работы: диск заполняется, хотя вы сами почти ничего не публиковали. Причина — тот же механизм кэширования из предыдущего раздела: каждый аватар, обложка профиля, картинка в посте и превью ссылки у каждого аккаунта, на который вы подписаны, скачивается на ваш сервер и хранится локально.
Проверить, сколько места это занимает:
RAILS_ENV=production bin/tootctl media usage
Очистить кэш удалённых медиа старше определённого срока (при следующем обращении Mastodon перекачает их заново по требованию):
RAILS_ENV=production bin/tootctl media remove --days=30
RAILS_ENV=production bin/tootctl media remove-orphans
RAILS_ENV=production bin/tootctl accounts cull
Эти команды стоит вынести в cron — вручную про них вспоминают обычно уже после того, как диск закончился:
0 4 * * * cd /home/mastodon/live && RAILS_ENV=production bin/tootctl media remove --days=30 >> /var/log/mastodon-media-cleanup.log 2>&1
Если инстанс планируется не как разовый эксперимент, а как постоянная точка присутствия, разумнее с самого начала вынести медиахранилище на S3-совместимое хранилище, а не на локальный диск сервера — это снимает вопрос «докупать диск» и упрощает перенос инстанса на другой сервер в будущем. В .env.production это выглядит так:
S3_ENABLED=true
S3_BUCKET=mastodon-media
S3_REGION=us-east-1
S3_ENDPOINT=https://s3.example.com
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
S3_ALIAS_HOST=media.mastodon.example.com
Разворачивать своё S3-совместимое хранилище под такие задачи мы разбирали в статье про S3-совместимое хранилище у себя — тот же подход применим и к медиатеке Mastodon.
Sidekiq-очереди: что будет, если сервер не успевает
Всё взаимодействие с федерацией — отправка ваших постов подписчикам на других инстансах, приём входящих постов, рассылка уведомлений, генерация превью — проходит через фоновые задачи Sidekiq, разложенные по нескольким очередям: default, push (исходящая доставка), pull (входящие обновления и поиск профилей), mailers, scheduler, ingress (приём входящей федерации).
Конфигурация конкурентности задаётся в config/sidekiq.yml:
:concurrency: 25
:queues:
- [ingress, 8]
- [push, 6]
- [pull, 4]
- [default, 4]
- [mailers, 2]
- [scheduler, 2]
Если очередь ingress недоукомплектована воркерами относительно входящего потока, происходит не «сайт тормозит» в привычном понимании, а более тонкая проблема: удалённые инстансы, пытающиеся доставить вам сообщение, получают таймауты и уходят в повторные попытки по экспоненциальной задержке. Со стороны ваш сервер в этот момент выглядит нестабильным узлом федерации, и некоторые крупные инстансы автоматически понижают приоритет таких узлов.
Диагностировать отставание можно через встроенный веб-интерфейс Sidekiq (обычно смонтированный на /sidekiq) — там видна глубина каждой очереди и число повторных попыток. Растущая глубина очереди push/pull без роста числа пользователей — признак нехватки выделенных ядер CPU, а не проблема конфигурации как таковой.
Точную цифру по RAM и CPU для персонального инстанса честно назвать нельзя — она зависит не от числа ваших пользователей, а от числа аккаунтов, на которые вы подписаны, и от активности тех инстансов, с которыми вы федеритесь (это определяет объём фан-аута). Ориентируйтесь на то, что стек Postgres + Redis + Puma + Sidekiq + streaming требует заметно больше ресурсов, чем статический сайт той же посещаемости, и закладывайте запас сверх минимальных требований из документации — обработка медиа (превью, перекодирование видео через ffmpeg) даёт заметные пики нагрузки на CPU.
Когда свой инстанс оправдан, а когда лучше присоединиться к существующему
Свой инстанс имеет смысл, если для вас важно хотя бы одно из следующего:
- Идентичность на собственном домене, не зависящая от политики чужого администратора.
- Полный контроль над правилами модерации и списком заблокированных доменов под ваши задачи.
- Интеграция с другими self-hosted сервисами (публикация из CI/CD, ботов, уведомлений).
- Интерес к инфраструктуре как таковой — рабочий способ разобраться в Rails, ActivityPub и очередях на практике.
Присоединиться к существующему инстансу разумнее, если:
- Вы не готовы дежурить по обновлениям безопасности и очередям Sidekiq на постоянной основе.
- Вам важна модерационная команда, уже поддерживающая блок-листы и разбирающая репорты — в одиночку это всё на вас.
- Сетевой эффект важнее контроля: на активном инстансе выше шанс, что вас увидят.
- Доступность аккаунта не должна зависеть от того, продлили ли вы вовремя домен или сертификат.
Отдельно стоит развести Mastodon и другое федеративное ПО, которое путают именно из-за общего слова «fediverse». Mastodon — лента коротких постов, аналог Twitter/X: подписки, буст, лайк, хронологическая лента. Lemmy — форум-агрегатор ссылок с обсуждениями, аналог Reddit: сообщества, посты с комментариями, голосование. Оба протокола (ActivityPub) роднит федерация и, как следствие, схожая инфраструктурная и модерационная нагрузка — входящие репорты, кэш чужого контента, свои блок-листы. Но модель контента разная: в Mastodon вы модерируете ленту и упоминания, в Lemmy — сообщества и ветки обсуждений. Выбирая между ними, стоит для начала определить, нужна ли вам лента коротких сообщений или форум с обсуждениями — это разные продукты с общим только транспортным протоколом.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть Mastodon на VPSНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Нужен ли Elasticsearch для маленького личного инстанса?
Не обязательно. Базовый поиск по вашим собственным постам и точным совпадениям хештегов работает и без него. Elasticsearch/OpenSearch добавляет полнотекстовый поиск по чужим постам в вашей ленте — для инстанса на 1-5 человек это часто избыточно на старте, можно подключить позже.
Останавливает ли закрытая регистрация модерационную нагрузку?
Частично. Она останавливает локальные спам-регистрации, но не останавливает входящие жалобы на федеративный контент и не останавливает кэширование чужих медиа на вашем диске — этот трафик идёт независимо от настроек регистрации.
Можно ли ограничить федерацию только доверенными инстансами?
Да, в Mastodon есть режим ограниченной федерации (allow-list вместо блок-листа) — данные идут только с явно разрешёнными доменами. Это снимает часть неожиданной нагрузки, но превращает публичную сеть в частную и лишает смысла часть преимуществ федерации.
Сколько ресурсов сервера реально нужно для инстанса на 1-3 человека?
Точную цифру честно назвать нельзя — она зависит от числа аккаунтов, на которые вы подписаны, а не от числа локальных пользователей. Закладывайте запас сверх минимальных требований из документации, особенно по CPU.
Чем это отличается от Lemmy, если оба — fediverse?
Mastodon — лента коротких постов, аналог Twitter/X. Lemmy — форум-агрегатор ссылок с обсуждениями, аналог Reddit. Общая федерация через ActivityPub даёт похожий профиль нагрузки, но модель контента разная.
Можно ли позже перенести инстанс на другой сервер?
Да, перенос базы PostgreSQL, Redis и медиахранилища технически несложен и обычно описан в официальной документации проекта. Но идентичность аккаунтов жёстко привязана к домену — смена домена ломает существующие подписки федерации, поэтому домен стоит выбирать один раз и надолго.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →