SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-26

Как установить Jellyfin на VPS в Docker

Пошаговое руководство по запуску Jellyfin на VPS. Разбираем настройку прав доступа к томам, оптимизацию транскодирования без GPU и безопасный удаленный доступ к медиатеке.

Что вы создаете

Медиасервер Jellyfin на VPS: один контейнер, три тома и блочное хранилище для ваших фильмов и сериалов, доступное из любого браузера или приложения Jellyfin. Установка выполняется с помощью compose-файла из 15 строк. Все последующие проблемы возникают по двум причинам: права доступа к файлам, которые контейнер не может прочитать, и попытки транскодирования видео на VPS без GPU, который для этого не предназначен. Большая часть этого руководства посвящена именно этим двум аспектам, так как именно они являются основными источниками обращений в поддержку.

Jellyfin — это бесплатное ПО с полностью открытым исходным кодом, без обязательных учетных записей, платных функций и телеметрии. Именно поэтому он входит почти в каждый список проектов для self-hosting в 2026 году. Он воспроизводит медиафайлы, которыми вы владеете. Продукт не поставляется с контентом, и данное руководство не касается вопросов его получения.

Реальность транскодирования: что нужно знать перед арендой

Прочитайте это до покупки, так как информация влияет на выбор оборудования. При нажатии кнопки воспроизведения медиасервер выполняет одно из двух действий. Direct play передает файл «как есть»: VPS считывает байты с диска и отправляет их по сети, практически не нагружая CPU. Транскодирование перекодирует видео на лету — меняет разрешение, кодек или «вшивает» субтитры, что требует значительных ресурсов CPU.

Типичный VPS не имеет GPU. Поэтому любое транскодирование выполняется силами CPU с помощью libx264/libx265, а программное кодирование — ресурсоемкий процесс. Одно транскодирование 1080p H.264 может полностью загрузить несколько общих vCPU; транскодирование 4K или HEVC обычно не успевает за реальным временем, из-за чего воспроизведение постоянно прерывается буферизацией. Аппаратное транскодирование, которое делает этот процесс дешевым на домашнем сервере с Intel iGPU или картой Nvidia, на VPS недоступно, если только провайдер не предоставляет GPU-инстансы.

Поэтому стратегия работы на VPS проста: избегайте транскодирования. Храните библиотеку в кодеках, которые клиенты воспроизводят нативно: видео H.264, аудио AAC или AC3 в контейнерах MP4 или MKV. Используйте клиентские приложения с поддержкой direct play: нативные приложения Jellyfin для Android TV, iOS и Roku, а также Infuse, Kodi и десктопный Jellyfin Media Player. При таком подходе VPS не использует ffmpeg, и даже скромный сервер с 2 vCPU может обслуживать несколько пользователей одновременно. Если вы планируете транскодирование, вам потребуется гораздо более мощный и дорогой сервер, но даже в этом случае 4K останется рискованным выбором.

Проведите и расчёт пропускной способности: это ещё один источник неожиданных ограничений. При прямом воспроизведении файл передаётся с исходным битрейтом. Сжатый файл 1080p требует 8-12 Mbps; remux Blu-ray 1080p — 20-30 Mbps; 4K HDR — 40-80 Mbps. Три пользователя, напрямую воспроизводящие файлы с битрейтом 10 Mbps, создают на VPS постоянный исходящий трафик 30 Mbps. Проверьте в вашем тарифе два параметра: скорость порта (может ли он передавать 30 Mbps в исходящем направлении?) и месячный лимит трафика. Один двухчасовой фильм с битрейтом 10 Mbps создаёт около 9 GB исходящего трафика. Поэтому при тарифе с лимитом 1 TB/month его хватит немного больше чем на сто таких фильмов в месяц — на три или четыре фильма в день. Если в доме смотрят 4K с битрейтом, в четыре-восемь раз превышающим этот показатель, лимит будет расходоваться намного быстрее. Учитывайте в том же бюджете любой другой исходящий трафик с этого сервера, включая самостоятельно размещённый relay RustDesk, который передаёт весь сеанс удалённого рабочего стола, когда двум узлам не удаётся подключиться напрямую.

