SSD Nodes Learn 8GB RAM — $66/वर्ष
मार्गदर्शक Matt Connorद्वारे Matt Connor · अपडेटेड 2026-08-01

एकाच Docker Compose file मध्ये arr stack कसा चालवायचा

VPS वर Prowlarr, Sonarr, Radarr आणि qBittorrent चालवा. समान PUID, PGID आणि volume layout ठेवल्यास hardlinks कार्यरत राहतात आणि imports जलद होतात.

तुम्ही काय तयार करत आहात

Docker Compose arr stack हे media library व्यवस्थापित करणारे चार containers आहेत: indexer settings साठी Prowlarr, series साठी Sonarr, films साठी Radarr आणि download client म्हणून qBittorrent. हे Compose network वर service name द्वारे एकमेकांशी संवाद साधतात आणि host वरील एका folder tree ला सामायिकपणे वापरतात. Installation लहान आहे. हा stack अनेक वर्षे सुरळीत चालेल की तुम्हाला दर आठवड्याला अडचणी देईल, हे volume layout ठरवते. त्यामुळे या मार्गदर्शकाचा बहुतांश भाग त्यावर आधारित आहे.

हा stack तुमच्यासाठी content शोधत नाही. तुम्ही Prowlarr मध्ये जोडलेले indexers त्यात साठवले जातात. कोणते indexers वापरायचे हा तुमचा निर्णय आणि कायदेशीर जबाबदारी आहे. या मार्गदर्शकात users, paths, permissions, container networking आणि ते कार्यरत असल्याचे सिद्ध करणाऱ्या तपासण्यांचा समावेश आहे.

तुम्ही यापूर्वी Compose file लिहिली नसेल, तर VPS साठी Docker Compose ची मूलभूत माहिती प्रथम वाचा. या लेखात असे गृहीत धरले आहे की docker compose version तुमच्या server वर आधीच काहीतरी output दाखवते.

हार्डलिंक्स का वापर का अयशस्वी होतो आणि हाच मुख्य मुद्दा का आहे

Sonarr डाउनलोड पूर्ण झाल्यावर फाइल तुमच्या लायब्ररीमध्ये आयात करते. डाउनलोड फोल्डर आणि लायब्ररी फोल्डर एकाच फाइलसिस्टमवर असल्यास, आयात हार्डलिंकद्वारे होते: डिस्कवरील त्याच डेटाकडे निर्देश करणारे हे दुसरे नाव असते. यासाठी अतिरिक्त जागा किंवा वेळ लागत नाही. मीडिया सर्व्हर नवीन नावातून फाइल वाचत असताना torrent जुन्या नावातून seeding सुरू ठेवतो.

दोन्ही फोल्डर वेगवेगळ्या फाइलसिस्टमवर असल्यास, kernel ती लिंक तयार करू शकत नाही. Sonarr त्याऐवजी कॉपी करते. आता 40 GB च्या एका season साठी डिस्कवर 80 GB जागा आणि input आणि output साठी अनेक मिनिटे लागतात. आयात लॉगमध्ये hardlink अयशस्वी झाल्याची आणि त्याऐवजी फाइल कॉपी केल्याची नोंद होते. निश्चित डिस्क मर्यादा असलेल्या VPS वर एका आठवड्यात डिस्कची जागा संपण्याचे हेच कारण असते.

येथे एक महत्त्वाचा अडथळा आहे. Container च्या आत bind mount ही फाइलसिस्टम सीमा असते. /mnt/data/torrents ला /downloads म्हणून आणि /mnt/data/media ला /tv म्हणून mount केल्यास, दोन्ही एकाच host disk वर असले तरी Sonarr त्यांना दोन स्वतंत्र mounts म्हणून पाहतो आणि त्यांच्यामध्ये लिंक तयार करण्यास नकार देतो. अधिकृत LinuxServer.io image documentation मध्ये हे स्पष्टपणे सांगितले आहे: स्वतंत्र /downloads आणि /tv paths वापरल्यास hardlink तयार करण्याची क्षमता नष्ट होते.

यावर उपाय म्हणजे एकच mount वापरणे. Media वर काम करणाऱ्या प्रत्येक container ला /mnt/data:/data हा समान single volume द्या. त्यांनी वापरलेले प्रत्येक path त्यातील एखाद्या फोल्डरमध्ये असावे. एक mount point, एक filesystem आणि कार्यरत hardlinks.

वापरकर्ता, गट आणि फोल्डर तयार करा

कंटेनर फाइल्स PUID आणि PGID ने निश्चित केलेल्या संख्यात्मक user id म्हणून लिहितात. तुमचे स्वतःचे खाते वापरा, म्हणजे sudo शिवाय SSH द्वारे त्या फाइल्स वाचता आणि संपादित करता येतील.

id -u
id -g

नवीन Ubuntu VPS वर दोन्ही आदेश सहसा 1000 दाखवतात. आता ही संरचना तयार करा. ती तुमच्या media असलेल्या डिस्कवर ठेवा आणि संपूर्ण संरचना त्याच डिस्कवर ठेवा.

sudo mkdir -p /mnt/data/torrents/movies /mnt/data/torrents/tv
sudo mkdir -p /mnt/data/media/Movies /mnt/data/media/Shows
sudo chown -R 1000:1000 /mnt/data
sudo chmod -R 775 /mnt/data

पुढे जाण्यापूर्वी ती खरोखर एकच filesystem आहे का ते तपासा:

df --output=source,target /mnt/data/torrents /mnt/data/media

दोन्ही ओळींमध्ये तोच source device दिसला पाहिजे. दोन वेगवेगळे devices असल्यास, container config मध्ये कोणतीही सेटिंग केली तरी hardlinks कधीही कार्य करणार नाहीत.

Library folders ची नावे जाणीवपूर्वक Movies आणि Shows ठेवली आहेत. तुम्ही आधीच Jellyfin ला तुमचा media server म्हणून वापरत असल्यास, /mnt/data/media हे Jellyfin मध्ये /media म्हणून mount करा. त्यानंतर त्याच्या libraries /media/Movies आणि /media/Shows येथे येतील, म्हणजे त्या guide मध्ये दाखवल्याप्रमाणेच.

पर्यावरण फाइल

प्रत्येक सर्व्हरनुसार बदलणारी मूल्ये Compose फाइलच्या शेजारील .env मध्ये ठेवा.

mkdir -p ~/arr && cd ~/arr

~/arr/.env लिहा:

PUID=1000
PGID=1000
TZ=Etc/UTC
DATA_ROOT=/mnt/data

TZ मध्ये तुमचा स्वतःचा zone सेट करा, उदाहरणार्थ Europe/Berlin. arr applications या zone नुसार tasks schedule करतात आणि log lines वर timestamp नोंदवतात. त्यामुळे चुकीचे मूल्य पुढे प्रत्येक log गोंधळात टाकते.

Compose फाइल

~/arr/docker-compose.yml लिहा:

services:
  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    container_name: prowlarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ./config/prowlarr:/config
    ports:
      - 127.0.0.1:9696:9696
    restart: unless-stopped

  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    container_name: sonarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ./config/sonarr:/config
      - ${DATA_ROOT}:/data
    ports:
      - 127.0.0.1:8989:8989
    restart: unless-stopped

  radarr:
    image: lscr.io/linuxserver/radarr:latest
    container_name: radarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ./config/radarr:/config
      - ${DATA_ROOT}:/data
    ports:
      - 127.0.0.1:7878:7878
    restart: unless-stopped

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - WEBUI_PORT=8080
      - TORRENTING_PORT=6881
    volumes:
      - ./config/qbittorrent:/config
      - ${DATA_ROOT}:/data
    ports:
      - 127.0.0.1:8080:8080
      - 6881:6881
      - 6881:6881/udp
    stop_grace_period: "10s"
    restart: unless-stopped

या फाइलमधील चार गोष्टी प्रत्यक्ष कार्य करतात.

मीडिया वापरणाऱ्या तीन कंटेनरमध्ये ${DATA_ROOT}:/data समान आहे. Prowlarr साठी ते आवश्यक नाही, कारण Prowlarr मीडिया फाइल कधीही उघडत नाही.

प्रत्येक वेब पोर्ट 127.0.0.1 ला बांधलेला आहे. त्यामुळे Docker तो केवळ loopback पत्त्यावर प्रकाशित करतो. साधा 8989:8989 वापरल्यास तो प्रत्येक interface वर प्रकाशित होईल आणि Docker चे स्वतःचे firewall नियम तो traffic थेट ufw deny नियमाच्या पलीकडे पाठवतील. हे वर्तन वारंवार अनपेक्षित ठरते. याचे स्पष्टीकरण Docker ufw मधून पोर्ट थेट का प्रकाशित करतो येथे दिले आहे.

पोर्ट 6881 सर्व interface वर जाणीवपूर्वक प्रकाशित केला आहे. हा torrent listening port आहे आणि incoming peer connections साठी तो पोहोचण्यायोग्य असणे आवश्यक आहे. sudo ufw allow 6881 वापरून तो परवानगी द्या. हा command नवीन असल्यास VPS साठी ufw firewall ची मूलभूत माहिती वाचा.

प्रत्येक application साठी config directories स्वतंत्र आहेत आणि केवळ media volume सामायिक आहे. पहिल्यांदा सुरू करण्यापूर्वी त्या तयार करा, म्हणजे त्या root ऐवजी तुमच्या user च्या मालकीच्या राहतील:

mkdir -p ~/arr/config/prowlarr ~/arr/config/sonarr ~/arr/config/radarr ~/arr/config/qbittorrent
docker compose up -d
docker compose ps

चारही services ने running वाचले पाहिजे. July 2026 पर्यंत या images lscr.io वर प्रकाशित केल्या जातात आणि latest tag सध्याच्या stable release चे अनुसरण करतो. त्यामुळे upgrades आश्चर्याऐवजी जाणीवपूर्वक घेतलेला निर्णय असावेत असे वाटत असल्यास version tag निश्चित करा.

वेब इंटरफेस सुरक्षितपणे वापरा

पोर्ट loopback वर असल्यामुळे सध्या काहीही बाहेरून उपलब्ध नाही. ते तुमच्या स्वतःच्या मशीनवरून SSH द्वारे forward करा:

ssh -L 9696:127.0.0.1:9696 -L 8989:127.0.0.1:8989 \
    -L 7878:127.0.0.1:7878 -L 8080:127.0.0.1:8080 you@your-server

आता तुमच्या ब्राउझरमधील http://127.0.0.1:8989 सर्व्हरवरील Sonarr पर्यंत पोहोचते. कायमस्वरूपी प्रवेशासाठी, stack ला अनेक ॲप्ससाठी TLS प्रमाणपत्रांसह Traefik मागे ठेवा किंवा तुम्ही स्वतः होस्ट केलेल्या WireGuard VPN द्वारे सर्व्हरपर्यंत पोहोचा. या application पैकी कोणतेही application फक्त त्याच्या स्वतःच्या login page समोर ठेवून public internet वर ठेवू नये.

qBittorrent पहिल्यांदा सुरू झाल्यावर यादृच्छिक administrator password तयार करते आणि ते container log मध्ये लिहिते. ते वाचा आणि web interface मध्ये बदला:

docker compose logs qbittorrent | grep -i password

तुम्ही ते बदलले नाही, तर प्रत्येक restart वेळी नवीन यादृच्छिक password तयार होईल आणि प्रत्येक वेळी तुम्हाला logs तपासावे लागतील.

प्रत्येक applicationमधील path सेट करा

qBittorrent मध्ये Options उघडा. त्यानंतर Downloads उघडा आणि default save path म्हणून /data/torrents सेट करा. अपूर्ण downloads चे folder त्याच tree मध्ये ठेवा, उदाहरणार्थ /data/torrents/incomplete. /data च्या बाहेर कुठेही पूर्ण झालेला download library मध्ये hardlink करता येत नाही.

Sonarr मध्ये Settings उघडा. त्यानंतर Media Management उघडा आणि /data/media/Shows हा root folder जोडा. Radarr मध्ये root folder /data/media/Movies आहे. हे container मधील paths आहेत. Host path /mnt/data/media/Shows नाकारला जातो, कारण container च्या दृष्टीने तो directory अस्तित्वात नाही.

Sonarr आणि Radarr दोन्हीमध्ये Settings उघडा. त्यानंतर Download Clients उघडा आणि qBittorrent जोडा. Host qbittorrent आणि port 8080 आहे. Service name hostname म्हणून कार्य करते, कारण Compose अंतर्गत DNS (domain name system) service असलेल्या एकाच network वर चारही containers ठेवते. येथे localhost वापरू नका: Sonarr container मध्ये localhost म्हणजे Sonarr आहे.

Remote Path Mappings रिकामे ठेवा. Download client ने दिलेला path arr application ला दिसणाऱ्या path मध्ये रूपांतरित करण्यासाठी हे feature असते. एकच shared /data mount असल्यामुळे दोन्ही containers आधीपासून प्रत्येक path बाबत एकमतात आहेत. हे layout प्रयत्न करण्यास योग्य ठरण्याचे हे दुसरे कारण आहे.

Prowlarr ला Sonarr आणि Radarr शी कनेक्ट करा

Prowlarr इतर अनुप्रयोगांमध्ये indexer व्याख्या पाठवते. त्यामुळे indexer दोनदा कॉन्फिगर करण्याऐवजी एकदाच कॉन्फिगर करता येतो. यासाठी प्रत्येक अनुप्रयोगाकडून API (application programming interface) key आवश्यक असते.

Sonarr मध्ये Settings उघडा. त्यानंतर General उघडून API key कॉपी करा. Prowlarr मध्ये Settings उघडा. त्यानंतर Apps उघडा आणि Sonarr अनुप्रयोग जोडा. तीन फील्ड भरा. Prowlarr Server हे http://prowlarr:9696 आहे. Sonarr Server हे http://sonarr:8989 आहे. API Key मध्ये कॉपी केलेली value द्या. Test दाबा. हिरवा result म्हणजे Compose network द्वारे Prowlarr ने Sonarr शी संपर्क साधला आहे. Radarr साठी http://radarr:7878 वापरून ही प्रक्रिया पुन्हा करा.

connection refused असा लाल result दिसल्यास service name चुकीचे असणे किंवा http:// prefix नसणे हे जवळजवळ नेहमीचे कारण असते. container च्या आतून name resolve होत असल्याची खात्री करा:

docker compose exec prowlarr curl -sS -o /dev/null -w '%{http_code}\n' http://sonarr:8989

HTTP status code मिळाल्यास network path योग्य असल्याचे सिद्ध होते. name resolution error मिळाल्यास service name चुकीचे आहे.

हार्डलिंक प्रत्यक्षात तयार झाल्याचे पडताळा

लिंक संख्या पाहेपर्यंत सेटअपवर विश्वास ठेवू नका. एक आयटम import केल्यानंतर, डाउनलोड केलेली फाइल आणि library मधील फाइल यांची तुलना करा:

