VPS पर Jellyfin कैसे सेटअप करें
Docker में Jellyfin चलाएं। Media permissions और CPU transcoding की समस्याओं को हल करने के लिए यह guide देखें और अपना media server सेटअप करें।
आप क्या बना रहे हैं
एक VPS पर Jellyfin media server: एक container, तीन volumes, और एक block-storage disk जिसमें आपकी films और shows होंगे, जिसे किसी भी browser या Jellyfin app से एक्सेस किया जा सकेगा। इसका installation एक fifteen-line compose file है। इसके बाद होने वाली अधिकांश समस्याओं के दो मुख्य कारण होते हैं — वे file permissions जिन्हें container पढ़ नहीं पाता, और एक GPU-less VPS से ऐसा video transcode करने को कहना जिसके लिए वह सक्षम नहीं है। यह guide मुख्य रूप से इन्हीं दो विषयों पर केंद्रित है, क्योंकि अधिकांश support tickets इन्हीं से संबंधित होते हैं।
Jellyfin पूरी तरह से free और open source है। इसमें कोई account, कोई paywalled features, और कोई telemetry नहीं है — यही कारण है कि यह things worth self-hosting in 2026 की लगभग हर list में शामिल है। यह आपके द्वारा owned media को play करता है। यह कोई content प्रदान नहीं करता है, और यह guide content प्राप्त करने के बारे में नहीं है।
Transcoding की वास्तविकता, कुछ भी किराए पर लेने से पहले
इसे सबसे पहले पढ़ें, क्योंकि यह आपकी खरीदारी के निर्णय को बदल सकता है। जब आप play दबाते हैं, तो एक media server दो में से एक काम करता है। Direct play फ़ाइल को उसके मूल रूप में स्ट्रीम करता है: VPS डिस्क से bytes पढ़ता है और उन्हें भेज देता है, जिसमें CPU का उपयोग न के बराबर होता है। Transcoding वीडियो को चलते हुए re-encode करता है — जैसे नया resolution, नया codec, या subtitles को video में जोड़ना — और यह पूरी तरह से CPU का काम है।
एक सामान्य VPS में GPU नहीं होता है। इसलिए हर transcode libx264/libx265 के साथ CPU पर चलता है, और software encoding काफी महंगा पड़ता है। एक अकेला 1080p H.264 transcode कई shared vCPUs को पूरी तरह उपयोग कर सकता है; 4K या HEVC transcode आमतौर पर real time के साथ तालमेल नहीं बिठा पाता, जिससे playback रुक जाता है और लगातार buffer होता है। Hardware transcoding — जो Intel iGPU या Nvidia card वाले home box पर इसे सस्ता बनाता है — आपके लिए उपलब्ध नहीं है, जब तक कि आपका provider GPU instances किराए पर न दे।
इसलिए VPS पर पूरी रणनीति यह है: transcoding से बचें। अपनी library को ऐसे codecs में रखें जिन्हें आपके clients natively चला सकें — H.264 video, AAC या AC3 audio, MP4 या MKV container में — और ऐसे client apps चुनें जो direct-play कर सकें: Android TV, iOS और Roku के लिए native Jellyfin apps, साथ ही Infuse, Kodi, और desktop Jellyfin Media Player। यदि आप ऐसा करते हैं, तो VPS को कभी ffmpeg की आवश्यकता नहीं होगी, और एक साधारण 2 vCPU वाला box एक साथ कई लोगों को stream कर सकता है। यदि आप transcoding की योजना बनाते हैं, तो आपको बहुत बड़े और महंगे box की आवश्यकता होगी, और तब भी 4K एक बुरा विकल्प है।
Bandwidth का हिसाब भी लगाएं, क्योंकि यह एक और बड़ा सरप्राइज है। Direct play फ़ाइल को उसके अपने bitrate पर भेजता है। एक compressed 1080p फ़ाइल 8-12 Mbps पर चलती है; एक 1080p Blu-ray remux 20-30 Mbps; 4K HDR 40-80 Mbps। 10 Mbps वाली फ़ाइलें direct-play करने वाले तीन लोग आपके VPS से 30 Mbps का निरंतर upload लेंगे। अपने plan में दो numbers चेक करें: port speed (क्या यह 30 Mbps upstream भेज सकता है?) और monthly transfer cap। 10 Mbps वाली दो घंटे की एक फ़ाइल लगभग 9 GB होती है, इसलिए 1 TB/month की सीमा में महीने में लगभग सौ से अधिक ऐसी फ़िल्में — दिन में तीन या चार — आ सकती हैं — और 4K देखने वाला परिवार, जो चार से आठ गुना अधिक bitrate का उपयोग करता है, इसे बहुत तेज़ी से समाप्त कर देगा।
Prerequisites
- Ek naya Ubuntu 24.04 KVM VPS jisme root ya sudo access ho, aur Docker ke saath Compose plugin installed ho.
- Media ke liye ek block-storage volume, jo aapki library ke size ke anusaar ho (niche sizing dekhein). VPS ke saath milne wala chhota root disk media ke liye upyukt nahi hai.
- Public HTTPS access ke liye ek domain name, ya phir usi VPS par WireGuard VPN agar aap sab kuch private rakhna chahte hain.
- Media jise stream karne ka aapke paas legal adhikaar ho — aapke apne rips, aapki apni recordings, ya aapki apni files.
सबसे पहले block storage को mount करें
अपने provider के panel में volume को attach करें, फिर उसे ढूंढें और mount करें। device name lsblk से प्राप्त करें — यह /dev/sdb या /dev/vdb जैसा कुछ होगा, root disk कभी नहीं होगा।
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 द्वारा mount करें, /dev/sdb द्वारा नहीं, क्योंकि reboot के दौरान device letters बदल जाते हैं। इससे आप गलत disk को format या mount कर सकते हैं। /etc/fstab में एक line जोड़ें:
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /mnt/media ext4 defaults,nofail 0 2sudo mount -a
df -h /mnt/medianofail महत्वपूर्ण है: इसके बिना, यदि block volume कभी detach हो जाता है, तो system boot नहीं होगा और emergency shell पर रुक जाएगा। यहाँ सबसे बड़ी गलती उस volume पर mkfs.ext4 चलाना है जिसमें पहले से data है — यह उसे wipe कर देगा। केवल नए volumes को format करें; यदि disk में पहले से ही आपकी library है, तो सीधे fstab line पर जाएँ।
Media को Jellyfin की आवश्यकता के अनुसार व्यवस्थित करें
Jellyfin, folder और file names के आधार पर metadata मैच करता है। यदि layout गलत हुआ, तो films बिना title और poster के दिखाई देंगी, या कोई episode गलत series से मैच हो सकता है। इसके लिए ठीक तीन नियम हैं: प्रत्येक movie अपने स्वयं के Name (Year) folder में होनी चाहिए और उसका filename मैच होना चाहिए; season folders का नाम Season 01 होना चाहिए, S01 नहीं; episode files में S01E01 का उपयोग करें; और specials को 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.mkvMovies पर (Year) केवल सजावट नहीं है — यह remakes के बीच अंतर स्पष्ट करता है ताकि matcher सही title चुन सके। Movies और Shows को अलग-अलग top-level folders के रूप में रखें क्योंकि प्रत्येक एक विशिष्ट content type की Jellyfin library बन जाता है, और इन्हें मिलाने से metadata provider भ्रमित हो सकता है।
Permissions: libraries के खाली होने का मुख्य कारण
यह एक गलतफहमी है जिससे लोगों का काफी समय बर्बाद होता है। official jellyfin/jellyfin image PUID/PGID environment variables को support नहीं करती है — ये LinuxServer.io image (lscr.io/linuxserver/jellyfin) के लिए हैं। official image में, आप compose में user: key का उपयोग करके user को control करते हैं। यदि आप इसे छोड़ देते हैं, तो container root के रूप में चलेगा। आप जो भी उपयोग करें, नियम समान है: container जिस uid/gid पर चलता है, उसे हर media directory को read और traverse करने की अनुमति होनी चाहिए।
हम uid/gid 1000 के रूप में चलेंगे, जो एक stock Ubuntu box पर पहला non-root user है। अपना uid/gid confirm करें और ownership सेट करें:
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 ~/jellyfinDirectories को केवल read ही नहीं, बल्कि execute bit (755 में x) की भी आवश्यकता होती है — इसके बिना container folder के अंदर नहीं जा सकता, भले ही वह नाम list कर सके। पूरी library को खाली करने वाली समस्या parent directory है: यदि container का uid mount को traverse नहीं कर सकता, तो वह /media/Movies या /media/Shows तक नहीं पहुँच पाएगा, और log में Access to the path ... is denied के साथ पूरी library एक साथ खाली दिखाई देगी। जिस भी single media folder को वह read नहीं कर सकता, उसे log किया जाता है और skip कर दिया जाता है। इसलिए, root के रूप में copy की गई files की batch library से गायब हो जाती है। यही कारण है कि हम केवल एक folder को ठीक करने के बजाय, recursively chown करते हैं और हर directory पर execute bit सेट करते हैं।
The docker-compose file
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.comLine by line: user: "1000:1000" वास्तव में file permissions सेट करता है, जो ऊपर दिए गए ownership से मेल खाता है। /config पूरे server को संभालता है — accounts, libraries, metadata, और watch state — इसलिए इसे writable होना चाहिए और आप इसी का backup लेते हैं। /cache एक temporary working space है। Media mount को जानबूझकर :ro (read-only) रखा गया है: Jellyfin डिफ़ॉल्ट रूप से artwork और metadata को /config के अंतर्गत store करता है, इसलिए इसे आपकी library में write करने की आवश्यकता नहीं होती है। read-only mode आपके files को accidental delete या किसी खराब plugin से बचाता है। Port को जानबूझकर 127.0.0.1 से bind किया गया है — Jellyfin का web login plain HTTP है, इसलिए हम 8096 को public internet पर publish नहीं करते हैं। JELLYFIN_PublishedServerUrl वह address है जिसे server local autodiscovery के लिए advertise करता है — यह एक LAN UDP broadcast है, इसलिए internet पर मौजूद clients इसे नहीं देख पाते और केवल आपके द्वारा app में टाइप किए गए URL का उपयोग करते हैं। इसे उस address पर सेट करें जिसे clients को बताया जाना चाहिए, और remote devices पर उस URL को मैन्युअल रूप से enter करने की अपेक्षा रखें।
Compose directory से इसे start करें:
docker compose up -d
docker logs -f jellyfinFirst run: setup wizard aur aapki libraries
Port localhost se bound hai, isliye firewall mein port open karne ke bajaye apne laptop se SSH tunnel ke zariye wizard tak pahunchein:
ssh -L 8096:127.0.0.1:8096 you@your-vps-ipAb http://localhost:8096 par jayein. Wizard pehle language select karne mein madad karega, phir ek strong password ke saath admin user banane ke liye kahega — yeh account aapka server hai, isliye koi temporary password istemal na karein. Apni pehli library add karein: content type Movies chunein, ise /media/Movies par point karein (yeh container ke andar ka path hai, host path nahi), aur yahi process Shows ke liye /media/Shows par dohraayein. Process poora karein, aur Jellyfin scan shuru kar dega. Agar library chhoti hai, to ek-do minute mein posters aur titles dikhne lagenge. Libraries ko baad mein Dashboard → Libraries mein add ya edit kar sakte hain, aur Scan All Libraries se rescan kar sakte hain.
Agar aap transcoding ka istemal karte hain, to Dashboard → Playback → Transcoding kholein aur transcode temp path ko /cache/transcodes par set karein. Isse temporary files cache volume mein rahengi aur /config bharne se bach jayengi. Hardware acceleration ko None par hi rehne dein — acceleration ke liye koi GPU nahi hai.
Remote access: TLS reverse proxy, या VPN का उपयोग करें
बाहरी नेटवर्क से Jellyfin तक पहुँचने के दो सुरक्षित तरीके हैं, और एक असुरक्षित तरीका है जिसे आपको टालना चाहिए। असुरक्षित तरीका है port 8096 को सीधे internet पर publish करना: इससे login credentials cleartext में जाते हैं और कुछ ही घंटों में port पर brute-force attack हो सकता है।
Option A — TLS reverse proxy. Jellyfin को Traefik with automatic TLS for your Docker apps के पीछे एक subdomain पर रखें, या Let's Encrypt certificate issued by Certbot के साथ nginx के पीछे रखें। Jellyfin real-time updates के लिए WebSockets का उपयोग करता है, इसलिए proxy को upgrade headers को forward करना चाहिए। Traefik यह काम अपने आप करता है; nginx में इन्हें स्पष्ट रूप से लिखना पड़ता है, और upstream के लिए HTTP/1.1 की आवश्यकता होती है अन्यथा 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:// address पर सेट करें ताकि local autodiscovery सही URL का विज्ञापन कर सके — remote apps आपके द्वारा दिए गए address का उपयोग करते हैं — और login के विरुद्ध fail2ban to slow brute-force attempts जोड़ें। एक बार server public हो जाने के बाद, Uptime Kuma को उस URL पर point करें ताकि viewers से पहले आपको downtime की जानकारी मिल जाए।
Option B — VPN पर इसे private रखें। 8096 को बिल्कुल भी publish न करें; Jellyfin तक केवल उसी machine पर समाप्त होने वाले WireGuard tunnel के माध्यम से पहुँचें। एक household के लिए यह सबसे सरल सुरक्षित विकल्प है — कोई certificate नहीं, कोई public exposure नहीं, और कोई brute-force surface नहीं। container को tunnel address या localhost से bind करें और VPN के माध्यम से connect करें। tunnel setup के लिए WireGuard VPN setup for a private VPS देखें।
Storage sizing aur backups
File count ke bajaye quality ke hisaab se budget banayein. Compressed 1080p films har ek 4-15 GB ki hoti hain; ek 1080p remux 20-40 GB; 1080p TV ka ek season 15-40 GB; aur 4K content har film ke liye 40-100 GB hota hai. Kuch sau films aur kuch shows ki library ke liye 2-4 TB volume ki zaroorat hogi. Baad mein migration karne ke bajaye ek baar mein zyada capacity wala block volume lena sasta padta hai.
/config poore server ka state hai, isliye ise back up karna sabse zaroori hai. Iska snapshot lein ya stop-and-tar karke copy ko server se bahar rakhein:
docker compose down
sudo tar czf jellyfin-config-$(date +%F).tgz -C ~/jellyfin config
docker compose up -d/cache aur transcode folder ko discard kiya ja sakta hai. /mnt/media par maujood media ko ya toh alag se back up karein ya phir use re-rippable maanein — size ko dekhte hue zyadaatar log doosra option chunte hain. Upgrades docker compose pull && docker compose up -d hain; upar diya gaya :10 tag 10.x major version ke andar hi rehta hai, isliye agle major version par jaane ke liye jaan-boojhkar tag edit karna padta hai — badlav karne se pehle Jellyfin release notes zaroor padh lein, kyunki major versions par library schema migrations hote hain.
Failure modes, with the strings you will see
Library is empty after a scan. Dashboard → Logs (या ~/jellyfin/config/log/log_*.log) पर log यह दिखाता है:
System.UnauthorizedAccessException: Access to the path '/media/Movies' is denied.Container का uid उस path को read नहीं कर सकता। Cause: media का ownership root के पास है या आपके user: value के अलावा किसी अन्य uid के पास है, directory में execute bit missing है, या parent mount उस uid के लिए traversable नहीं है। Fix: chown -R 1000:1000 /mnt/media, directories 755, files 644, फिर rescan करें।
Playback pins the CPU and buffers. docker stats jellyfin में CPU usage आपके core count के हिसाब से 100% के पास दिखता है, और Dashboard → Playback में session की speed 1.0x से कम और status Transcode दिखता है। Client direct-play नहीं कर रहा है, इसलिए VPS real time से धीमा CPU-transcoding कर रहा है और buffering हो रही है। Cause: unsupported codec या container, subtitle burn-in, या HDR tone-mapping। Fix: direct-play client का उपयोग करें, sources को H.264/AAC में रखें, image subtitles (PGS/VOBSUB) के बजाय text subtitles (SRT) का उपयोग करें क्योंकि image subtitles burn-in के लिए मजबूर करते हैं, और 4K HDR को CPU-only box से पूरी तरह दूर रखें।
"No compatible streams are available." पूरा message आमतौर पर यह होता है: "This client isn't compatible with the media and the server isn't sending a compatible media format." Client ने source को reject कर दिया है और fallback transcode भी start नहीं हो पाया। Cause: broken ffmpeg command, unreadable file, या user profile द्वारा video conversion को block करना। Fix: Dashboard → Logs में ffmpeg line पढ़ें, confirm करें कि file play हो रही है या नहीं, यदि आप transcoding पर निर्भर हैं तो user की playback permissions चेक करें, और browser codec की समस्याओं को हटाने के लिए दूसरे client का उपयोग करके देखें।
Films have no poster or the wrong one. Metadata match नहीं हुआ। Cause: movie अपने स्वयं के Name (Year) folder में नहीं है, season folder का नाम Season 01 के बजाय S01 है, episodes S01E01 format में नहीं हैं, या year missing है। Fix: ऊपर दिए गए layout के अनुसार rename करें, फिर Refresh metadata → Replace all करें, या सही TMDB/TVDB entry के लिए किसी single item पर Identify का उपयोग करें।
FAQ
क्या VPS बिना GPU के वीडियो transcode कर सकता है?
हाँ, लेकिन केवल CPU पर, और यह महंगा होता है। एक single 1080p software transcode कई vCPUs को saturate कर सकता है। 4K या HEVC आमतौर पर real time का साथ नहीं दे पाते, जिससे playback buffer होता है। सबसे अच्छा तरीका transcoding से बचना है: अपनी library को H.264/AAC में रखें और ऐसे client apps का उपयोग करें जो direct-play करते हों, ताकि VPS केवल bytes stream करे। GPU instance तभी rent करें जब आपको वास्तव में on-the-fly transcoding की आवश्यकता हो।
scan करने के बाद मेरी Jellyfin library खाली क्यों है?
लगभग हमेशा permissions की समस्या होती है। Official jellyfin/jellyfin image उसी user: के रूप में चलती है जो आपने सेट किया है (या root), और यदि files उस uid द्वारा readable नहीं हैं, तो scan logs Access to the path ... is denied और उन्हें skip कर देता है। Ownership को chown -R 1000:1000 /mnt/media से ठीक करें, directories को execute bit (755) दें, और फिर से rescan करें — साथ ही parent directory भी चेक करें, क्योंकि यदि container का uid /mnt/media को traverse नहीं कर सकता, तो वह library folders तक नहीं पहुँच पाएगा और सब कुछ खाली दिखाई देगा। दूसरा सबसे सामान्य कारण folder layout का Jellyfin की अपेक्षा के अनुरूप न होना है।
मैं Jellyfin को remotely और safely कैसे access करूँ?
इसके दो अच्छे विकल्प हैं। Login और stream को encrypt करने के लिए इसे subdomain पर TLS reverse proxy के पीछे रखें, और fail2ban जोड़ें — port 8096 को कभी भी plain expose न करें, क्योंकि यह आपका password cleartext में भेजता है। या इसे पूरी तरह private रखें और केवल VPN के माध्यम से access करें, जो household के लिए सबसे सरल और सुरक्षित विकल्प है। Apps को सीधे public address दें — autodiscovery एक local-network broadcast है, इसलिए यह internet के माध्यम से आने वाले clients तक नहीं पहुँचता है।
Jellyfin VPS को कितनी disk और bandwidth की आवश्यकता होती है?
Disk की आवश्यकता quality पर निर्भर करती है: प्रत्येक compressed 1080p film के लिए 4-15 GB, प्रत्येक remux के लिए 20-40 GB, और 4K के लिए 40-100 GB का अनुमान लगाएं, इसलिए अधिकांश libraries के लिए 2-4 TB block volume की आवश्यकता होती है। Bandwidth direct-play bitrate द्वारा निर्धारित होती है — प्रत्येक 1080p stream के लिए 8-12 Mbps, और 4K के लिए इससे कहीं अधिक — इसलिए सुनिश्चित करें कि आपकी port speed simultaneous viewers की संख्या को संभाल सके और monthly transfer cap पर ध्यान दें। यदि आप transcode करने की योजना बना रहे हैं तो CPU headroom बढ़ाएं; यदि आप direct-play करने की योजना बना रहे हैं तो cores के बजाय bandwidth को प्राथमिकता दें।
क्या VPS पर Jellyfin चलाना legal है?
Jellyfin स्वयं एक free, open-source software है और इसे चलाना पूरी तरह से legal है। जो महत्वपूर्ण है वह content है: केवल वही media stream करें जिसके आप मालिक हैं या जिसे रखने के लिए आपके पास license है — आपके अपने disc rips, recordings, या वे files जिनका आपके पास अधिकार है। Jellyfin कोई media प्रदान नहीं करता है और न ही इसे प्राप्त करने का कोई तरीका देता है; यह आपकी पहले से मौजूद library के लिए एक player है।