SSD Nodes Learn
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-07-24

Cara Install Jellyfin di VPS Pakai Docker

Panduan setup Jellyfin di VPS menggunakan Docker. Pelajari solusi masalah file permissions dan kendala CPU transcoding tanpa GPU agar streaming lancar.

Apa yang Anda bangun

Sebuah media server Jellyfin pada VPS: satu container, tiga volume, dan sebuah disk block-storage untuk menyimpan film serta acara Anda, yang dapat diakses dari browser atau aplikasi Jellyfin mana pun. Proses instalasi hanya menggunakan file compose sebanyak lima belas baris. Masalah yang muncul setelahnya biasanya disebabkan oleh dua hal — izin file (file permissions) yang tidak dapat dibaca oleh container, dan penggunaan VPS tanpa GPU untuk melakukan transcoding video. Panduan ini akan fokus membahas kedua hal tersebut karena merupakan penyebab utama masalah teknis.

Jellyfin bersifat gratis dan sepenuhnya open source, tanpa akun, tanpa fitur berbayar, dan tanpa telemetri — alasan mengapa Jellyfin masuk dalam daftar hal yang layak di-self-host pada 2026. Jellyfin memutar media milik Anda. Jellyfin tidak menyediakan konten, dan panduan ini bukan tentang cara mendapatkan konten tersebut.

Realitas transcoding, sebelum Anda menyewa apa pun

Baca ini terlebih dahulu, karena ini akan mengubah pilihan pembelian Anda. Media server melakukan salah satu dari dua hal saat Anda menekan tombol play. Direct play mengirimkan file apa adanya: VPS membaca byte dari disk dan mengirimkannya melalui jaringan, sehingga hampir tidak memakan beban CPU. Transcoding melakukan encoding ulang video secara langsung — resolusi baru, codec baru, atau subtitle yang disematkan — dan ini sepenuhnya menggunakan beban CPU.

VPS standar tidak memiliki GPU. Jadi setiap proses transcode berjalan pada CPU dengan libx264/libx265, dan software encoding sangat berat. Satu transcode 1080p H.264 dapat membebani beberapa vCPU shared; transcode 4K atau HEVC biasanya tidak dapat berjalan secara real-time, sehingga pemutaran akan berhenti dan buffering terus-menerus. Hardware transcoding — fitur yang membuat proses ini murah pada perangkat rumah dengan Intel iGPU atau kartu Nvidia — tidak tersedia bagi Anda kecuali penyedia layanan menyewakan instance GPU.

Oleh karena itu, strategi utama pada VPS adalah: hindari transcoding. Simpan pustaka Anda dalam codec yang dapat diputar secara native oleh klien Anda — video H.264, audio AAC atau AC3, dalam kontainer MP4 atau MKV — dan pilih aplikasi klien yang mendukung direct-play: aplikasi Jellyfin native untuk Android TV, iOS, dan Roku, serta Infuse, Kodi, dan Jellyfin Media Player desktop. Jika Anda melakukan itu, VPS tidak akan pernah menjalankan ffmpeg, dan VPS dengan 2 vCPU sederhana dapat melakukan streaming ke beberapa orang sekaligus. Jika Anda berencana melakukan transcoding, Anda membutuhkan server yang jauh lebih besar dan lebih mahal, dan bahkan dalam kondisi tersebut, 4K tetap merupakan pilihan yang buruk.

Hitung juga penggunaan bandwidth, karena ini adalah kejutan lainnya. Direct play mengirimkan file sesuai bitrate aslinya. File 1080p yang terkompresi 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 pada file 10 Mbps akan menghabiskan 30 Mbps upload berkelanjutan dari VPS Anda. Periksa dua angka pada paket Anda: kecepatan port (apakah mampu mengirim 30 Mbps upstream?) dan batas transfer bulanan. Satu film 10 Mbps berdurasi dua jam menghabiskan sekitar 9 GB, jadi kuota 1 TB/bulan hanya cukup untuk sedikit lebih dari seratus film seperti itu per bulan — sekitar tiga atau empat film sehari — dan penggunaan 4K oleh satu rumah tangga, dengan bitrate empat hingga delapan kali lipat lebih tinggi, akan menghabiskan kuota jauh lebih cepat.

