PeerTube на сервере: частые ошибки и решения
PeerTube выглядит просто на бумаге: Docker Compose, пара переменных окружения — и у вас свой видеохостинг без цензуры и рекламы. На практике первый же залитый ролик падает на транскодировании, nginx возвращает 413 на загрузке, а федерация с другими инстансами молчит неделями. Ниже — конкретные причины и рабочие решения для типичных проблем PeerTube на VPS и выделенном сервере.
Содержание
- Минимальные требования и на чём экономить нельзя
- Docker Compose: типичные ошибки установки
- Транскодирование: ffmpeg падает или зависает
- Хранилище: локальный диск против S3-совместимого объектного хранилища
- Nginx как reverse proxy: 413, таймауты и зависшие загрузки
- Федерация ActivityPub: инстанс не виден другим серверам
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Минимальные требования и на чём экономить нельзя
PeerTube — это не просто веб-приложение, а связка из пяти компонентов: сам сервер на Node.js, PostgreSQL, Redis (очередь задач на Bull), ffmpeg для транскодирования и nginx как reverse proxy. Официально разработчики рекомендуют от 2 CPU и 2 ГБ RAM для инстанса без активного транскодирования, но это оптимистичная цифра.
Реальные узкие места:
- CPU при транскодировании. Каждый залитый ролик перекодируется в несколько разрешений (обычно 240p–1080p), и это чисто процессорная нагрузка — GPU-ускорение в стандартной сборке не используется. На 2 vCPU перекодирование часового видео в четыре разрешения может занять дольше, чем длится само видео — ориентируйтесь на это, у вас цифры будут отличаться в зависимости от кодека и битрейта исходника.
- Диск. Одно видео на входе плюс 4-5 транскодированных копий плюс превью и штормовые превью (storyboard) — итоговый объём на диске легко в 2-3 раза больше исходника. Если планируете десятки активных пользователей — закладывайте место с запасом, а не по факту.
- RAM. PostgreSQL и Redis сами по себе просят немного, но ffmpeg-процессы транскодирования держат по несколько сотен мегабайт каждый, и при нескольких параллельных джобах сервер на 2 ГБ уходит в swap.
Практический стартовый минимум для боевого инстанса с несколькими активными авторами — 4 vCPU, 8 ГБ RAM, SSD от 100 ГБ с возможностью расширения. Диск закладывайте по худшему сценарию — с расчётом на несколько транскодированных копий каждого ролика, а не по размеру исходников.
Docker Compose: типичные ошибки установки
Официальный способ — docker-compose из репозитория PeerTube. Базовая структура docker-compose.yml:
services:
peertube:
image: chocobozzz/peertube:production-bookworm
env_file:
- .env
volumes:
- ./docker-volume/data:/data
- ./docker-volume/config:/config
depends_on:
- postgres
- redis
ports:
- "127.0.0.1:9000:9000"
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: peertube
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: peertube
volumes:
- ./docker-volume/db:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
- ./docker-volume/redis:/data
Частые ошибки на этом шаге:
- Контейнер стартует и сразу падает — почти всегда либо PostgreSQL ещё не готов принимать соединения (нет
depends_onс healthcheck, PeerTube пытается подключиться раньше времени), либо не хватает переменных в.env. Проверяйте логи черезdocker compose logs -f peertube, а не гадайте. PEERTUBE_WEBSERVER_HOSTNAMEуказан неверно или изменён после первого запуска. Это критично: PeerTube "зашивает" домен в идентификаторы ActivityPub-акторов (https://ваш-домен/accounts/username) при первой инициализации базы. Смена домена после старта ломает федерацию и требует ручной миграции в базе — проще сразу определиться с доменом и не трогать его.- PostgreSQL без нужных расширений. PeerTube требует
pg_trgmиunaccent. Официальный образ PostgreSQL для PeerTube их накатывает автоматически через init-скрипт, но если вы используете внешнюю управляемую БД — расширения нужно включить вручную:
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS unaccent;
Если проблема не в PeerTube-специфике, а в общих граблях конфигурации — стоит свериться с материалом про частые ошибки Docker Compose в проде.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверТранскодирование: ffmpeg падает или зависает
Транскодирование — самое хрупкое место PeerTube в эксплуатации. Симптомы: видео залилось, но остаётся в статусе "обрабатывается" бесконечно, либо в логах ошибка ffmpeg exited with code 1.
Проверьте по порядку:
- Версия ffmpeg внутри контейнера. PeerTube чувствителен к версии ffmpeg — слишком старая не поддерживает нужные пресеты кодирования. В официальном Docker-образе версия уже подобрана правильно; если вы ставите PeerTube вручную (не через Docker), проверьте версию:
ffmpeg -version
Нужна версия из репозитория, актуальная на момент установки — не та, что осталась в дистрибутиве по умолчанию (в Debian/Ubuntu репозиториях ffmpeg часто устаревший).
- Очередь Redis забита. Транскодирование идёт через job-очередь на Bull/Redis. Если Redis недоступен или переполнен, задачи копятся, но не выполняются. Проверка:
docker compose exec redis redis-cli ping
docker compose exec redis redis-cli llen bull:transcoding-job:wait
Если очередь растёт, а не убывает — увеличивайте transcoding.concurrency в конфиге или добавляйте CPU. Общие грабли самого Redis (память, конфиг persistence, потеря данных после рестарта) разобраны в статье про частые ошибки Redis на сервере.
- Не хватает памяти под конкретный ffmpeg-процесс. OOM killer тихо убивает процесс транскодирования без явной ошибки в интерфейсе PeerTube — только в
dmesgилиjournalctl -kнайдётеOut of memory: Killed process ffmpeg. Решение — либо увеличить RAM, либо снизить число одновременных транскодирований (transcoding.concurrencyвconfig/production.yaml), либо урезать список целевых разрешений:
transcoding:
enabled: true
resolutions:
"240p": true
"360p": true
"480p": true
"720p": true
"1080p": false
concurrency: 1
Меньше разрешений — меньше нагрузки и меньше диска на каждое видео.
Хранилище: локальный диск против S3-совместимого объектного хранилища
По умолчанию PeerTube хранит видео и превью на локальном диске сервера в /data. Это работает, но масштабируется плохо: диск на VPS конечен, а видео растут быстро.
С версии PeerTube поддерживает объектное хранилище (S3-совместимое) для видео, стримов и веб-торрент файлов. Конфигурация в config/production.yaml:
object_storage:
enabled: true
endpoint: "s3.example.com"
region: "us-east-1"
credentials:
access_key_id: "YOUR_ACCESS_KEY"
secret_access_key: "YOUR_SECRET_KEY"
streaming_playlists:
bucket_name: "peertube-streaming"
web_videos:
bucket_name: "peertube-web-videos"
Частые проблемы с этой схемой:
- Загрузка "зависает" на 100%, но видео не появляется. Обычно это таймаут при заливке файла из локального temp-каталога PeerTube в S3-хранилище — либо сеть между сервером и хранилищем медленная, либо bucket-политика не даёт права на запись. Проверяйте права ключа доступа отдельно, до подключения к PeerTube.
- Проигрыватель показывает "видео недоступно" после переключения на S3, хотя раньше всё работало. Часто причина — не выставлен
base_urlдля CDN/прокси перед бакетом, и PeerTube формирует ссылки, недоступные извне.
Если разворачиваете собственное S3-совместимое хранилище на том же сервере — например, для тестового стенда, — подойдёт любой self-hosted S3-совместимый сервер: конфигурация PeerTube не отличается от подключения к облачному провайдеру, важны только endpoint и region, соответствующие вашей установке.
Nginx как reverse proxy: 413, таймауты и зависшие загрузки
PeerTube не рассчитан на приём внешнего трафика напрямую — перед ним обязательно нужен nginx. Официальный конфиг из репозитория PeerTube — хорошая база, но два параметра ломаются чаще всего.
Ошибка 413 Request Entity Too Large при загрузке видео больше нескольких сотен мегабайт — классика. По умолчанию nginx ограничивает тело запроса в 1 МБ. Для видеохостинга это нужно поднять явно:
client_max_body_size 12G;
Ставьте значение с запасом относительно реального максимального размера ролика, который вы готовы принимать (в конфиге PeerTube тоже есть свой лимит user.video_quota, они должны быть согласованы).
Таймаут при долгой загрузке или во время live-стрима. Дефолтные 60 секунд proxy_read_timeout в nginx рвут соединение на медленной загрузке большого файла или на RTMP-подобных операциях, обрабатываемых через HTTP. Рекомендуемые значения из официального конфига PeerTube:
proxy_connect_timeout 5m;
proxy_send_timeout 5m;
proxy_read_timeout 5m;
send_timeout 5m;
client_body_timeout 5m;
Также обязательно включите proxy_request_buffering off; для эндпоинтов загрузки — иначе nginx буферизует весь файл на диск перед тем как передать его дальше, что удваивает нагрузку на диск и на время ответа.
Если 502 или 504 всё равно всплывают после этих правок — причина обычно уже не в таймаутах, а в самом PeerTube-процессе (упал, перегружен). Общий разбор диагностики смотрите в статье про ошибку 504 Gateway Timeout в nginx — методика проверки применима и здесь.
Федерация ActivityPub: инстанс не виден другим серверам
PeerTube — часть Fediverse: инстансы федерируются друг с другом через ActivityPub, обмениваясь метаданными о новых видео. Если федерация не работает, ваши видео не появляются в лентах подписчиков на других инстансах, даже если подписка формально оформлена.
Типичные причины:
- Исходящие запросы блокируются файрволом. PeerTube должен уметь стучаться на другие инстансы (webfinger, inbox/outbox ActivityPub) по 443 порту наружу. Если на сервере настроен строгий исходящий firewall — проверьте правила
ufw statusи убедитесь, что исходящий HTTPS не режется по умолчанию. /.well-known/nodeinfoи/.well-known/webfingerнедоступны извне. Эти эндпоинты нужны другим инстансам, чтобы опознать ваш сервер как PeerTube. Проверка снаружи (не с самого сервера, а с другой машины):
curl -s https://ваш-домен/.well-known/nodeinfo
curl -s "https://ваш-домен/.well-known/webfinger?resource=acct:username@ваш-домен"
Если ответ пустой или ошибка — проблема в nginx-роутинге для этих путей, а не в самом PeerTube.
- HTTPS-сертификат некорректен или просрочен. Федерация требует валидный TLS — самоподписанный сертификат или просроченный Let's Encrypt тихо обрывают все входящие федеративные запросы без внятной ошибки в интерфейсе. Если сертификат не обновился автоматически, смотрите разбор в статье SSL-сертификат не обновился.
- DNS PTR-запись отсутствует или не совпадает с доменом. Не строго обязательно для ActivityPub, но некоторые инстансы с усиленной модерацией спама проверяют reputation IP через обратный DNS, и её отсутствие иногда снижает доверие к вашему инстансу при ручной модерации со стороны других администраторов.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли запустить PeerTube на 1 vCPU и 1 ГБ RAM?
Технически стартует, но транскодирование даже одного видео будет крайне медленным, а параллельные загрузки от нескольких пользователей приведут к падениям из-за нехватки памяти. Для тестового ознакомления — да, для боевого инстанса — нет.
Почему видео залилось, но не проигрывается на телефоне, хотя на компьютере работает?
Чаще всего не докачалось одно из низких разрешений (например, 240p), которое мобильный плеер запрашивает первым при слабом сигнале. Проверьте статус транскодирования конкретного видео в админке — если разрешение отсутствует в списке готовых, проблема в очереди транскодирования, а не в проигрывателе.
Нужен ли отдельный сервер под PostgreSQL, если инстанс небольшой?
Нет, для небольшого и среднего инстанса PostgreSQL прекрасно работает на том же сервере в отдельном контейнере. Разносить стоит только когда транскодирование начинает конкурировать с базой за CPU и диск на пиковых нагрузках — тогда логичнее вынести Redis и Postgres на отдельный сервер.
Можно ли отключить транскодирование совсем и отдавать оригинал?
Да, transcoding.enabled: false в конфиге. Но тогда проигрывание зависит от того, поддерживает ли браузер зрителя оригинальный кодек и битрейт файла — часть аудитории с медленным интернетом или старыми устройствами не сможет смотреть комфортно. Отключать имеет смысл только если исходники уже в веб-совместимом формате (H.264 + AAC в MP4) и умеренном битрейте.
Как понять, что причина сбоя — именно PeerTube, а не инфраструктура вокруг?
Начните с логов самого приложения (docker compose logs -f peertube), затем проверьте journalctl на уровне ОС и логи nginx отдельно — совпадение по времени сразу покажет, на каком слое проблема.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →