Встановлення Jellyfin на VPS у Docker
Налаштуйте Jellyfin на VPS за допомогою Docker Compose. Вирішіть проблеми з правами доступу до файлів та налаштуйте транскодування без GPU на VPS.
Що ви створюєте
Медіасервер Jellyfin на VPS: один контейнер, три volumes та диск із блочним сховищем для ваших фільмів і серіалів, доступний через будь-який браузер або додаток Jellyfin. Встановлення виконується за допомогою compose-файлу з п'ятнадцятьма рядками. Більшість проблем виникає з двох причин: права доступу до файлів, які контейнер не може прочитати, та спроби виконувати транскодування відео на VPS без GPU. Цей посібник присвячений саме цим двом аспектам, оскільки саме вони є найчастішими причинами звернень у службу підтримки.
Jellyfin — це безкоштовне програмне забезпечення з відкритим кодом, без реєстрації, платних функцій та телеметрії. Саме тому він постійно потрапляє до списків речей, що варті self-hosting у 2026. Він відтворює медіафайли, які належать вам. Він не містить готового контенту, і цей посібник не присвячений його пошуку.
Реалії транскодування перед орендою
Прочитайте це спочатку, оскільки це впливає на вибір обладнання. Медіасервер виконує одну з двох дій під час відтворення. Direct play передає файл без змін: VPS зчитує байти з диска та передає їх по мережі, що майже не навантажує CPU. Transcoding перекодує відео на льоту — змінює роздільну здатність, кодек або вбудовує субтитри — і це створює високе навантаження на CPU.
Типовий VPS не має GPU. Тому кожне транскодування виконується на CPU з libx264/libx265, а програмне кодування є ресурсомістким. Одне транскодування 1080p H.264 може повністю завантажити кілька спільних vCPU; транскодування 4K або HEVC зазвичай не встигає за реальним часом, через що відтворення зупиняється та постійно буферизується. Апаратне транскодування — функція, яка робить цей процес дешевим на домашніх пристроях з Intel iGPU або карткою Nvidia — недоступне вам, якщо провайдер не пропонує інстанси з 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 є ризикованим рішенням.
Також розрахуйте пропускну здатність мережі, оскільки це ще один сюрприз. Direct play передає файл з його оригінальним бітрейтом. Стиснутий файл 1080p має бітрейт 8-12 Mbps; remux 1080p Blu-ray — 20-30 Mbps; 4K HDR — 40-80 Mbps. Три користувачі, що дивляться файли по 10 Mbps через direct play, створюють постійне навантаження на вихідний канал VPS у 30 Mbps. Перевірте два показники у вашому тарифному плані: швидкість порту (чи зможе він забезпечити 30 Mbps на вихід?) та місячний ліміт трафіку. Один двогодинний фільм з бітрейтом 10 Mbps споживає близько 9 GB трафіку, тому ліміт у 1 TB/місяць дозволяє переглянути трохи більше ста таких фільмів на місяць — три або чотири на день. Якщо ж сім'я дивиться 4K, що у 4-8 разів перевищує цей бітрейт, ліміт вичерпається набагато швидше.
Prerequisites
- Чиста Ubuntu 24.04 KVM VPS з правами root або sudo, встановленими Docker та плагіном Compose.
- Том блочного сховища для медіафайлів, розмір якого відповідає вашій бібліотеці (див. розділ про розрахунок розміру нижче). Фільми не слід зберігати на невеликому кореневому диску, що постачається з VPS.
- Доменне ім'я для публічного доступу через HTTPS або WireGuard VPN на тому ж VPS, якщо ви хочете забезпечити повну приватність.
- Медіаконтент, на трансляцію якого у вас є законні права — ваші власні копії (rips), ваші власні записи або файли, які належать вам.
Спочатку змонтуйте блочне сховище
Приєднайте том у панелі керування вашого провайдера, потім знайдіть його та змонтуйте. Дізнайтеся назву пристрою за допомогою 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 2sudo mount -a
df -h /mnt/medianofail має значення: без цього параметра, якщо блочний том буде від'єднано, система не завантажиться і перейде в режим emergency shell. Найпоширеніша помилка — запуск mkfs.ext4 на томі, що вже містить дані — це видалить їх. Форматуйте лише нові томи; якщо на диску вже є ваша бібліотека, одразу переходьте до рядка у fstab.
Підготуйте медіафайли відповідно до вимог Jellyfin
Jellyfin зіставляє метадані за назвами папок та файлів. Якщо структура порушена, фільми відображатимуться як untitled-файли без постерів, або серія може належати не тому серіалу. Існує три основні правила: кожен фільм має зберігатися в окремій папці 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 певного типу контенту. Змішування цих типів призводить до помилок у метаданих.
Permissions: основна причина порожніх бібліотек
Ось помилка, через яку користувачі втрачають вечір. Офіційний образ jellyfin/jellyfin не підтримує змінні середовища PUID/PGID — вони належать образу LinuxServer.io (lscr.io/linuxserver/jellyfin). В офіційному образі користувач керується через ключ user: у compose; якщо його не вказати, контейнер запускається від імені root. Незалежно від обраного методу, правило однакове: uid/gid, під яким працює контейнер, повинен мати права на читання та проходження (traverse) для кожної директорії з медіафайлами.
Ми будемо використовувати 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, тому йому не потрібно записувати дані у вашу бібліотеку. Режим read-only захищає ваші файли від випадкового видалення або помилок плагінів. Порт прив'язано до 127.0.0.1 навмисно: веб-інтерфейс Jellyfin використовує HTTP, тому ми не відкриваємо порт 8096 для публічного інтернету. JELLYFIN_PublishedServerUrl — це адреса, яку сервер використовує для локального автовиявлення через UDP-трансляцію в LAN; клієнти через інтернет її не побачать і використовуватимуть лише ту URL-адресу, яку ви введете в додатку. Вкажіть тут адресу, яку мають знати клієнти, враховуючи, що на віддалених пристроях цю URL-адресу доведеться вводити вручну.
Запустіть контейнер з директорії compose:
docker compose up -d
docker logs -f jellyfinПерший запуск: майстер налаштування та ваші бібліотеки
Оскільки порт прив'язаний до localhost, використовуйте SSH-тунель зі свого ноутбука замість відкриття порту у firewall:
ssh -L 8096:127.0.0.1:8096 you@your-vps-ipТепер перейдіть за адресою http://localhost:8096. Майстер налаштування запропонує вибрати мову, а потім створити користувача admin із надійним паролем. Цей обліковий запис є основним для сервера, тому не використовуйте тимчасові паролі. Додайте першу бібліотеку: виберіть тип контенту Movies, вкажіть шлях /media/Movies (шлях всередині контейнера, а не хост-системи) і повторіть те саме для Shows за шляхом /media/Shows. Після завершення Jellyfin почне сканування. Якщо бібліотека невелика, постери та назви з'являться протягом 1–2 хвилин. Додавати або редагувати бібліотеки можна пізніше у розділі Dashboard → Libraries; для примусового пересканування використовуйте Scan All Libraries.
Якщо ви плануєте використовувати транскодування, відкрийте Dashboard → Playback → Transcoding і встановіть шлях для тимчасових файлів транскодування на /cache/transcodes. Це дозволить зберігати навантаження на кеш-том, не переповнюючи /config. Параметр hardware acceleration залиште у значенні None, оскільки GPU для прискорення відсутній.
Віддалений доступ: TLS reverse proxy або використання VPN
Існує два безпечні способи доступу до Jellyfin ззовні та один небезпечний, якого слід уникати. Небезпечний спосіб — відкриття порту 8096 безпосередньо в інтернет: дані авторизації передаються у відкритому вигляді, а порт буде підданий brute-force атакам протягом кількох годин.
Варіант А — TLS reverse proxy. Розмістіть Jellyfin на піддомені за допомогою Traefik з автоматичним TLS для ваших Docker-додатків або за допомогою nginx з сертифікатом Let's Encrypt, виданим Certbot. Jellyfin використовує WebSockets для оновлень у реальному часі, тому проксі-сервер має пересилати upgrade headers. Traefik робить це автоматично; у nginx ці заголовки потрібно прописати вручну, а також необхідно використовувати HTTP/1.1 до upstream, інакше upgrade не відбудеться:
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:// адресу, щоб будь-яке локальне автовиявлення (autodiscovery) використовувало правильний URL — віддалені додатки використовують ту адресу, яку ви їм надаєте — і додайте fail2ban для уповільнення brute-force атак на логін. Коли сервер стане публічним, налаштуйте Uptime Kuma на цей URL, щоб дізнатися про збій раніше за глядачів.
Варіант Б — використання приватної VPN. Не відкривайте порт 8096 у мережу; доступ до Jellyfin здійснюйте лише через тунель WireGuard, що завершується на тому ж хості. Для домашнього використання це найпростіший безпечний вибір — без сертифікатів, без публічного доступу та без поверхні для brute-force атак. Прив'яжіть контейнер до адреси тунелю або localhost і підключайтеся через VPN. Детальніше про налаштування тунелю дивіться у WireGuard VPN setup for a private VPS.
Обсяг сховища та резервне копіювання
Орієнтуйтеся на якість, а не на кількість файлів. Стиснуті фільми у 1080p займають від 4 до 15 GB кожен; 1080p remux — 20-40 GB; сезон 1080p TV — 15-40 GB; будь-який 4K контент займає 40-100 GB за фільм. Для бібліотеки з кількох сотень фільмів та серіалів потрібен том обсягом 2-4 TB. Дешевше одразу виділити надлишковий обсяг блочного тому, ніж виконувати міграцію пізніше.
/config — це стан усього сервера, тому це єдиний об'єкт, який необхідно резервувати. Зробіть snapshot або виконайте stop-and-tar і зберігайте копію на іншому пристрої:
docker compose down
sudo tar czf jellyfin-config-$(date +%F).tgz -C ~/jellyfin config
docker compose up -d/cache та папка transcode є тимчасовими. Медіафайли на /mnt/media резервуйте окремо або вважайте такими, що підлягають повторному рипуванню — через великий обсяг більшість обирає другий варіант. Оновлення є docker compose pull && docker compose up -d; тег :10 залишається в межах мажорної версії 10.x, тому перехід на наступну мажорну версію потребує навмисної зміни тегу. Перед зміною перегляньте release notes Jellyfin, оскільки міграція схеми бібліотеки відбувається під час переходу на мажорні версії.
Режими відмови та відповідні повідомлення
Бібліотека порожня після сканування. У журналі Dashboard → Logs (або ~/jellyfin/config/log/log_*.log) відображається:
System.UnauthorizedAccessException: Access to the path '/media/Movies' is denied.UID контейнера не має прав на читання цього шляху. Причина: медіафайли належать root або іншому UID, відмінному від вашого значення user:; у директорії відсутній біт виконання (execute bit); або батьківський монтований розділ недоступний для цього UID. Виправлення: chown -R 1000:1000 /mnt/media, директорії 755, файли 644, потім повторно запустіть сканування.
Відтворення навантажує CPU та буферизує. docker stats jellyfin показує завантаження CPU, близьке до 100% на кожне ядро, а в Dashboard → Playback сесія позначена як Transcode зі швидкістю нижче 1.0x. Клієнт не використовує direct-play, тому VPS виконує CPU-транскодування повільніше за реальний час, що призводить до втрати синхронізації. Причина: непідтримуваний кодек або контейнер, вбудовування субтитрів (burn-in) або HDR tone-mapping. Виправлення: використовуйте клієнт із підтримкою direct-play, зберігайте джерела у форматі H.264/AAC, використовуйте текстові субтитри (SRT) замість графічних (PGS/VOBSUB), які потребують вбудовування, і повністю уникніть використання 4K HDR на пристроях лише з CPU.
"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 — це найпростіший безпечний вибір для домашнього використання. Вказуйте додаткам публічну адресу безпосередньо — функція autodiscovery використовує широкомовне оповіщення в локальній мережі, тому вона не працює для клієнтів через інтернет.
Скільки дискового простору та трафіку потрібно для Jellyfin VPS?
Обсяг диска залежить від якості: закладайте 4-15 GB на один стиснутий фільм 1080p, 20-40 GB на remux та 40-100 GB для 4K; тому більшості бібліотек потрібен блок об'єму на 2-4 TB. Пропускна здатність визначається бітрейтом при direct-play: 8-12 Mbps для потоку 1080p, значно більше для 4K. Переконайтеся, що швидкість порту дозволяє обслуговувати певну кількість одночасних глядачів, і стежте за місячним лімітом трафіку. Додайте запас потужності CPU, якщо плануєте транскодування; якщо плануєте direct-play, пріоритет віддавайте пропускній здатності, а не ядрам.
Чи законно запускати Jellyfin на VPS?
Jellyfin — це безкоштовне програмне забезпечення з відкритим кодом, його використання є цілком законним. Важливим є контент: транслюйте лише ті медіафайли, які ви володієте або на які маєте ліцензію (ваші власні рипи з дисків, записи або файли, на які у вас є права). Jellyfin не містить медіафайлів і не надає способів їх отримання; це плеєр для вашої власної бібліотеки.