Установка Mastodon на Rocky Linux 9 с Docker
Введение

Mastodon — бесплатная, децентрализованная и с открытым исходным кодом социальная сеть. Она была создана как альтернатива Twitter. Как и в Twitter, пользователи могут подписываться друг на друга и публиковать сообщения, изображения и видео. В отличие от централизованных сервисов, контент в Mastodon распределён по тысячам серверов (инстансов), которыми управляют разные люди и организации.
Пользователи, зарегистрированные на одном сервере, могут подписываться и взаимодействовать с пользователями на других серверах благодаря федерации (ActivityPub).
Любой может установить собственный инстанс Mastodon. В этом руководстве показано, как развернуть инстанс Mastodon на сервере с Rocky Linux 9 с помощью Docker. Docker упрощает установку, помещая все зависимости в контейнеры.
Важно: краткие определения
- Docker: платформа для запуска приложений в контейнерах.
- Инстанс: отдельный сервер Mastodon, работающий со своим доменом и базой данных.
Кому это подходит
- Тем, кто хочет сам хостить социальный инстанс.
- Тем, кто знаком с Linux, системным администрированием и Docker.
Требования
- Сервер с Rocky Linux 9, минимум 2 CPU и 2 ГБ оперативной памяти (рекомендуется больше для реальной нагрузки).
- Ненулевой пользователь с правами sudo.
- Полное доменное имя (FQDN) с A/AAAA-записью на ваш сервер (в примерах используется mastodon.example.com).
- Почтовый сервис для рассылки уведомлений (рекомендуются Mailgun, SendGrid, Amazon SES или SparkPost). В этом руководстве используется Amazon SES в примерах.
Подготовьте систему и установите базовые утилиты:
$ sudo dnf update$ sudo dnf install wget curl nano unzip yum-utils -yШаг 1 — Настройка брандмауэра
Rocky Linux использует firewalld. Проверьте статус:
$ sudo firewall-cmd --state
runningСписок текущих сервисов в зоне public:
$ sudo firewall-cmd --permanent --list-servicesОткройте HTTP и HTTPS:
$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=httpsMastodon общается с внешними инстансами, поэтому разрешите masquerade:
$ sudo firewall-cmd --permanent --add-masqueradeПримените изменения:
$ sudo firewall-cmd --reloadВажно: если вы используете нестандартные зоны firewalld, используйте соответствующую зону вместо public.
Шаг 2 — Установка Docker и Docker Compose
Rocky Linux может включать старую версию Docker. Подключите официальный репозиторий Docker:
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repoУстановите Docker:
$ sudo dnf install docker-ce docker-ce-cli containerd.ioЕсли при установке возникнет конфликт с runc/containerd, используйте опцию –allowerasing:
$ sudo dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin --allowerasingВключите и запустите демон Docker:
$ sudo systemctl enable docker --nowПроверьте статус:
$ sudo systemctl status dockerЧтобы не вводить sudo при каждой команде docker, добавьте пользователя в группу docker:
$ sudo usermod -aG docker $(whoami)
$ su - ${USER}
$ groupsШаг 3 — Подготовка системы к установке
Elasticsearch требует большего лимита mmap. Проверьте текущий предел:
$ sysctl vm.max_map_count
vm.max_map_count = 65530Увеличьте предел:
$ echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/90-max_map_count.conf
$ sudo sysctl --load /etc/sysctl.d/90-max_map_count.confНастройте SELinux, чтобы разрешить сетевые подключения из веб-процесса:
$ sudo setsebool -P httpd_can_network_connect 1Примечание: если вы используете отключённый SELinux, убедитесь, что это безопасно в вашей среде.
Шаг 4 — Установка Mastodon
Создание директорий и прав владения
Создайте каталоги для Mastodon и сервисов:
$ sudo mkdir -p /opt/mastodon/database/{postgresql,pgbackups,redis,elasticsearch}
$ sudo mkdir -p /opt/mastodon/web/{public,system}
$ sudo mkdir -p /opt/mastodon/brandingУстановите владельцев для нужных директорий. UID/GID в примерах соответствуют рекомендациям образов контейнеров:
$ sudo chown 991:991 /opt/mastodon/web/{public,system}
$ sudo chown 1000 /opt/mastodon/database/elasticsearch
$ sudo chown 70:70 /opt/mastodon/database/pgbackupsПерейдите в рабочую директорию:
$ cd /opt/mastodonФайлы окружения и Docker Compose
Создайте файлы окружения:
$ sudo touch application.env database.envСоздайте docker-compose.yml:
$ sudo nano docker-compose.ymlВставьте содержимое docker-compose, как показано ниже (осторожно: большой блок). Сохраните Ctrl+X, Y.
version: '3'
services:
postgresql:
image: postgres:15-alpine
env_file: database.env
restart: always
shm_size: 512mb
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'postgres']
volumes:
- postgresql:/var/lib/postgresql/data
- pgbackups:/backups
networks:
- internal_network
redis:
image: redis:7-alpine
restart: always
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
volumes:
- redis:/data
networks:
- internal_network
redis-volatile:
image: redis:7-alpine
restart: always
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
networks:
- internal_network
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.7
restart: always
env_file: database.env
environment:
- cluster.name=elasticsearch-mastodon
- discovery.type=single-node
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- ingest.geoip.downloader.enabled=false
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test: ["CMD-SHELL", "nc -z elasticsearch 9200"]
volumes:
- elasticsearch:/usr/share/elasticsearch/data
networks:
- internal_network
website:
image: tootsuite/mastodon:v4.0.2
env_file:
- application.env
- database.env
command: bash -c "bundle exec rails s -p 3000"
restart: always
depends_on:
- postgresql
- redis
- redis-volatile
- elasticsearch
ports:
- '127.0.0.1:3000:3000'
networks:
- internal_network
- external_network
healthcheck:
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
volumes:
- uploads:/mastodon/public/system
shell:
image: tootsuite/mastodon:v4.0.2
env_file:
- application.env
- database.env
command: /bin/bash
restart: "no"
networks:
- internal_network
- external_network
volumes:
- uploads:/mastodon/public/system
- static:/static
streaming:
image: tootsuite/mastodon:v4.0.2
env_file:
- application.env
- database.env
command: node ./streaming
restart: always
depends_on:
- postgresql
- redis
- redis-volatile
- elasticsearch
ports:
- '127.0.0.1:4000:4000'
networks:
- internal_network
- external_network
healthcheck:
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
sidekiq:
image: tootsuite/mastodon:v4.0.2
env_file:
- application.env
- database.env
command: bundle exec sidekiq
restart: always
depends_on:
- postgresql
- redis
- redis-volatile
- website
networks:
- internal_network
- external_network
healthcheck:
test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]
volumes:
- uploads:/mastodon/public/system
networks:
external_network:
internal_network:
#internal:true
volumes:
postgresql:
driver_opts:
type: none
device: /opt/mastodon/database/postgresql
o: bind
pgbackups:
driver_opts:
type: none
device: /opt/mastodon/database/pgbackups
o: bind
redis:
driver_opts:
type: none
device: /opt/mastodon/database/redis
o: bind
elasticsearch:
driver_opts:
type: none
device: /opt/mastodon/database/elasticsearch
o: bind
uploads:
driver_opts:
type: none
device: /opt/mastodon/web/system
o: bind
static:
driver_opts:
type: none
device: /opt/mastodon/web/public
o: bindСохраните файл. Обратите внимание: версия образа tootsuite/mastodon указана как v4.0.2 — проверьте релизы на GitHub и обновляйте по мере необходимости.
Комментарий: строка internal: true закомментирована — такая сетка может не работать с firewalld; при исправлении совместимости можно вернуть ограничение.
Генерация секретов приложения
Сгенерируйте SECRET_KEY_BASE и OTP_SECRET (команда потребуется выполнить дважды):
$ docker compose run --rm shell bundle exec rake secretМожно также использовать openssl:
$ openssl rand -hex 64Сгенерируйте VAPID-ключи для webpush:
$ docker compose run --rm shell bundle exec rake mastodon:webpush:generate_vapid_keyВы получите две строки вида VAPID_PRIVATE_KEY=… и VAPID_PUBLIC_KEY=….
Для паролей PostgreSQL и Elasticsearch удобно использовать:
$ openssl rand -hex 15Заполнение application.env и database.env
Отредактируйте application.env:
$ sudo nano application.envВставьте (обязательно измените секреты, ключи и параметры SMTP на свои):
# environment
RAILS_ENV=production
NODE_ENV=production
# domain
LOCAL_DOMAIN=mastodon.example.com
# redirect to the first profile
SINGLE_USER_MODE=false
# do not serve static files
RAILS_SERVE_STATIC_FILES=false
# concurrency
WEB_CONCURRENCY=2
MAX_THREADS=5
# pgbouncer
#PREPARED_STATEMENTS=false
# locale
DEFAULT_LOCALE=en
# email, not used
SMTP_SERVER=email-smtp.us-west-2.amazonaws.com
SMTP_PORT=587
SMTP_LOGIN=AKIA3FIG4NVFNSC3AHXE
SMTP_PASSWORD=BHM4MVOjBmnGhSJ9lH3PAXKJ/9AiLWcUghG/kEN2kkFo
[email protected]
# secrets
SECRET_KEY_BASE=c09fa403575e0b431e54a2e228f20cd5a5fdfdbba0da80598959753b829a4e3c0266eedbac7e3cdf9f3345db36c56302c0e1bc5bfc8c5d516be59a2c41de7e37
OTP_SECRET=febb7dbb0d3308094083733fc923a430e52ccec767d48d7d2e0c577bfcb6863dbdfc920b1004b1f8c2967b9866bd7a0b4a15460f9fc7687aa4a42acf54e5a3d4
# Changing VAPID keys will break push notifications
VAPID_PRIVATE_KEY=13RgrfOY2tkwuUycylDPOkoHennkJ0ZAPV_fUwDy7-g=
VAPID_PUBLIC_KEY=BDAQuGwPbh1kbCV904adYXHvz9lLRaJHkiQkihRDPyBn3QmkAYbR21WHYoP8TkyG6dylG6IXpEVfLwdoW7fJVns=Сохраните и закройте.
Отредактируйте database.env:
$ sudo nano database.envВставьте содержимое (замените пароли на свои):
# postgresql configuration
POSTGRES_USER=mastodon
POSTGRES_DB=mastodon
POSTGRES_PASSWORD=15ff12dcb93aa60680d2aadb4032ee
PGPASSWORD=15ff12dcb93aa60680d2aadb4032ee
PGPORT=5432
PGHOST=postgresql
PGUSER=mastodon
# elasticsearch
ES_JAVA_OPTS=-Xms512m -Xmx512m
ELASTIC_PASSWORD=13382e99f6b2d4dc7f3d66e4b9872d
# mastodon database configuration
DB_HOST=postgresql
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=15ff12dcb93aa60680d2aadb4032ee
DB_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_REDIS_HOST=redis-volatile
CACHE_REDIS_PORT=6379
ES_ENABLED=true
ES_HOST=elasticsearch
ES_PORT=9200
ES_USER=elastic
ES_PASS=13382e99f6b2d4dc7f3d66e4b9872dСохраните и закройте.
Подготовка статики и запуск слоя данных
Скопируйте статические файлы для Nginx:
$ docker compose run --rm shell bash -c "cp -r /opt/mastodon/public/* /static/"Поднимите слой данных:
$ docker compose up -d postgresql redis redis-volatileПроверяйте состояние контейнеров:
$ watch docker compose psКогда контейнеры будут в состоянии running (healthy), инициализируйте базу данных:
$ docker compose run --rm shell bundle exec rake db:setupШаг 5 — Установка Nginx
Добавьте официальный репозиторий Nginx:
$ sudo nano /etc/yum.repos.d/nginx.repoВставьте:
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=trueУстановите Nginx:
$ sudo dnf install nginx
$ nginx -v
$ sudo systemctl enable nginx --now
$ sudo systemctl status nginxШаг 6 — SSL и Certbot
Установите EPEL и Snapd, затем Certbot:
$ sudo dnf install epel-release
$ sudo dnf install snapd
$ sudo systemctl enable snapd --now
$ sudo snap install core
$ sudo snap refresh core
$ sudo ln -s /var/lib/snapd/snap /snap
$ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbotЗапрос сертификата для Nginx (замените email и домен):
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d mastodon.example.comСертификат окажется в /etc/letsencrypt/live/mastodon.example.com.
Сгенерируйте Diffie-Hellman группу:
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096Проверьте dry-run обновления:
$ sudo certbot renew --dry-runЕсли ошибок нет — автообновление настроено.
Шаг 7 — Конфигурация Nginx
Отредактируйте /etc/nginx/nginx.conf и добавьте перед include строку:
server_names_hash_bucket_size 64;Создайте конфигурацию /etc/nginx/conf.d/mastodon.conf и вставьте блок Nginx, как в оригинале. Приведённый ниже фрагмент содержит оптимизации TLS, кэширования и проксирования к внутренним портам 3000/4000.
(Вставьте полный блок конфигурации, приведённый в исходном руководстве — он остаётся без изменений.)
Проверьте синтаксис и перезапустите Nginx:
$ sudo nginx -t
$ sudo systemctl restart nginxЕсли вы видите ошибку SELinux на запуске Nginx, примените policy:
$ sudo ausearch -c 'nginx' --raw | audit2allow -M my-nginx
$ sudo semodule -X 300 -i my-nginx.pp
$ sudo systemctl start nginxШаг 8 — Запуск Mastodon
Утилита tootctl
Сделайте удобную обёртку для tootctl на хосте:
$ sudo nano /usr/local/bin/tootctlВставьте:
#!/bin/bash
docker compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl "$@"Сделайте файл исполняемым:
$ sudo chmod +x /usr/local/bin/tootctlsystemd-юнит для Mastodon
Создайте /etc/systemd/system/mastodon.service:
[Unit]
Description=Mastodon service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml down
[Install]
WantedBy=multi-user.targetАктивируйте сервис:
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mastodon.service
$ watch docker compose -f /opt/mastodon/docker-compose.yml psСоздайте администратора:
$ tootctl accounts create navjot --email [email protected] --confirmed --role adminЕсли нужно закрыть регистрацию:
$ tootctl settings registrations closeИ снова открыть:
$ tootctl settings registrations openИнициализация поиска
Для Elasticsearch нужно создать хотя бы одну запись («тоот»), затем развернуть индексы:
$ tootctl search deployЕсли получите ошибку, связанную с ProgressBar (InvalidProgressError), войдите в контейнер web и выполните замену:
$ docker exec -it mastodon-web-1 /bin/bash
$ sed -E 's/indices.sum.+/2000/g' -i lib/mastodon/search_cli.rb
$ exit
$ tootctl search deployШаг 9 — Дополнительные сервисы и обслуживание
Службы удаления медиа и превью
Создайте systemd-сервисы для очистки медиа и preview-карт, а также таймеры для планирования задач. Примеры сервисов и таймеров приведены в исходном руководстве — вставьте их как файлы в /etc/systemd/system и включите:
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mastodon-preview_cards-remove.timer
$ sudo systemctl enable --now mastodon-media-remove.timer
$ systemctl list-timersМониторинг и администрирование
- Sidekiq: https://mastodon.example.com/sidekiq/ — просмотр фоновых задач и ошибок.
- PgHero: https://mastodon.example.com/pghero/ — состояние базы данных и медленные запросы.
Чтобы включить статистику запросов, добавьте в postgresql.conf в каталоге данных блок:
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.track = allЗатем перезапустите контейнеры Mastodon:
$ sudo systemctl restart mastodon.serviceЕсли сайт не открывается, смотрите логи контейнеров:
$ docker logs Шаг 10 — Резервное копирование
Мы используем Restic для резервного копирования в S3-совместимое хранилище. Составьте список файлов для бэкапа:
$ sudo nano /opt/mastodon/backup-filesПример списка:
/etc/nginx
/etc/letsencrypt
/etc/systemd/system
/root
/opt/mastodon/database/pgbackups
/opt/mastodon/*.env
/opt/mastodon/docker-compose.yml
/opt/mastodon/branding
/opt/mastodon/database/redis
/opt/mastodon/web/system
/opt/mastodon/backup-files
/opt/mastodon/mastodon-backupУстановите Restic:
$ sudo dnf install resticИнициализируйте репозиторий и сделайте первый бэкап (пример для S3):
$ restic -r s3:https://$SERVER:$PORT/mybucket init
$ restic -r s3:https://$SERVER:$PORT/mybucket backup $(cat /opt/mastodon/backup-files) --exclude /opt/mastodon/database/postgresqlСоздайте systemd-юнит и таймер для периодического запуска бэкапов (пример hourly). Также создайте скрипт /opt/mastodon/mastodon-backup с командами pg_dump и вызовами restic. Не забудьте заполнить переменные AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, SERVER, PORT и RESTIC_PASSWORD_FILE.
Включите таймеры:
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mastodon-backup.service
$ sudo systemctl enable --now mastodon-backup.timerПроверьте снимки:
$ restic -r s3:https://$SERVER:$PORT/mybucket snapshots
$ restic -r s3:https://$SERVER:$PORT/mybucket mount /mntШаг 11 — Обновление Mastodon
Базовый порядок действий при обновлении:
$ cd /opt/mastodon
$ docker compose pull
$ docker compose run --rm shell bundle exec rake db:migrate
$ docker compose run --rm shell bash -c "cp -r /opt/mastodon/public/* /static/"
$ sudo systemctl restart mastodon.serviceОбязательно изучите релиз-ноуты на GitHub перед обновлением — иногда требуются дополнительные шаги миграции.
Доступ к веб-интерфейсу и панель администратора
Откройте в браузере https://mastodon.example.com. Войдя под администратором, используйте меню Настройки → Администрирование, затем пункт Site settings, чтобы заполнить контактную информацию, описание сервера, логотип и правила.




Разделы обслуживания и отладки




Когда установка может не сработать
- Недостаточно ресурсов: реальный инстанс требует больше RAM/CPU и дискового пространства, особенно при росте числа пользователей.
- Неправильно настроенные DNS-записи или блокировка портов провайдером — проверьте A/AAAA и открытые порты 80/443.
- SELinux без корректных правил может блокировать Nginx или Docker — примените audit2allow или настройте политику.
- Неправильные секреты или ошибки в application.env/database.env — внимательно проверяйте переменные среды.
Альтернативные подходы
- Установка без Docker: рекомендуется опытным администраторам, даёт больше контроля, но сложнее в поддержке.
- Использование готовых управлямых сервисов Mastodon-as-a-Service для уменьшения операционной нагрузки.
- Использование k8s (Kubernetes) с Helm-чартом для масштабируемых инсталляций.
Безопасность и конфиденциальность
Советы по усилению безопасности:
- Обновляйте образы и системы своевременно.
- Ограничьте доступ к Docker socket и SSH.
- Настройте бэкап и проверку восстановления (restore тесты).
- Минимизируйте хранение чувствительных данных в плейнтексте; храните секреты в защищённом секрет-менеджере.
Конфиденциальность и GDPR:
- По умолчанию Mastodon хранит данные пользователей; документируйте политику хранения и срока удаления данных.
- Для юрисдикций с требованиями по геолокации данных используйте региональные S3 и файрволы.
Модель зрелости инстанса (уровни)
- Ниво 0 — тестовый: один админ, минимум пользователей, нет резервных копий.
- Ниво 1 — продуктивный маленький: регулярные бэкапы, SSL, мониторинг, лимиты ресурсов.
- Ниво 2 — зрелый: автомасштабирование, репликация БД, уведомления инцидентов.
Контрольный список по ролям
Администратор сервера:
- Настроить DNS и firewall.
- Установить Docker, Nginx и Certbot.
- Настроить systemd-сервисы и таймеры.
Администратор Mastodon:
- Создать администратора аккаунт через tootctl.
- Настроить Site settings и правила сервера.
- Проводить регулярные обновления и мониторинг Sidekiq/PgHero.
Операции и резервное копирование:
- Проверять снимки Restic и тестировать восстановление.
- Следить за временем отклика Elasticsearch и размером индексов.
Критерии приёмки
- Сайт доступен по HTTPS и корректно редиректит с HTTP.
- Sidekiq и PgHero доступны и показывают статус процессов.
- Резервные копии создаются по расписанию и успешно восстанавливаются в тестовой среде.
- Индексы поиска развернуты и поисковые запросы возвращают результаты.
Быстрая методология обновления
- Сделать бэкап (Restic + pg_dump).
- Прочитать release notes Mastodon.
- docker compose pull -> db:migrate -> обновление статики -> перезапуск сервисов.
- Проверить Sidekiq и логи.
Типичные ошибки и как их решать
- Nginx: “Permission denied” — проверьте SELinux и примените политики audit2allow.
- Elasticsearch: недостаточно vm.max_map_count — увеличьте значение, как описано.
- Webpush не работает — проверьте VAPID-ключи и сохранение VAPID_PRIVATE_KEY/ PUBLIC.
- Ошибки при миграции — проверьте версии образов и совместимость баз данных.
Шаблон восстановления (коротко)
- Остановить mastodon.service.
- Восстановить файлы из Restic.
- Восстановить дамп PostgreSQL в контейнере postgresql.
- Запустить контейнеры и проверить db:migrate и состояние Sidekiq.
Заключение
Это руководство покрывает полный цикл развёртывания Mastodon на Rocky Linux 9 через Docker: подготовка сервера, сетевые настройки, Docker, Nginx и SSL, запуск, обслуживание, бэкап и обновления. При внедрении адаптируйте параметры под нагрузку и соблюдайте политики безопасности и резервного копирования.
Если остались вопросы — опишите их в комментариях к статье или обратитесь к официальной документации Mastodon и репозиторию на GitHub.
Похожие материалы
Malwarebytes: исправление высокого потребления памяти
Ошибка 'Этот файл нельзя просмотреть' в Outlook — исправление
Исправить KERNEL_SECURITY_CHECK_FAILURE в Windows 10
Микрофон не работает в Windows 11 — руководство
LEMH: Nginx + MariaDB + HHVM на Ubuntu