Предварительные требования

  • Свежий VPS на базе Ubuntu 24.04 с KVM, доступом root или sudo, а также установленными Docker и плагином Compose.
  • Блочное хранилище для медиафайлов, объем которого соответствует вашей библиотеке (см. раздел о расчете размера ниже). Не следует хранить фильмы на небольшом корневом диске, который поставляется вместе с VPS.
  • Доменное имя, если вам нужен публичный доступ по HTTPS, или WireGuard VPN на том же VPS, если вы предпочитаете оставить систему полностью приватной.
  • Медиафайлы, на трансляцию которых у вас есть законные права: ваши собственные копии, записи или файлы, которыми вы владеете.

Сначала смонтируйте блочное хранилище

Подключите том в панели управления вашего провайдера, затем найдите его и смонтируйте. Получите имя устройства с помощью lsblk, оно будет выглядеть как /dev/sdb или /dev/vdb, но это никогда не должен быть корневой диск.

lsblk
sudo mkfs.ext4 /dev/sdb          # ONLY on a new, empty volume — this ERASES it
sudo mkdir -p /mnt/media
sudo blkid /dev/sdb              # copy the UUID shown for this device

Монтируйте его по UUID, а не по /dev/sdb, так как буквы устройств могут меняться после перезагрузок, и вы можете случайно отформатировать или смонтировать не тот диск. Добавьте одну строку в /etc/fstab:

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  /mnt/media  ext4  defaults,nofail  0  2
sudo mount -a
df -h /mnt/media

Параметр nofail важен: без него, если блочный том будет отсоединен, сервер откажется загружаться и перейдет в аварийную оболочку (emergency shell). Самая распространенная ошибка здесь — запуск mkfs.ext4 на томе, где уже есть данные, так как это приведет к их удалению. Форматируйте только новые тома; если на диске уже находится ваша библиотека, сразу переходите к добавлению строки в fstab.

Организация медиафайлов в соответствии с требованиями Jellyfin

Jellyfin сопоставляет метаданные на основе имен папок и файлов. При неверной структуре фильмы отображаются как файлы без названия и обложек, а серии могут быть ошибочно приписаны к другому сериалу. Существует ровно три правила: каждый фильм должен находиться в собственной папке Name (Year) с соответствующим именем файла; папки сезонов должны называться Season 01, а не S01; файлы эпизодов должны использовать S01E01, а спецвыпуски — Season 00.

/mnt/media
├── Movies
│   ├── Blade Runner (1982)
│   │   └── Blade Runner (1982).mkv
│   └── Arrival (2016)
│       └── Arrival (2016).mkv
└── Shows
    └── Severance (2022)
        ├── Season 01
        │   ├── Severance - S01E01.mkv
        │   └── Severance - S01E02.mkv
        └── Season 00
            └── Severance - The Lexington Letter.mkv

(Year) в названиях фильмов — это не декоративный элемент, а способ различения ремейков, позволяющий сканеру выбрать верное название. Храните Movies и Shows в отдельных корневых папках, так как каждая из них становится библиотекой Jellyfin с определенным типом контента, а их смешивание затрудняет работу провайдера метаданных. Jellyfin может проиндексировать и третью папку с фотографиями, но функциональность будет значительно уступать специализированному серверу. Если ваши альбомы важны, выделите для них отдельный сервер с PhotoPrism или Immich, а этот оставьте для фильмов и сериалов.

Права доступа: главная причина пустых библиотек

Это заблуждение, которое стоит людям целого вечера. Официальный образ jellyfin/jellyfin не учитывает переменные окружения PUID/PGID, они относятся к образу LinuxServer.io (lscr.io/linuxserver/jellyfin). В официальном образе вы управляете пользователем с помощью ключа user: в compose, а если его пропустить, контейнер будет запущен от имени root. Какой бы вариант вы ни выбрали, правило одно: uid/gid, от имени которого работает контейнер, должен иметь права на чтение и обход всех каталогов с медиафайлами.

Мы будем запускаться от uid/gid 1000 — это первый пользователь без прав root в стандартной установке Ubuntu. Уточните свои значения и установите владельца:

id                                  # confirm your user is uid=1000 gid=1000
sudo chown -R 1000:1000 /mnt/media
sudo find /mnt/media -type d -exec chmod 755 {} \;
sudo find /mnt/media -type f -exec chmod 644 {} \;
mkdir -p ~/jellyfin/config ~/jellyfin/cache
sudo chown -R 1000:1000 ~/jellyfin