Prasyarat

  • VPS Ubuntu 24.04 KVM baru dengan akses root atau sudo, serta Docker dan plugin Compose yang sudah terinstal.
  • Volume block-storage untuk media, dengan ukuran sesuai pustaka Anda (lihat panduan ukuran di bawah). Jangan simpan film di disk root kecil bawaan VPS.
  • Nama domain jika Anda ingin akses HTTPS publik, atau WireGuard VPN pada VPS yang sama jika Anda ingin menjaga semuanya tetap privat.
  • Media yang secara hukum berhak Anda streaming — hasil rip sendiri, rekaman sendiri, atau file milik Anda sendiri.

Pasang block storage terlebih dahulu

Lampirkan volume pada panel penyedia layanan Anda, lalu cari dan pasang volume tersebut. Dapatkan nama perangkat dari lsblk — namanya akan berupa /dev/sdb atau /dev/vdb, bukan disk 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 device

Pasang menggunakan UUID, bukan /dev/sdb, karena urutan huruf perangkat dapat berubah setelah reboot dan Anda berisiko memformat atau memasang disk yang salah. Tambahkan satu baris ke /etc/fstab:

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

nofail sangat penting: tanpa baris ini, jika block volume dilepas, sistem akan gagal booting dan masuk ke emergency shell. Kesalahan terbesar adalah menjalankan mkfs.ext4 pada volume yang sudah berisi data — perintah ini akan menghapus seluruh data. Hanya format volume baru; jika disk sudah berisi library Anda, langsung saja ke baris fstab.

Atur media sesuai format Jellyfin

Jellyfin mencocokkan metadata berdasarkan nama folder dan file. Struktur yang salah menyebabkan film muncul sebagai file tanpa judul tanpa poster, atau episode tidak cocok dengan serial yang benar. Ada tiga aturan utama: setiap film berada dalam folder Name (Year) sendiri dengan nama file yang sesuai; folder musim dinamai Season 01, bukan S01; file episode menggunakan S01E01; dan konten spesial berada di 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 film bukan sekadar dekorasi — ini berfungsi untuk membedakan film remake agar pencocokan mengambil judul yang tepat. Tetap gunakan Movies dan Shows sebagai folder tingkat atas yang terpisah karena masing-masing akan menjadi pustaka Jellyfin untuk tipe konten tertentu, dan mencampurnya akan membingungkan penyedia metadata.

Permissions: alasan utama mengapa library kosong

Berikut adalah kekeliruan yang membuang waktu pengguna. Image jellyfin/jellyfin resmi tidak mendukung variabel lingkungan PUID/PGID — variabel tersebut milik image LinuxServer.io (lscr.io/linuxserver/jellyfin). Pada image resmi, Anda mengontrol pengguna menggunakan kunci user: di compose, dan jika Anda mengabaikannya, container akan berjalan sebagai root. Apa pun yang Anda gunakan, aturannya tetap sama: uid/gid tempat container berjalan harus dapat membaca dan menelusuri setiap direktori media.

Kita akan berjalan sebagai uid/gid 1000, pengguna non-root pertama pada sistem Ubuntu standar. Pastikan uid/gid Anda dan atur kepemilikannya:

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

Direktori memerlukan bit execute (x pada 755), bukan hanya read — tanpa bit ini, container tidak dapat masuk ke dalam folder meskipun dapat melihat daftar namanya. Kesalahan yang menyebabkan seluruh library kosong adalah direktori induk: jika uid container tidak dapat menelusuri mount itu sendiri, container tidak akan pernah mencapai /media/Movies atau /media/Shows, dan seluruh library akan kosong seketika dengan pesan Access to the path ... is denied di log. Setiap folder media tunggal yang tidak dapat dibaca akan dicatat di log dan dilewati, sehingga sekumpulan file yang disalin sebagai root akan hilang secara diam-diam dari library. Inilah sebabnya kita melakukan chown secara rekursif dan mengatur bit execute pada setiap direktori, alih-alih hanya memperbaiki satu folder.