stat -c '%i %h %n' /mnt/data/torrents/tv/*/*.mkv
stat -c '%i %h %n' /mnt/data/media/Shows/*/*/*.mkv

पहिली संख्या inode आणि दुसरी संख्या link count असते. हार्डलिंक केलेल्या फाइलमध्ये दोन्ही ठिकाणी समान inode आणि 2 इतकी link count दिसते. प्रत्येकी 1 इतकी link count असलेले दोन वेगवेगळे inode दिसल्यास Sonarr ने फाइल कॉपी केली आहे. Import log मध्ये hardlink अयशस्वी झाल्याचे नमूद असेल.

डिस्कचाही निरीक्षण करा. Import होताना df -h /mnt/data मध्ये फारसा बदल होऊ नये, कारण हार्डलिंक केवळ एक नाव जोडते आणि डेटा जोडत नाही.

नेमके काय बिघडते

आयात करताना परवानगीसंबंधी त्रुटी येतात याचा अर्थ container चा user id library folder मध्ये लिहू शकत नाही. संदेश Access to the path ... is denied असा आहे. मालकाचा id तुमच्या PUID शी जुळतो का हे ls -ln /mnt/data/media वापरून तपासा. तसेच, container त्या directories मध्ये प्रवेश करण्यापूर्वी त्यांच्यावर execute bit आवश्यक असतो.

root च्या मालकीच्या दिसणाऱ्या files म्हणजे host directory अस्तित्वात येण्यापूर्वी container सुरू झाला होता. त्यामुळे Docker ने ती root म्हणून तयार केली. Stack थांबवा, directory chown करा आणि ती पुन्हा सुरू करा.

qBittorrent मधून torrent हटवल्यानंतर library file देखील गायब झाल्याचे आढळल्यास, आयात ही नंतर हटवलेली copy होती किंवा तुम्ही torrent entry ऐवजी data हटवला. वास्तविक hardlink असल्यास, एक नाव हटवले तरी दुसरे नाव कायम राहते, कारण link count शून्यावर पोहोचल्यावरच data मोकळा होतो.

तुम्ही जोडलेल्या media पेक्षा disk अधिक वेगाने भरत असेल, तर ही copy समस्या सर्वाधिक खर्चिक स्वरूपात आहे. अधिक storage घेण्यापूर्वी वरील stat तपासणी चालवा.

या stack ला VPS कडून आवश्यक असलेल्या गोष्टी

तीन arr अनुप्रयोग हलके आहेत. ते indexers कडून माहिती घेतात, लहान SQLite database मध्ये नोंदी करतात आणि files ची नावे बदलतात. 2 GB RAM असलेला server हे चारही containers सहज चालवतो. भार इतर ठिकाणाहून येतो. मोठ्या torrents साठी download client disk input आणि output ची क्षमता पूर्णपणे वापरतो. त्याच box वर media server video transcoding करत असल्यास CPU वर मोठा भार पडतो. Media ला प्रत्यक्ष throughput असलेल्या volume वर ठेवा. Server वर इतर महत्त्वाचे काम सुरू असल्यास download client वर bandwidth limit सेट करा.

FAQ

Container च्या दृष्टीने source आणि destination वेगवेगळ्या filesystems वर असल्यामुळे असे होते. /downloads आणि /tv सारखे दोन स्वतंत्र bind mounts असतील, तर ते एकाच host disk वरून आलेले असले तरी ते दोन filesystems मानले जातात. प्रत्येक container मध्ये एकच parent directory /data म्हणून mount करा आणि त्यामध्ये downloads आणि library ठेवा. त्यामुळे link तयार करणे शक्य होते. दोन्ही फाइल्सवर stat -c '%i %h %n' वापरून परिणाम तपासा: inode समान आणि link count 2 असणे आवश्यक आहे.

कोणते PUID आणि PGID वापरावे?

media tree च्या मालकीच्या host account चा numeric id वापरा. तो id -u आणि id -g वापरून मिळवता येतो. नव्याने तयार केलेल्या Ubuntu VPS वर दोन्हीसाठी तो साधारणपणे 1000 असतो. stack मधील प्रत्येक container ने हीच जोडी वापरली पाहिजे. अन्यथा एखादे application लिहिलेल्या फाइल्समध्ये दुसरे application बदल करू शकणार नाही. मूल्ये बदलल्यानंतर docker compose up -d --force-recreate वापरून containers पुन्हा तयार करा आणि विद्यमान फाइल्ससाठी chown -R वापरा.

ही web interfaces internet वर उपलब्ध करून देणे आवश्यक आहे का?

नाही. तसे करू नये. Compose file मध्ये प्रत्येक published port 127.0.0.1 ला bind करा. त्यानंतर SSH tunnel, VPN किंवा TLS (transport layer security) समाप्त करून स्वतःचे authentication लागू करणाऱ्या reverse proxy द्वारे interfaces वापरा. ती interfaces थेट publish करणे दिसते त्यापेक्षा अधिक धोकादायक आहे, कारण Docker स्वतःचे firewall rules समाविष्ट करते आणि ufw deny rule तो network traffic थांबवू शकत नाही.

qBittorrent चा password कुठे मिळेल?

LinuxServer.io image च्या startup log मध्ये admin user साठी temporary password दाखवला जातो. तो वाचण्यासाठी docker compose logs qbittorrent | grep -i password चालवा. त्यानंतर Options आणि Web UI अंतर्गत permanent password सेट करा. स्वतःचा password सेट करेपर्यंत प्रत्येक restart वेळी नवीन temporary password तयार केला जातो.

Jellyfin हीच folders वापरू शकते का?

होय. हीच या layout ची उद्दिष्टे आहेत. /mnt/data/media हे तुमच्या media server मध्ये /media म्हणून mount करा. त्याच्या libraries /media/Movies आणि /media/Shows येथे असतील, तर Sonarr आणि Radarr /data/media द्वारे त्याच directories मध्ये लिहितील. media server ला PUID आणि PGID हीच values द्या, जेणेकरून arr stack ने लिहिलेल्या फाइल्स तो वाचू शकेल.

#sonarr#radarr#prowlarr#docker-compose#self-hosting