Каталогам необходим бит execute (x в 755), а не только право на чтение. Без него контейнер не сможет войти в папку, даже если видит её имя. Ловушка, из-за которой пустеет вся библиотека, кроется в родительском каталоге: если uid контейнера не может выполнить обход самой точки монтирования, он никогда не доберется до /media/Movies или /media/Shows, и вся библиотека мгновенно окажется пустой, а в логах появится Access to the path ... is denied. Любая отдельная папка с медиафайлами, которую контейнер не может прочитать, будет пропущена с записью в лог, поэтому пакет файлов, скопированный от имени root, просто исчезнет из библиотеки. Именно поэтому мы выполняем chown рекурсивно и устанавливаем бит execute для всех каталогов, а не исправляем одну папку.

Файл docker-compose

services:
  jellyfin:
    image: jellyfin/jellyfin:10
    container_name: jellyfin
    user: "1000:1000"
    restart: unless-stopped
    ports:
      - "127.0.0.1:8096:8096"
    volumes:
      - ./config:/config
      - ./cache:/cache
      - /mnt/media:/media:ro
    environment:
      - JELLYFIN_PublishedServerUrl=https://jellyfin.example.com

Разбор по строкам: user: "1000:1000" — это команда, которая фактически устанавливает права доступа к файлам, соответствующие владельцу, указанному выше. В /config хранится весь сервер, учетные записи, библиотеки, метаданные и состояние просмотра, поэтому каталог должен быть доступен для записи; именно его необходимо резервировать. /cache — это временное рабочее пространство. Монтирование медиабиблиотеки выполнено как :ro (только для чтения) намеренно: Jellyfin по умолчанию сохраняет обложки и метаданные в /config, поэтому серверу не требуется запись в вашу библиотеку, а режим только для чтения защищает файлы от случайного удаления или некорректной работы плагинов. Порт привязан к 127.0.0.1 намеренно, так как веб-интерфейс Jellyfin использует обычный HTTP, поэтому мы никогда не открываем 8096 для публичного доступа из Интернета. JELLYFIN_PublishedServerUrl — это адрес, который сервер сообщает для локального автообнаружения через широковещательные UDP-пакеты в локальной сети, поэтому клиенты в Интернете его не увидят и будут просто использовать URL, который вы вводите в приложении. Установите этот параметр в соответствии с адресом, который должны знать клиенты; на удаленных устройствах ожидайте, что URL придется вводить вручную.

Запустите сервис из директории с файлом compose:

docker compose up -d
docker logs -f jellyfin

Первый запуск: мастер настройки и ваши библиотеки

Поскольку порт привязан к localhost, получите доступ к мастеру через SSH-туннель с вашего ноутбука, вместо того чтобы открывать порт в брандмауэре:

ssh -L 8096:127.0.0.1:8096 you@your-vps-ip

Теперь перейдите по адресу http://localhost:8096. Мастер предложит выбрать язык, а затем создать учетную запись администратора с надежным паролем. Эта учетная запись управляет вашим сервером, поэтому не используйте временные или слабые пароли. Добавьте свою первую библиотеку: выберите тип контента Movies, укажите путь /media/Movies (путь внутри контейнера, а не путь на хосте), и повторите то же самое для Shows, указав /media/Shows. Завершите настройку, и Jellyfin начнет сканирование. При корректной работе плакаты и названия появятся в течение минуты или двух для небольшой библиотеки. Добавлять или редактировать библиотеки можно позже в разделе Dashboard → Libraries, а принудительное сканирование запускается через Scan All Libraries.

Если вы планируете использовать транскодирование, откройте Dashboard → Playback → Transcoding и установите путь для временных файлов транскодирования в /cache/transcodes, чтобы нагрузка приходила на том кэша, а не переполняла /config. Оставьте аппаратное ускорение (hardware acceleration) в значении None, так как в системе отсутствует GPU для обработки видео.

Удаленный доступ: TLS reverse proxy или использование VPN

Существует два безопасных способа доступа к Jellyfin извне и один небезопасный, которого следует избегать. Небезопасный способ — публикация порта 8096 напрямую в Интернет: данные для входа передаются в открытом виде, а порт подвергается брутфорс-атакам в течение нескольких часов.