File 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

Baris demi baris: user: "1000:1000" adalah bagian yang mengatur izin file, sesuai dengan kepemilikan di atas. /config menyimpan seluruh server — akun, pustaka, metadata, status pemantauan — sehingga harus dapat ditulis dan merupakan data yang Anda cadangkan. /cache adalah ruang kerja sementara. Mount media diatur ke :ro (hanya baca) dengan sengaja: Jellyfin secara default menyimpan artwork dan metadata di bawah /config, sehingga tidak perlu menulis ke pustaka Anda, dan mode hanya baca melindungi file Anda dari penghapusan tidak sengaja atau plugin yang bermasalah. Port dihubungkan ke 127.0.0.1 dengan sengaja — login web Jellyfin menggunakan HTTP biasa, jadi kita tidak mempublikasikan port 8096 ke internet publik. JELLYFIN_PublishedServerUrl adalah alamat yang diumumkan server untuk autodiscovery lokal — sebuah siaran UDP LAN, sehingga klien di internet tidak akan melihatnya dan cukup menggunakan URL yang Anda ketikkan di aplikasi. Atur ke alamat yang harus diberikan kepada klien, dan Anda harus memasukkan URL tersebut secara manual pada perangkat jarak jauh.

Jalankan dari direktori compose:

docker compose up -d
docker logs -f jellyfin

Penggunaan pertama: wizard pengaturan dan library Anda

Karena port terikat pada localhost, akses wizard melalui SSH tunnel dari laptop Anda daripada membuka celah pada firewall:

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

Sekarang buka http://localhost:8096. Wizard akan memandu Anda memilih bahasa, lalu membuat user admin dengan password yang kuat — akun ini adalah server Anda, jadi jangan gunakan password sementara. Tambahkan library pertama Anda: pilih content type Movies, arahkan ke /media/Movies (jalur di dalam container, bukan jalur host), dan ulangi untuk Shows di /media/Shows. Selesaikan prosesnya, dan Jellyfin akan melakukan pemindaian. Hasil yang benar adalah poster dan judul muncul dalam satu atau dua menit untuk library kecil. Tambahkan atau edit library nanti melalui Dashboard → Libraries, dan paksa pemindaian ulang dengan Scan All Libraries.

Jika Anda menggunakan transcoding, buka Dashboard → Playback → Transcoding dan atur transcode temp path ke /cache/transcodes agar beban kerja berada di volume cache dan tidak memenuhi /config. Biarkan hardware acceleration tetap pada None — tidak ada GPU untuk akselerasi.

Akses jarak jauh: TLS reverse proxy, atau tetap gunakan VPN

Anda memiliki dua cara aman untuk mengakses Jellyfin dari luar, dan satu cara tidak aman yang harus dihindari. Cara yang tidak aman adalah membuka port 8096 langsung ke internet: kredensial login dikirim dalam bentuk cleartext dan port tersebut akan terkena brute-force dalam hitungan jam.

Opsi A — TLS reverse proxy. Letakkan Jellyfin pada subdomain di belakang Traefik dengan TLS otomatis untuk aplikasi Docker Anda, atau di belakang nginx dengan sertifikat Let's Encrypt yang diterbitkan oleh Certbot. Jellyfin menggunakan WebSockets untuk pembaruan real-time, sehingga proxy harus meneruskan upgrade headers. Traefik melakukan ini secara otomatis; nginx memerlukan konfigurasi eksplisit, dan memerlukan HTTP/1.1 ke upstream agar upgrade berhasil:

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";
}

Atur JELLYFIN_PublishedServerUrl ke alamat https:// agar autodiscovery lokal mengiklankan URL yang benar — aplikasi jarak jauh menggunakan alamat yang Anda berikan — dan tambahkan fail2ban untuk memperlambat upaya brute-force pada login. Setelah server bersifat publik, arahkan Uptime Kuma ke URL tersebut agar Anda mengetahui downtime sebelum penonton Anda mengetahuinya.

