cara pasang Jellyfin pada VPS guna Docker
Panduan pasang Jellyfin dalam Docker pada VPS. Pelajari cara urus storan blok, isu keizinan fail, dan cara elak masalah CPU transcoding tanpa GPU.
Apa yang anda bina
Pelayan media Jellyfin pada VPS: satu bekas (container), tiga volum, dan satu cakera storan blok yang menyimpan filem serta rancangan anda, yang boleh dicapai melalui mana-mana pelayar atau aplikasi Jellyfin. Pemasangan ini hanya menggunakan fail compose sebanyak lima belas baris. Segala masalah yang timbul selepas itu berpunca daripada dua perkara — keizinan fail (file permissions) yang tidak boleh dibaca oleh bekas, dan meminta VPS tanpa GPU untuk melakukan transkod video yang tidak sepatutnya dilakukan. Panduan ini menumpukan sebahagian besar kandungan pada dua perkara tersebut kerana itulah punca utama tiket sokongan.
Jellyfin adalah percuma dan sumber terbuka sepenuhnya, tanpa akaun, tanpa ciri berbayar, dan tanpa telemetri — sebab itulah ia disenaraikan dalam hampir setiap senarai perkara yang berbaloi untuk self-host pada 2026. Ia memainkan media milik anda. Ia tidak menyediakan sebarang kandungan, dan panduan ini bukan mengenai cara mendapatkan kandungan tersebut.
Realiti transcoding, sebelum anda menyewa apa-apa
Baca ini terlebih dahulu kerana ia mengubah pilihan pembelian anda. Pelayan media melakukan salah satu daripada dua perkara apabila anda menekan butang main. Direct play menstrim fail secara asal: VPS membaca bait daripada cakera dan menghantarnya melalui rangkaian, yang hampir tidak menggunakan CPU. Transcoding menyusun semula kod video secara langsung — resolusi baharu, codec baharu, atau sari kata yang digabungkan — dan itu adalah kerja CPU sepenuhnya.
VPS tipikal tidak mempunyai GPU. Oleh itu, setiap transcoding dijalankan pada CPU dengan libx264/libx265, dan pengekodan perisian adalah mahal. Satu transcoding 1080p H.264 boleh memenuhkan beberapa vCPU kongsi; transcoding 4K atau HEVC biasanya tidak dapat mengekalkan masa nyata, menyebabkan tontonan terhenti dan mengalami penimbalan (buffering) berterusan. Transcoding perkakasan — perkara yang menjadikannya murah pada komputer rumah dengan Intel iGPU atau kad Nvidia — tidak tersedia untuk anda melainkan penyedia anda menyewakan instans GPU.
Oleh itu, strategi utama pada VPS adalah: elakkan transcoding. Simpan perpustakaan anda dalam codec yang boleh dimainkan secara asli oleh klien anda — video H.264, audio AAC atau AC3, dalam bekas MP4 atau MKV — dan pilih aplikasi klien yang menyokong direct-play: aplikasi Jellyfin asli untuk Android TV, iOS dan Roku, serta Infuse, Kodi, dan Jellyfin Media Player desktop. Jika anda melakukannya, VPS tidak akan menggunakan ffmpeg, dan pelayan 2 vCPU yang sederhana boleh menstrim kepada beberapa orang secara serentak. Jika anda merancang untuk melakukan transcoding, anda memerlukan pelayan yang jauh lebih besar dan mahal, dan walaupun begitu, 4K adalah pilihan yang berisiko.
Kira juga penggunaan jalur lebar, kerana ia adalah kejutan yang lain. Direct play menghantar fail pada bitrate asalnya. Fail 1080p yang dimampatkan berjalan pada 8-12 Mbps; remux Blu-ray 1080p pada 20-30 Mbps; 4K HDR pada 40-80 Mbps. Tiga orang yang melakukan direct-play fail 10 Mbps memerlukan 30 Mbps muat naik berterusan daripada VPS anda. Semak dua nombor pada pelan anda: kelajuan port (bolehkah ia menghantar 30 Mbps ke atas?) dan had pemindahan bulanan. Satu filem 10 Mbps berdurasi dua jam adalah sekitar 9 GB, jadi had 1 TB/bulan bermaksud anda hanya boleh menonton sekitar seratus filem sebulan — tiga atau empat sehari — dan isi rumah yang menonton 4K, pada empat hingga lapan kali ganda bitrate, akan menghabiskan kuota tersebut jauh lebih cepat.
Prasyarat
- VPS Ubuntu 24.04 KVM yang baru dengan akses root atau sudo, serta Docker dan plugin Compose yang telah dipasang.
- Volume storan blok untuk media, saiz mengikut perpustakaan anda (rujuk saiz di bawah). Cakera root kecil yang disertakan dengan VPS bukan tempat untuk menyimpan filem anda.
- Nama domain jika anda mahukan akses HTTPS awam, atau WireGuard VPN pada VPS yang sama jika anda mahu mengekalkan semuanya secara peribadi.
- Media yang anda mempunyai hak undang-undang untuk strim — hasil rakaman sendiri, rakaman sendiri, atau fail milik anda.
Pasang storan blok terlebih dahulu
Lampirkan volum dalam panel pembekal anda, kemudian cari dan pasang volum tersebut. Dapatkan nama peranti daripada lsblk — ia akan kelihatan seperti /dev/sdb atau /dev/vdb, bukannya cakera root.
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 devicePasang menggunakan UUID, bukan menggunakan /dev/sdb, kerana huruf peranti akan berubah selepas but semula dan anda mungkin memformat atau memasang cakera yang salah. Tambah satu baris ke dalam /etc/fstab:
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /mnt/media ext4 defaults,nofail 0 2sudo mount -a
df -h /mnt/medianofail adalah penting: tanpa baris ini, jika volum blok dilepaskan, sistem akan gagal but semula dan masuk ke shell kecemasan. Kesilapan terbesar di sini adalah menjalankan mkfs.ext4 pada volum yang sudah mempunyai data — ia akan memadamkan semua data tersebut. Format volum baharu sahaja; jika cakera sudah mempunyai perpustakaan anda, teruskan ke baris fstab.
Susun media mengikut format Jellyfin
Jellyfin memadankan metadata berdasarkan nama folder dan fail. Susunan yang salah akan menyebabkan filem muncul sebagai fail tanpa tajuk dan tanpa poster, atau episod tidak sepadan dengan siri yang betul. Terdapat tiga peraturan utama: setiap filem mesti berada dalam folder Name (Year) sendiri dengan nama fail yang sepadan; folder musim mesti dinamakan Season 01, bukan S01; fail episod mesti menggunakan S01E01; dan kandungan khas mesti diletakkan dalam 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) pada filem bukan sekadar hiasan — ia bertujuan membezakan filem remake supaya pemadanan tajuk adalah tepat. Kekalkan Movies dan Shows sebagai folder peringkat teratas yang berasingan kerana setiap satu akan menjadi perpustakaan Jellyfin bagi jenis kandungan yang spesifik, dan mencampurkannya akan mengelirukan pembekal metadata.
Kebenaran: punca utama perpustakaan tidak memaparkan kandungan
Ini adalah salah faham yang membuang masa pengguna. Imej jellyfin/jellyfin rasmi tidak menyokong pemboleh ubah persekitaran PUID/PGID — pemboleh ubah tersebut adalah milik imej LinuxServer.io (lscr.io/linuxserver/jellyfin). Pada imej rasmi, anda mengawal pengguna menggunakan kunci user: dalam compose, dan jika anda mengabaikannya, kontena akan berjalan sebagai root. Walau apa pun imej yang anda gunakan, peraturannya tetap sama: uid/gid yang digunakan oleh kontena mesti mempunyai kebenaran untuk membaca dan melintasi setiap direktori media.
Kita akan berjalan sebagai uid/gid 1000, iaitu pengguna bukan root pertama pada sistem Ubuntu standard. Sahkan uid anda dan tetapkan pemilikan:
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 ~/jellyfinDirektori memerlukan bit execute (x dalam 755), bukan sekadar bit baca — tanpa bit ini, kontena tidak dapat masuk ke dalam folder walaupun ia boleh menyenaraikan nama fail. Kesilapan yang menyebabkan seluruh perpustakaan kosong adalah pada direktori induk: jika uid kontena tidak boleh melintasi mount tersebut, ia tidak akan sampai ke /media/Movies atau /media/Shows, dan setiap perpustakaan akan menjadi kosong secara tiba-tiba dengan ralat Access to the path ... is denied dalam log. Sebarang folder media tunggal yang tidak boleh dibaca akan direkodkan dalam log dan dilewati, jadi kumpulan fail yang disalin sebagai root akan hilang daripada perpustakaan tanpa sebarang amaran. Ini sebabnya kita menggunakan chown secara rekursif dan menetapkan bit execute pada setiap direktori berbanding hanya membaiki satu folder sahaja.
Fail 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.comBaris demi baris: user: "1000:1000" menetapkan kebenaran fail, selaras dengan pemilikan di atas. /config menyimpan keseluruhan pelayan — akaun, perpustakaan, metadata, keadaan pemantauan — jadi ia mestilah boleh ditulis dan merupakan perkara yang anda sandarkan. /cache adalah ruang kerja sementara. Mount media adalah :ro (baca sahaja) dengan sengaja: Jellyfin secara lalai menyimpan seni grafik dan metadata di bawah /config, jadi ia tidak perlu menulis ke perpustakaan anda, dan mod baca sahaja melindungi fail anda daripada pemadaman tidak sengaja atau plugin yang rosak. Port diikat ke 127.0.0.1 dengan sengaja — log masuk web Jellyfin adalah HTTP biasa, jadi kita tidak akan mendedahkan 8096 ke internet awam. JELLYFIN_PublishedServerUrl adalah alamat yang diiklankan pelayan untuk penemuan automatik tempatan — siaran UDP LAN, jadi klien di internet tidak akan melihatnya dan hanya menggunakan URL yang anda taip ke dalam aplikasi. Tetapkannya kepada alamat yang perlu diberitahu kepada klien, dan bersedia untuk memasukkan URL tersebut secara manual pada peranti jauh.
Jalankan dari direktori compose:
docker compose up -d
docker logs -f jellyfinPelaksanaan pertama: wizard tetapan dan perpustakaan anda
Kerana port diikat pada localhost, akses wizard melalui terowong SSH dari komputer riba anda berbanding membuka lubang firewall:
ssh -L 8096:127.0.0.1:8096 you@your-vps-ipSekarang layari http://localhost:8096. Wizard akan membimbing anda melalui tetapan bahasa, kemudian mencipta pengguna admin dengan kata laluan yang kuat — akaun ini adalah pelayan anda, jadi jangan gunakan kata laluan sementara. Tambah perpustakaan pertama anda: pilih jenis kandungan Movies, tetapkan ke /media/Movies (laluan di dalam kontena, bukan laluan hos), dan ulangi dengan Shows pada /media/Shows. Selesaikan proses, dan Jellyfin akan melakukan imbasan. Hasil yang betul adalah poster dan tajuk muncul dalam masa satu atau dua minit untuk perpustakaan kecil. Tambah atau edit perpustakaan kemudian di bawah Dashboard → Libraries, dan paksa imbasan semula dengan Scan All Libraries.
Jika anda menggunakan sebarang transcoding, buka Dashboard → Playback → Transcoding dan tetapkan laluan tempoh transcode ke /cache/transcodes supaya beban kerja tersebut masuk ke volum cache dan bukannya memenuhi /config. Biarkan pecutan perkakasan ditetapkan pada None — tiada GPU untuk melakukan pecutan.
Akses jauh: TLS reverse proxy, atau kekal pada VPN
Anda mempunyai dua cara selamat untuk mengakses Jellyfin dari luar, dan satu cara tidak selamat yang perlu dielakkan. Cara tidak selamat adalah mendedahkan port 8096 terus ke internet: maklumat log masuk dihantar dalam teks biasa dan port tersebut akan diserang secara brute-force dalam masa beberapa jam.
Pilihan A — TLS reverse proxy. Letakkan Jellyfin pada subdomain di belakang Traefik dengan TLS automatik untuk aplikasi Docker anda, atau di belakang nginx dengan sijil Let's Encrypt yang dikeluarkan oleh Certbot. Jellyfin menggunakan WebSockets untuk kemas kini masa nyata, jadi proxy mesti memajukan upgrade headers. Traefik melakukan ini secara automatik; nginx memerlukan ia dinyatakan secara eksplisit, dan memerlukan HTTP/1.1 ke upstream supaya upgrade dapat dilakukan:
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";
}Tetapkan JELLYFIN_PublishedServerUrl kepada alamat https:// supaya sebarang penemuan automatik tempatan mengiklankan URL yang betul — aplikasi jauh menggunakan alamat yang anda berikan — dan tambah fail2ban untuk melambatkan percubaan brute-force terhadap log masuk. Sebaik sahaja pelayan menjadi awam, halakan Uptime Kuma ke URL tersebut supaya anda mengetahui tentang gangguan perkhidmatan sebelum penonton anda tahu.
Pilihan B — kekal peribadi pada VPN. Jangan dedahkan 8096 sama sekali; akses Jellyfin hanya melalui terowong WireGuard yang berakhir pada mesin yang sama. Untuk kegunaan isi rumah, ini adalah pilihan selamat yang paling mudah — tiada sijil, tiada pendedahan awam, tiada permukaan serangan brute-force. Ikat container kepada alamat terowong atau localhost dan sambung melalui VPN. Rujuk Tetapan VPN WireGuard untuk VPS peribadi untuk konfigurasi terowong itu sendiri.
Saiz storan dan sandaran
Bajet berdasarkan kualiti, bukan bilangan fail. Filem 1080p yang dimampatkan berukuran 4-15 GB setiap satu; remux 1080p berukuran 20-40 GB; satu musim TV 1080p berukuran 15-40 GB; apa-apa kandungan 4K berukuran 40-100 GB setiap filem. Koleksi beberapa ratus filem berserta beberapa rancangan memerlukan volum 2-4 TB, dan adalah lebih murah untuk menyediakan volum blok yang lebih besar sekali gus daripada melakukan migrasi kemudian hari.
/config adalah keseluruhan keadaan pelayan, jadi ia adalah satu-satunya perkara yang wajib anda sandarkan. Gunakan snapshot atau gunakan kaedah stop-and-tar dan simpan salinan tersebut di luar peranti:
docker compose down
sudo tar czf jellyfin-config-$(date +%F).tgz -C ~/jellyfin config
docker compose up -d/cache dan folder transcode adalah boleh dibuang. Media pada /mnt/media perlu disandarkan secara berasingan atau diterima sebagai fail yang boleh di-ripp semula — kebanyakan orang memilih pilihan kedua memandangkan saiznya. Naik taraf adalah docker compose pull && docker compose up -d; tag :10 di atas kekal dalam versi utama 10.x, jadi beralih ke versi utama seterusnya memerlukan suntingan tag secara sengaja — semak nota keluaran Jellyfin sebelum anda melakukannya, kerana migrasi skema perpustakaan berlaku pada versi utama.
Mod kegagalan, dengan rentetan yang akan anda lihat
Library kosong selepas imbasan. Log pada Dashboard → Logs (atau ~/jellyfin/config/log/log_*.log) menunjukkan:
System.UnauthorizedAccessException: Access to the path '/media/Movies' is denied.uid kontena tidak boleh membaca laluan tersebut. Punca: media dimiliki oleh root atau uid selain daripada nilai user: anda, direktori kehilangan bit execute, atau mount induk tidak boleh dilalui oleh uid tersebut. Penyelesaian: chown -R 1000:1000 /mnt/media, direktori 755, fail 644, kemudian imbas semula.
Playback menyebabkan CPU tinggi dan buffering. docker stats jellyfin menunjukkan CPU hampir 100% gandaan bilangan teras anda, dan Dashboard → Playback menyenaraikan sesi sebagai Transcode dengan kelajuan di bawah 1.0x. Klien tidak melakukan direct-play, maka VPS melakukan CPU-transcoding lebih lambat daripada masa nyata dan mengalami kegagalan. Punca: codec atau kontena tidak disokong, burn-in sari kata, atau HDR tone-mapping. Penyelesaian: tukar kepada klien direct-play, simpan sumber dalam H.264/AAC, gunakan sari kata text (SRT) berbanding sari kata image (PGS/VOBSUB) yang memaksa burn-in, dan jangan gunakan 4K HDR pada peranti CPU-only sepenuhnya.
"No compatible streams are available." Mesej penuh biasanya ialah "This client isn't compatible with the media and the server isn't sending a compatible media format." Klien menolak sumber dan transcode fallback juga gagal dimulakan. Punca: arahan ffmpeg yang rosak, fail tidak boleh dibaca, atau profil pengguna menyekat penukaran video. Penyelesaian: baca baris ffmpeg dalam Dashboard → Logs, sahkan fail boleh dimainkan, semak kebenaran playback pengguna jika anda bergantung pada transcoding, dan cuba klien kedua untuk menolak masalah codec pelayar.
Filem tiada poster atau poster salah. Metadata tidak sepadan. Punca: filem tidak berada dalam folder Name (Year) sendiri, folder musim dinamakan S01 dan bukannya Season 01, episod tidak dalam bentuk S01E01, atau tahun hilang. Penyelesaian: namakan semula mengikut susun atur di atas, kemudian Refresh metadata → Replace all, atau gunakan Identify pada item tunggal untuk menetapkan entri TMDB/TVDB yang betul.
FAQ
Bolehkah VPS melakukan transcode video tanpa GPU?
Boleh, tetapi hanya menggunakan CPU, dan ia adalah mahal. Satu transcode perisian 1080p boleh memenuhkan beberapa vCPU, manakala 4K atau HEVC biasanya tidak dapat mengekalkan masa nyata, menyebabkan penimbalan (buffering) semasa main balik. Langkah terbaik adalah mengelakkan transcode: simpan perpustakaan anda dalam format H.264/AAC dan gunakan aplikasi klien yang menyokong direct-play, supaya VPS hanya menghantar aliran data. Sewa instans GPU hanya jika anda benar-benar memerlukan transcode secara langsung (on-the-fly).
Mengapa perpustakaan Jellyfin saya kosong selepas imbasan?
Hampir sentiasa disebabkan oleh keizinan (permissions). Imej jellyfin/jellyfin rasmi berjalan sebagai user: yang anda tetapkan (atau root), dan jika fail tidak boleh dibaca oleh uid tersebut, log imbasan Access to the path ... is denied dan melangkau fail tersebut. Baiki pemilikan dengan chown -R 1000:1000 /mnt/media, berikan bit execute pada direktori (755), dan imbas semula — semak juga direktori induk, kerana jika uid kontena tidak boleh melintasi /mnt/media itu sendiri, ia tidak akan sampai ke folder perpustakaan dan semuanya akan kelihatan kosong. Punca kedua yang paling biasa adalah susun atur folder yang tidak sepadan dengan jangkaan Jellyfin.
Bagaimanakah cara untuk mengakses Jellyfin secara jauh dan selamat?
Dua pilihan yang baik. Letakkan ia di belakang reverse proxy TLS pada subdomain supaya log masuk dan penstriman disulitkan, dan tambah fail2ban — jangan sesekali dedahkan port 8096 biasa, kerana ia menghantar kata laluan anda dalam teks biasa. Atau, kekalkan ia sepenuhnya peribadi dan akses hanya melalui VPN, pilihan selamat yang paling mudah untuk isi rumah. Berikan alamat awam secara terus kepada aplikasi — penemuan automatik (autodiscovery) adalah siaran rangkaian tempatan, jadi ia tidak sampai kepada klien yang datang melalui internet.
Berapakah storan dan jalur lebar yang diperlukan oleh VPS Jellyfin?
Storan bergantung pada kualiti: sediakan 4-15 GB untuk setiap filem 1080p yang dimampatkan, 20-40 GB untuk setiap remux, dan 40-100 GB untuk 4K, jadi kebanyakan perpustakaan memerlukan volum blok 2-4 TB. Jalur lebar ditetapkan oleh kadar bit direct-play — 8-12 Mbps bagi setiap penstriman 1080p, jauh lebih tinggi untuk 4K — jadi pastikan kelajuan port anda mampu menampung jumlah penonton serentak dan perhatikan had pemindahan bulanan. Tambah ruang CPU jika anda merancang untuk melakukan transcode; utamakan jalur lebar berbanding teras jika anda merancang untuk melakukan direct-play.
Adakah sah untuk menjalankan Jellyfin pada VPS?
Jellyfin sendiri adalah perisian sumber terbuka yang percuma dan menjalankannya adalah sepenuhnya sah. Apa yang penting adalah kandungan: strim hanya media yang anda miliki atau mempunyai lesen untuk memegangnya — hasil rakaman cakera anda sendiri, rakaman, atau fail yang anda mempunyai hak. Jellyfin tidak membekalkan sebarang media dan tidak menyediakan cara untuk mendapatkannya; ia adalah pemain untuk perpustakaan yang anda sudah miliki.