Вариант A, TLS reverse proxy. Разместите Jellyfin на поддомене за Traefik с автоматическим TLS для ваших Docker-приложений или за nginx с сертификатом Let's Encrypt, выпущенным через Certbot. Jellyfin использует WebSockets для обновлений в реальном времени, поэтому прокси должен пересылать заголовки upgrade. Traefik делает это автоматически; для nginx их нужно прописать явно, а также использовать HTTP/1.1 для upstream, иначе обновление соединения не произойдет:

location / {
    proxy_pass http://127.0.0.1:8096;
    proxy_http_version 1.1;
    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;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

Установите JELLYFIN_PublishedServerUrl в значение адреса https://, чтобы локальное автообнаружение транслировало правильный URL, удаленные приложения использовали указанный вами адрес, и добавьте fail2ban для замедления попыток брутфорса страницы входа. Как только сервер станет публичным, настройте Uptime Kuma на этот URL, чтобы узнавать о простоях раньше ваших пользователей.

Вариант B, ограничение доступа через VPN. Не публикуйте порт 8096 вовсе; получайте доступ к Jellyfin только через туннель WireGuard, завершающийся на том же сервере. Для домашнего использования это самый простой и безопасный выбор: нет необходимости в сертификатах, нет публичного доступа и нет поверхности для брутфорс-атак. Привяжите контейнер к адресу туннеля или localhost и подключайтесь через VPN. Инструкцию по настройке самого туннеля см. в настройке WireGuard VPN для частного VPS.

Планирование объема хранилища и резервное копирование

Ориентируйтесь на качество контента, а не на количество файлов. Сжатые фильмы в 1080p занимают 4-15 ГБ; ремуксы 1080p — 20-40 ГБ; сезон сериала в 1080p — 15-40 ГБ; любой контент в 4K — 40-100 ГБ на фильм. Для библиотеки из нескольких сотен фильмов и сериалов потребуется том объемом 2-4 ТБ. Дешевле сразу выделить избыточный объем блочного устройства, чем заниматься миграцией данных в будущем.

/config содержит всё состояние сервера, поэтому это единственный элемент, который необходимо копировать. Создавайте снапшот или останавливайте контейнер для архивации (tar), после чего сохраняйте копию вне сервера:

docker compose down
sudo tar czf jellyfin-config-$(date +%F).tgz -C ~/jellyfin config
docker compose up -d

/cache и папка транскодирования являются временными данными. Медиафайлы на /mnt/media копируются отдельно или рассматриваются как данные, которые можно восстановить повторно (большинство пользователей выбирают второй вариант из-за большого объема). Обновления выполняются через docker compose pull && docker compose up -d; тег :10, указанный выше, остается в рамках мажорной версии 10.x, поэтому переход на следующую мажорную версию требует осознанного изменения тега. Перед этим ознакомьтесь с примечаниями к выпуску Jellyfin, так как в мажорных версиях часто происходят миграции схемы базы данных библиотеки. Закрепленный тег и одна резервная копия директории состояния — это универсальный рецепт для любого постоянно работающего контейнера. Тот же принцип лежит в основе сохранения памяти и расписаний self-hosted агента после перезагрузки.

Режимы сбоев и соответствующие сообщения

Библиотека пуста после сканирования. Журнал в разделе Dashboard → Logs (или ~/jellyfin/config/log/log_*.log) содержит:

System.UnauthorizedAccessException: Access to the path '/media/Movies' is denied.

Контейнер с указанным uid не имеет прав на чтение этого пути. Причина: медиафайлы принадлежат пользователю root или uid, отличному от вашего значения user:, у каталога отсутствует бит выполнения, либо сам родительский раздел недоступен для обхода этим uid. Решение: chown -R 1000:1000 /mnt/media, каталоги 755, файлы 644, затем повторите сканирование.

Воспроизведение загружает процессор и вызывает буферизацию. docker stats jellyfin показывает загрузку процессора, близкую к 100% на количество ядер, а в Dashboard → Playback сессия помечена как Transcode со скоростью ниже 1.0x. Клиент не использует прямое воспроизведение (direct play), поэтому VPS выполняет транскодирование на процессоре медленнее реального времени и не успевает. Причина: неподдерживаемый кодек или контейнер, «вшивание» субтитров или HDR tone-mapping. Решение: переключитесь на клиент с поддержкой прямого воспроизведения, используйте исходные файлы в формате H.264/AAC, применяйте текстовые субтитры (SRT) вместо графических (PGS/VOBSUB), которые требуют принудительного «вшивания», и не используйте 4K HDR на серверах без аппаратного ускорения.

«No compatible streams are available.» Полное сообщение обычно выглядит как «This client isn't compatible with the media and the server isn't sending a compatible media format.» Клиент отклонил исходный файл, а резервное транскодирование также не удалось запустить. Причина: некорректная команда ffmpeg, нечитаемый файл или настройки профиля пользователя, запрещающие конвертацию видео. Решение: изучите строку ffmpeg в Dashboard → Logs, убедитесь, что файл вообще воспроизводится, проверьте права пользователя на воспроизведение, если вы полагаетесь на транскодирование, и попробуйте другой клиент, чтобы исключить особенности работы кодеков в браузере.

У фильмов нет постера или он неверный. Метаданные не совпали. Причина: фильм находится не в собственной папке Name (Year), папка сезона названа S01 вместо Season 01, эпизоды не соответствуют формату S01E01 или отсутствует год выпуска. Решение: переименуйте файлы согласно структуре выше, затем выберите Refresh metadata → Replace all или используйте Identify для отдельного элемента, чтобы привязать его к корректной записи TMDB/TVDB.

FAQ

Может ли VPS выполнять транскодирование видео без GPU?

Да, но только силами CPU, что требует значительных ресурсов. Одно программное транскодирование 1080p может загрузить несколько vCPU, а 4K или HEVC обычно не успевают обрабатываться в реальном времени, что приводит к буферизации при воспроизведении. Лучшее решение — избегать транскодирования: храните библиотеку в формате H.264/AAC и используйте клиентские приложения с поддержкой прямого воспроизведения (direct-play), чтобы VPS просто передавал байты. Арендуйте инстанс с GPU, только если вам действительно необходимо транскодирование на лету.

Почему библиотека Jellyfin пуста после сканирования?

Почти всегда проблема в правах доступа. Официальный образ jellyfin/jellyfin работает от имени того user:, который вы указали (или root), и если файлы недоступны для чтения этим uid, в логах сканирования появляется Access to the path ... is denied и файлы пропускаются. Исправьте владельца с помощью chown -R 1000:1000 /mnt/media, установите бит исполнения для директорий (755) и запустите сканирование заново. Проверьте также родительские директории: если uid контейнера не может пройти по пути /mnt/media, он никогда не доберется до папок библиотеки, и всё будет выглядеть пустым. Вторая по частоте причина — структура папок, не соответствующая ожиданиям Jellyfin.

Как получить безопасный удаленный доступ к Jellyfin?

Есть два хороших варианта. Разместите его за TLS reverse proxy на поддомене, чтобы логин и поток были зашифрованы, и добавьте fail2ban. Никогда не открывайте порт 8096 напрямую, так как он передает пароль в открытом виде. Либо оставьте его полностью приватным и подключайтесь только через VPN — это самый простой и безопасный выбор для дома. Указывайте приложениям публичный адрес напрямую, так как автообнаружение работает через широковещательные рассылки в локальной сети и не доходит до клиентов, подключающихся через интернет.

Сколько дискового пространства и пропускной способности нужно для VPS с Jellyfin?

Объем диска зависит от качества: закладывайте 4-15 ГБ на сжатый фильм в 1080p, 20-40 ГБ на ремукс и 40-100 ГБ на 4K, поэтому для большинства библиотек потребуется блочное хранилище на 2-4 ТБ. Пропускная способность определяется битрейтом прямого воспроизведения: 8-12 Мбит/с на один поток 1080p и значительно больше для 4K. Убедитесь, что скорость вашего порта справляется с количеством одновременных зрителей, и следите за ежемесячным лимитом трафика. Добавьте запас по CPU, если планируете транскодирование; если планируете прямое воспроизведение, отдайте приоритет пропускной способности, а не количеству ядер.

Законно ли запускать Jellyfin на VPS?

Jellyfin — это бесплатное программное обеспечение с открытым исходным кодом, и его использование полностью законно. Важен контент: транслируйте только те медиафайлы, которыми вы владеете или на которые имеете лицензию: собственные рипы с дисков, записи или файлы, на которые у вас есть права. Jellyfin не поставляется с медиаконтентом и не предоставляет способов его получения; это плеер для библиотеки, которая уже принадлежит вам.