Cara Pasang Jellyfin di VPS dengan Docker
Ketahui cara memasang Jellyfin di VPS menggunakan Docker. Panduan ini menyelesaikan isu keizinan fail, konfigurasi storan blok, dan masalah transkod CPU yang perlahan.
Apa yang anda sedang bina
Pelayan media Jellyfin pada VPS: satu kontena, tiga volum, dan satu cakera storan blok yang menyimpan filem dan rancangan anda, boleh diakses daripada mana-mana pelayar atau aplikasi Jellyfin. Pemasangan ini menggunakan fail compose sepanjang lima belas baris. Segala masalah yang timbul selepas itu berpunca daripada dua perkara: keizinan fail yang tidak boleh dibaca oleh kontena, dan permintaan kepada VPS tanpa GPU untuk melakukan transkod video yang tidak sepatutnya. Panduan ini menumpukan sebahagian besar kandungannya pada dua perkara tersebut, kerana di situlah punca kebanyakan tiket sokongan.
Jellyfin adalah percuma dan sumber terbuka sepenuhnya, tanpa akaun, tanpa ciri berbayar, dan tanpa telemetri; itulah sebabnya ia tersenarai dalam hampir setiap senarai perkara yang berbaloi untuk di-self-host pada tahun 2026. Ia memainkan media milik anda. Ia tidak membekalkan sebarang kandungan, dan panduan ini bukan mengenai cara untuk memperoleh kandungan tersebut.
Realiti transkod, sebelum anda menyewa apa-apa
Baca ini dahulu, kerana ia mengubah apa yang anda beli. Pelayan media melakukan salah satu daripada dua perkara apabila anda menekan butang main. Direct play menstrim fail seperti sedia ada: VPS membaca bait daripada cakera dan menolaknya melalui rangkaian, yang hampir tidak menggunakan CPU. Transcoding mengekod semula video secara langsung (on the fly), dengan resolusi baharu, codec baharu, atau sari kata yang dibakar masuk (burned in), dan ini merupakan kerja CPU sepenuhnya.
VPS biasa tidak mempunyai GPU. Jadi, setiap transkod dijalankan pada CPU dengan libx264/libx265, dan pengekodan perisian adalah mahal. Satu transkod 1080p H.264 boleh memenuhkan beberapa vCPU kongsi; transkod 4K atau HEVC biasanya tidak mampu mengejar masa nyata, jadi main balik akan terhenti dan menimbal (buffer) selama-lamanya. Transkod perkakasan, perkara yang menjadikannya murah pada kotak rumah dengan iGPU Intel atau kad Nvidia, tidak tersedia kepada anda melainkan penyedia anda menyewakan instans GPU.
Oleh itu, keseluruhan strategi pada VPS adalah: elakkan transcoding. Simpan pustaka anda dalam codec yang dimainkan secara natif oleh klien anda, video H.264, audio AAC atau AC3, dalam bekas MP4 atau MKV, dan pilih aplikasi klien yang menyokong direct-play: aplikasi natif Jellyfin untuk Android TV, iOS dan Roku, serta Infuse, Kodi, dan Jellyfin Media Player desktop. Lakukan itu dan VPS tidak akan menyentuh ffmpeg, dan kotak 2 vCPU yang sederhana boleh menstrim kepada beberapa orang serentak. Jika anda merancang untuk melakukan transkod, anda memerlukan kotak yang jauh lebih besar dan mahal, dan walaupun begitu, 4K adalah pertaruhan yang buruk.
Buat pengiraan lebar jalur juga kerana aspek ini sering mengejutkan. Main terus menghantar fail pada kadar bit asalnya. Fail 1080p termampat menggunakan 8-12 Mbps; remux Blu-ray 1080p menggunakan 20-30 Mbps; HDR 4K menggunakan 40-80 Mbps. Tiga orang yang memainkan terus fail 10 Mbps menggunakan 30 Mbps muat naik berterusan daripada VPS anda. Semak dua nombor pada pelan anda: kelajuan port (bolehkah port itu menghantar 30 Mbps ke hulu?) dan had pemindahan bulanan. Filem 10 Mbps selama dua jam menghasilkan kira-kira 9 GB trafik keluar, jadi kuota bermeter 1 TB/bulan hanya membenarkan sedikit lebih daripada seratus filem sedemikian sebulan, iaitu tiga atau empat filem sehari. Isi rumah yang menonton kandungan 4K, dengan kadar bit empat hingga lapan kali lebih tinggi, akan menghabiskan kuota itu jauh lebih cepat. Ambil kira juga apa-apa trafik lain yang keluar dari pelayan yang sama dalam belanjawan tersebut, termasuk relay RustDesk yang dihos sendiri, yang membawa keseluruhan sesi desktop jauh apabila dua peer tidak dapat bersambung secara terus.
Prasyarat
- VPS KVM Ubuntu 24.04 baharu dengan akses root atau sudo, serta Docker dan pemalam Compose yang telah dipasang.
- Storan blok (block-storage volume) untuk media, dengan saiz yang sesuai untuk pustaka anda (lihat panduan saiz di bawah). Jangan simpan fail filem pada cakera root kecil yang disertakan bersama VPS.
- Nama domain jika anda mahukan akses HTTPS awam, atau VPN WireGuard pada VPS yang sama jika anda lebih suka memastikan keseluruhan sistem kekal peribadi.
- Media yang anda mempunyai hak sah untuk distrim, hasil salinan (rip) sendiri, rakaman sendiri, atau fail milik anda.
Lekapkan storan blok terlebih dahulu
Lampirkan volum dalam panel pembekal anda, kemudian cari dan lekapkannya. Dapatkan nama peranti daripada lsblk, ia akan kelihatan seperti /dev/sdb atau /dev/vdb, jangan sekali-kali menggunakan 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 deviceLekapkan ia menggunakan UUID, bukan /dev/sdb, kerana huruf peranti boleh berubah susunan selepas but semula dan anda mungkin memformat atau melekap cakera yang salah. Tambahkan 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: tanpanya, jika volum blok ditanggalkan, pelayan akan enggan but dan masuk ke shell kecemasan. Kesilapan paling besar di sini ialah menjalankan mkfs.ext4 pada volum yang sudah mengandungi data, kerana ia akan memadamkan data tersebut. Format volum baharu sahaja; jika cakera tersebut sudah mengandungi pustaka anda, terus langkau ke baris fstab.
Susun media mengikut jangkaan Jellyfin
Jellyfin memadankan metadata berdasarkan nama folder dan fail. Jika susun atur salah, filem akan muncul sebagai fail tanpa tajuk dan poster, atau episod dipadankan dengan siri yang salah. Terdapat tiga peraturan utama: setiap filem mesti berada dalam folder Name (Year) sendiri dengan nama fail yang sepadan; folder musim dinamakan Season 01, bukan S01; fail episod menggunakan S01E01; dan episod khas 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 membezakan pembikinan semula (remake) supaya sistem padanan memilih tajuk yang tepat. Pastikan Movies dan Shows sebagai folder peringkat atas yang berasingan kerana setiap satunya akan menjadi pustaka Jellyfin bagi jenis kandungan tertentu, dan mencampurkannya akan mengelirukan penyedia metadata. Jellyfin boleh mengindeks folder ketiga untuk foto, namun pengalaman penggunaannya adalah terhad berbanding pelayan foto khusus. Jika album anda penting, gunakan PhotoPrism atau Immich pada pelayan berasingan dan biarkan pelayan ini khusus untuk filem dan TV.
Kebenaran: punca utama pustaka kelihatan kosong
Ini adalah salah faham yang sering membuang masa pengguna. Imej rasmi jellyfin/jellyfin tidak mengiktiraf pemboleh ubah persekitaran PUID/PGID; pemboleh ubah tersebut adalah milik imej LinuxServer.io (lscr.io/linuxserver/jellyfin). Pada imej rasmi, anda mengawal pengguna dengan kunci user: dalam compose, dan jika anda meninggalkannya, kontena akan berjalan sebagai root. Walau apa pun yang anda gunakan, peraturannya tetap sama: uid/gid yang digunakan oleh kontena mesti mempunyai kebenaran untuk membaca dan melayari setiap direktori media.
Kita akan menjalankan kontena sebagai uid/gid 1000, iaitu pengguna bukan root pertama pada sistem Ubuntu standard. Sahkan milik 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 baca. Tanpanya, kontena tidak boleh memasuki folder walaupun ia boleh menyenaraikan nama folder tersebut. Perangkap yang menyebabkan seluruh pustaka menjadi kosong ialah direktori induk: jika uid kontena tidak boleh melayari titik lekap (mount point) itu sendiri, ia tidak akan sampai ke /media/Movies atau /media/Shows, dan setiap pustaka akan kelihatan kosong serta-merta dengan Access to the path ... is denied dalam log. Mana-mana folder media yang tidak boleh dibaca akan direkodkan dalam log dan dilangkau, jadi sekumpulan fail yang disalin sebagai root akan hilang secara senyap daripada pustaka. Inilah sebabnya kita melakukan chown secara rekursif dan menetapkan bit execute pada setiap direktori dan bukannya 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" ialah arahan yang menetapkan keizinan fail, selaras dengan pemilikan di atas. /config menyimpan keseluruhan pelayan, akaun, pustaka, metadata, dan status tontonan, jadi ia mestilah boleh ditulis dan merupakan perkara yang perlu anda sandarkan. /cache ialah ruang kerja sementara. Mount media adalah :ro (baca sahaja) secara sengaja: Jellyfin secara lalai menyimpan karya seni dan metadata di bawah /config, jadi ia tidak perlu menulis ke dalam pustaka anda, dan mod baca sahaja melindungi fail anda daripada pemadaman tidak sengaja atau pemalam yang bermasalah. Port diikat kepada 127.0.0.1 secara sengaja, log masuk web Jellyfin menggunakan HTTP biasa, jadi kami tidak pernah menerbitkan 8096 ke internet awam. JELLYFIN_PublishedServerUrl ialah alamat yang diiklankan oleh pelayan untuk penemuan automatik tempatan, iaitu siaran UDP LAN, jadi klien melalui internet tidak akan melihatnya dan hanya menggunakan URL yang anda taip ke dalam aplikasi. Tetapkan kepada alamat yang sepatutnya diberitahu kepada klien, dan jangkakan untuk memasukkan URL tersebut secara manual pada peranti jauh.
Jalankan servis dari direktori compose:
docker compose up -d
docker logs -f jellyfinJalankan kali pertama: wizard tetapan dan pustaka anda
Oleh kerana port terikat pada localhost, akses wizard melalui SSH tunnel dari komputer riba anda dan bukannya membuka lubang firewall:
ssh -L 8096:127.0.0.1:8096 you@your-vps-ipSekarang layari ke http://localhost:8096. Wizard akan memandu anda memilih bahasa, kemudian mencipta pengguna admin dengan kata laluan yang kuat. Akaun ini adalah pelayan anda, jadi jangan gunakan semula kata laluan pakai buang. Tambahkan pustaka pertama anda: pilih jenis kandungan Movies, halakan ia ke /media/Movies (laluan di dalam kontena, bukan laluan hos), dan ulangi langkah tersebut dengan Shows di /media/Shows. Selesaikan proses, dan Jellyfin akan melakukan imbasan. Hasil yang betul ialah poster dan tajuk akan dipaparkan dalam masa satu atau dua minit untuk pustaka yang kecil. Tambah atau edit pustaka kemudian di bawah Dashboard → Libraries, dan paksa imbasan semula dengan Scan All Libraries.
Jika anda bergantung pada sebarang transkod, buka Dashboard → Playback → Transcoding dan tetapkan laluan sementara transkod ke /cache/transcodes supaya data tersebut disimpan pada volum cache dan tidak memenuhkan /config. Biarkan pecutan perkakasan ditetapkan kepada None, kerana tiada GPU untuk melakukan pecutan.
Akses jauh: Reverse proxy TLS, atau kekalkan pada VPN
Anda mempunyai dua cara selamat untuk mencapai Jellyfin dari luar, dan satu cara tidak selamat yang perlu dielakkan. Cara yang tidak selamat ialah mendedahkan port 8096 terus ke internet: maklumat log masuk dihantar dalam teks jelas (cleartext) dan port tersebut akan diserang secara brute-force dalam masa beberapa jam.
Pilihan A, reverse proxy TLS. 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 WebSocket untuk kemas kini masa nyata, jadi proksi mesti memajukan (forward) header naik taraf (upgrade headers). Traefik melakukan ini secara automatik; nginx memerlukan header tersebut dinyatakan secara eksplisit, dan memerlukan HTTP/1.1 ke upstream atau proses naik taraf tidak akan berlaku:
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 autodiscovery tempatan mengiklankan URL yang betul, aplikasi jauh menggunakan alamat yang anda berikan, dan tambahkan fail2ban untuk melambatkan percubaan brute-force terhadap log masuk. Sebaik sahaja pelayan menjadi awam, halakan Uptime Kuma ke URL tersebut supaya anda mengetahui tentang downtime sebelum pengguna anda mengetahuinya.
Pilihan B, kekalkan secara peribadi pada VPN. Jangan dedahkan port 8096 langsung; capai Jellyfin hanya melalui terowong WireGuard yang ditamatkan pada mesin yang sama. Bagi isi rumah, ini adalah pilihan paling selamat dan ringkas, tanpa sijil, tanpa pendedahan awam, dan tanpa permukaan serangan brute-force. Ikat (bind) kontena kepada alamat terowong atau localhost dan sambung melalui VPN. Lihat persediaan VPN WireGuard untuk VPS peribadi bagi mendapatkan maklumat mengenai terowong itu sendiri.
Saiz storan dan sandaran
Tentukan bajet berdasarkan kualiti, bukan bilangan fail. Filem 1080p yang dimampatkan bersaiz 4-15 GB setiap satu; remux 1080p bersaiz 20-40 GB; satu musim siri TV 1080p bersaiz 15-40 GB; manakala kandungan 4K bersaiz 40-100 GB bagi setiap filem. Pustaka yang mengandungi beberapa ratus filem serta beberapa siri TV memerlukan volum 2-4 TB, dan adalah lebih murah untuk memperuntukkan volum blok secara berlebihan pada peringkat awal berbanding melakukan migrasi kemudian hari.
/config ialah keseluruhan keadaan pelayan, jadi ia merupakan satu-satunya perkara yang wajib anda sandarkan. Lakukan snapshot atau hentikan servis dan gunakan tar untuk menyandarkannya, kemudian simpan salinan tersebut di luar pelayan:
docker compose down
sudo tar czf jellyfin-config-$(date +%F).tgz -C ~/jellyfin config
docker compose up -d/cache dan folder transcode boleh dibuang. Media pada /mnt/media perlu disandarkan secara berasingan atau anda boleh menganggapnya sebagai data yang boleh dimuat turun semula; kebanyakan pengguna memilih pilihan kedua memandangkan saiznya yang besar. Naik taraf adalah menggunakan docker compose pull && docker compose up -d; tag :10 di atas kekal dalam versi utama 10.x, jadi beralih ke versi utama seterusnya memerlukan penyuntingan tag secara sengaja. Teliti nota keluaran Jellyfin sebelum anda melakukannya, kerana migrasi skema pustaka sering berlaku pada versi utama. Tag yang ditetapkan (pinned) berserta satu direktori keadaan yang disandarkan merupakan resipi lengkap bagi mana-mana kontena yang sentiasa berjalan, dan ia merupakan corak yang sama di sebalik mengekalkan memori dan jadual ejen yang dihoskan sendiri merentas but semula.
Mod kegagalan, berserta rentetan yang akan anda lihat
Pustaka kosong selepas imbasan. Log di Dashboard → Logs (atau ~/jellyfin/config/log/log_*.log) menunjukkan:
System.UnauthorizedAccessException: Access to the path '/media/Movies' is denied.uid kontena tidak dapat membaca laluan tersebut. Punca: media dimiliki oleh root atau uid selain daripada nilai user: anda, direktori kehilangan bit execute, atau mount induk itu sendiri tidak boleh dilalui oleh uid tersebut. Pembaikan: chown -R 1000:1000 /mnt/media, direktori 755, fail 644, kemudian imbas semula.
Main balik membebankan CPU dan menimbal (buffering). docker stats jellyfin menunjukkan CPU hampir 100% didarab dengan bilangan teras anda, dan Dashboard → Playback menyenaraikan sesi sebagai Transcode dengan kelajuan di bawah 1.0x. Pelanggan tidak melakukan direct-play, jadi VPS sedang melakukan CPU-transcoding lebih perlahan daripada masa sebenar dan gagal mengejar. Punca: codec atau kontena yang tidak disokong, pembakaran sari kata (subtitle burn-in), atau pemetaan tona HDR. Pembaikan: tukar kepada pelanggan direct-play, simpan sumber dalam H.264/AAC, gunakan sari kata teks (SRT) dan bukannya sari kata imej (PGS/VOBSUB) yang memaksa pembakaran, dan elakkan 4K HDR sepenuhnya pada kotak yang hanya menggunakan CPU.
"No compatible streams are available." Mesej penuh biasanya berbunyi "This client isn't compatible with the media and the server isn't sending a compatible media format." Pelanggan menolak sumber tersebut dan transcode sandaran juga gagal bermula. Punca: arahan ffmpeg yang rosak, fail yang tidak boleh dibaca, atau profil pengguna yang menyekat penukaran video. Pembaikan: baca baris ffmpeg dalam Dashboard → Logs, sahkan fail tersebut boleh dimainkan, semak kebenaran main balik pengguna jika anda bergantung pada transcoding, dan cuba pelanggan kedua untuk menolak kemungkinan keanehan codec pelayar.
Filem tiada poster atau poster yang 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 yang hilang. Pembaikan: namakan semula kepada susun atur di atas, kemudian Refresh metadata → Replace all, atau gunakan Identify pada satu item untuk menetapkan entri TMDB/TVDB yang betul.
FAQ
Bolehkah VPS melakukan transkod video tanpa GPU?
Boleh, tetapi hanya menggunakan CPU dan ia memakan sumber yang tinggi. Satu transkod perisian 1080p boleh membebankan beberapa vCPU, manakala 4K atau HEVC biasanya tidak dapat mengejar masa nyata, menyebabkan main balik terhenti-henti. Langkah terbaik adalah mengelakkan transkod: simpan pustaka anda dalam format H.264/AAC dan gunakan aplikasi klien yang menyokong direct-play, supaya VPS hanya menstrim bait data. Sewa instans GPU hanya jika anda benar-benar memerlukan transkod secara langsung (on-the-fly).
Mengapa pustaka Jellyfin saya kosong selepas imbasan?
Hampir selalu disebabkan oleh keizinan (permissions). Imej rasmi jellyfin/jellyfin berjalan sebagai user: yang anda tetapkan (atau root), dan jika fail tidak boleh dibaca oleh uid tersebut, log imbasan akan menunjukkan Access to the path ... is denied dan melangkau fail berkenaan. Betulkan pemilikan dengan chown -R 1000:1000 /mnt/media, berikan bit laksana (execute bit) kepada direktori (755), lakukan imbasan semula, dan periksa juga direktori induk, kerana jika uid kontena tidak boleh melayari /mnt/media itu sendiri, ia tidak akan sampai ke folder pustaka dan semuanya akan kelihatan kosong. Punca kedua paling kerap ialah susun atur folder yang tidak sepadan dengan jangkaan Jellyfin.
Bagaimanakah cara mengakses Jellyfin dari jauh dengan selamat?
Terdapat dua pilihan yang baik. Letakkan ia di belakang reverse proxy TLS pada subdomain supaya log masuk dan strim disulitkan, serta tambahkan fail2ban; jangan sekali-kali mendedahkan port 8096 secara terus kerana ia menghantar kata laluan anda dalam teks jelas (cleartext). Atau, kekalkan ia sepenuhnya peribadi dan akses hanya melalui VPN, pilihan paling selamat dan mudah untuk kegunaan isi rumah. Berikan alamat awam secara terus kepada aplikasi; autodiscovery adalah siaran rangkaian tempatan (local-network broadcast), jadi ia tidak akan sampai kepada klien yang masuk melalui internet.
Berapakah ruang cakera dan lebar jalur yang diperlukan oleh VPS Jellyfin?
Ruang cakera bergantung pada kualiti: peruntukkan 4-15 GB bagi setiap filem 1080p yang dimampatkan, 20-40 GB bagi setiap remux, dan 40-100 GB bagi 4K, jadi kebanyakan pustaka memerlukan volum blok 2-4 TB. Lebar jalur ditentukan oleh kadar bit direct-play, iaitu 8-12 Mbps bagi setiap strim 1080p, dan jauh lebih tinggi bagi 4K, jadi pastikan kelajuan port anda mampu menampung jumlah penonton serentak dan pantau had pemindahan bulanan. Tambahkan kapasiti CPU jika anda bercadang untuk melakukan transkod; utamakan lebar jalur berbanding teras (cores) jika anda bercadang untuk menggunakan direct-play.
Adakah sah di sisi undang-undang untuk menjalankan Jellyfin pada VPS?
Jellyfin sendiri adalah perisian sumber terbuka percuma dan menjalankannya adalah sah sepenuhnya. Perkara yang penting ialah kandungan: strim hanya media yang anda miliki atau dilesenkan untuk disimpan, salinan cakera (rip) anda sendiri, rakaman, atau fail yang anda mempunyai hak untuk menggunakannya. Jellyfin tidak menyertakan sebarang media dan tidak menyediakan cara untuk mendapatkannya; ia hanyalah pemain untuk pustaka yang sudah anda miliki.