Opsi B — tetap privat menggunakan VPN. Jangan buka port 8096 sama sekali; akses Jellyfin hanya melalui terowongan WireGuard yang berakhir pada mesin yang sama. Untuk penggunaan rumah tangga, ini adalah pilihan aman yang paling sederhana — tanpa sertifikat, tanpa eksposur publik, tanpa celah brute-force. Ikat container ke alamat terowongan atau localhost dan hubungkan melalui VPN. Lihat pengaturan WireGuard VPN untuk VPS privat untuk konfigurasi terowongan itu sendiri.

Ukuran penyimpanan dan cadangan

Hitung anggaran berdasarkan kualitas, bukan jumlah file. Film 1080p terkompresi berukuran 4-15 GB per file; remux 1080p berukuran 20-40 GB; satu musim serial TV 1080p berukuran 15-40 GB; konten 4K apa pun berukuran 40-100 GB per film. Koleksi berisi beberapa ratus film ditambah beberapa serial membutuhkan volume 2-4 TB. Lebih murah untuk menyediakan kapasitas berlebih pada block volume di awal daripada melakukan migrasi di kemudian hari.

/config adalah seluruh status server, jadi ini adalah satu hal yang wajib Anda cadangkan. Gunakan snapshot atau metode stop-and-tar, lalu simpan salinannya di luar perangkat:

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

/cache dan folder transcode bersifat opsional. Media pada /mnt/media dapat Anda cadangkan secara terpisah atau dibiarkan sebagai file yang dapat di-ripping ulang — sebagian besar orang memilih opsi terakhir karena ukurannya. Pembaruan bersifat docker compose pull && docker compose up -d; tag :10 di atas tetap berada dalam versi mayor 10.x, sehingga berpindah ke versi mayor berikutnya memerlukan pengeditan tag secara sengaja — baca catatan rilis Jellyfin sebelum melakukan perubahan, karena migrasi skema pustaka terjadi pada versi mayor.

Mode kegagalan, beserta string yang akan Anda lihat

Library kosong setelah pemindaian. Log pada Dashboard → Logs (atau ~/jellyfin/config/log/log_*.log) menunjukkan:

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

UID kontainer tidak dapat membaca path tersebut. Penyebab: media dimiliki oleh root atau UID selain nilai user: Anda, direktori kehilangan execute bit, atau mount induk tidak dapat ditelusuri oleh UID tersebut. Solusi: chown -R 1000:1000 /mnt/media, direktori 755, file 644, lalu lakukan pemindaian ulang.

Playback membebani CPU dan buffer. docker stats jellyfin menunjukkan penggunaan CPU mendekati 100% dikali jumlah core Anda, dan Dashboard → Playback mencantumkan sesi sebagai Transcode dengan kecepatan di bawah 1.0x. Client tidak melakukan direct-play, sehingga VPS melakukan CPU-transcoding lebih lambat dari waktu nyata dan mengalami penurunan performa. Penyebab: codec atau container tidak didukung, subtitle burn-in, atau HDR tone-mapping. Solusi: beralih ke client direct-play, simpan sumber dalam format H.264/AAC, gunakan subtitle text (SRT) alih-alih subtitle image (PGS/VOBSUB) yang memaksa burn-in, dan jangan gunakan 4K HDR pada perangkat yang hanya memiliki CPU.

"No compatible streams are available." Pesan lengkapnya biasanya "This client isn't compatible with the media and the server isn't sending a compatible media format." Client menolak sumber media dan fallback transcode juga gagal dimulai. Penyebab: perintah ffmpeg rusak, file tidak dapat dibaca, atau profil pengguna memblokir konversi video. Solusi: baca baris ffmpeg di Dashboard → Logs, pastikan file dapat diputar, periksa izin playback pengguna jika Anda mengandalkan transcoding, dan coba client kedua untuk memastikan bukan karena masalah codec browser.

Film tidak memiliki poster atau poster salah. Metadata tidak cocok. Penyebab: film tidak berada di dalam folder Name (Year) miliknya, folder musim bernama S01 alih-alih Season 01, episode tidak dalam format S01E01, atau tahun tidak ada. Solusi: ubah nama sesuai tata letak di atas, lalu Refresh metadata → Replace all, atau gunakan Identify pada item tunggal untuk menetapkan entri TMDB/TVDB yang benar.

FAQ

Bisakah VPS melakukan transcode video tanpa GPU?

Bisa, tetapi hanya menggunakan CPU, dan biayanya mahal. Satu proses transcode software 1080p dapat membebani beberapa vCPU. Transcode 4K atau HEVC biasanya tidak dapat berjalan secara real-time sehingga menyebabkan buffer saat pemutaran. Solusi terbaik adalah menghindari transcode: simpan pustaka Anda dalam format H.264/AAC dan gunakan aplikasi klien yang mendukung direct-play, sehingga VPS hanya mengirimkan data byte. Sewa instance GPU hanya jika Anda benar-benar membutuhkan transcode secara langsung (on-the-fly).

Mengapa pustaka Jellyfin saya kosong setelah pemindaian?

Hampir selalu karena masalah izin (permissions). Image jellyfin/jellyfin resmi berjalan menggunakan user: yang Anda tentukan (atau root). Jika file tidak dapat dibaca oleh uid tersebut, log pemindaian Access to the path ... is denied dan melewati file tersebut. Perbaiki kepemilikan dengan chown -R 1000:1000 /mnt/media, berikan bit execute pada direktori (755), lalu lakukan pemindaian ulang. Periksa juga direktori induknya, karena jika uid container tidak dapat menelusuri /mnt/media, maka container tidak akan mencapai folder pustaka dan semuanya akan kosong. Penyebab umum kedua adalah struktur folder yang tidak sesuai dengan ekspektasi Jellyfin.

Bagaimana cara mengakses Jellyfin secara jarak jauh dan aman?

Ada dua opsi yang baik. Gunakan TLS reverse proxy pada subdomain agar login dan streaming terenkripsi, lalu tambahkan fail2ban — jangan pernah mengekspos port 8096 secara terbuka karena akan mengirimkan kata sandi dalam bentuk teks biasa (cleartext). Atau, buat koneksi sepenuhnya privat dan akses hanya melalui VPN; ini adalah pilihan aman yang paling sederhana untuk penggunaan rumah tangga. Berikan alamat publik secara langsung ke aplikasi — fitur autodiscovery menggunakan broadcast jaringan lokal, sehingga tidak dapat menjangkau klien yang datang melalui internet.

Berapa kapasitas disk dan bandwidth yang dibutuhkan Jellyfin VPS?

Kapasitas disk bergantung pada kualitas: siapkan 4-15 GB per film 1080p yang sudah dikompresi, 20-40 GB per remux, dan 40-100 GB untuk 4K. Sebagian besar pustaka membutuhkan volume blok sebesar 2-4 TB. Bandwidth ditentukan oleh bitrate direct-play — 8-12 Mbps per stream 1080p, dan jauh lebih besar untuk 4K. Pastikan kecepatan port Anda mampu menangani jumlah penonton simultan dan perhatikan batas transfer bulanan. Tambahkan kapasitas CPU jika Anda berencana melakukan transcode; prioritaskan bandwidth di atas jumlah core jika Anda berencana menggunakan direct-play.

Jellyfin sendiri adalah perangkat lunak open-source gratis dan menjalankannya sepenuhnya legal. Yang penting adalah kontennya: hanya streaming media yang Anda miliki atau yang memiliki lisensi — hasil rip disc sendiri, rekaman, atau file yang Anda miliki haknya. Jellyfin tidak menyertakan media apa pun dan tidak menyediakan cara untuk mendapatkannya; Jellyfin adalah pemutar untuk pustaka yang sudah Anda miliki.

#jellyfin#media-server#docker#self-hosting#transcoding