SSD Nodes Learn 8GB RAM — yılda $66
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-01

Tek Docker Compose Dosyasında Prowlarr Sonarr Radarr

Prowlarr, Sonarr, Radarr ve qBittorrent'i VPS üzerinde tek Docker Compose dosyasıyla çalıştırın; ortak PUID, PGID ve volume düzeni hardlink'leri korur.

Oluşturulan yapı

Bir Docker Compose arr yığını, medya kitaplığını yöneten dört container içerir: indexer ayarları için Prowlarr, diziler için Sonarr, filmler için Radarr ve indirme istemcisi olarak qBittorrent. Bu container'lar Compose ağı üzerinden service name kullanarak iletişim kurar ve host üzerindeki tek bir klasör ağacını paylaşır. Kurulum kısadır. Yığının yıllarca sorunsuz çalışmasını veya her hafta sorun çıkarmasını belirleyen bölüm volume düzenidir. Bu nedenle bu kılavuzun çoğu volume düzenine ayrılmıştır.

Yığın içeriği sizin için bulmaz. Prowlarr, eklediğiniz indexer'ları barındırır. Hangi indexer'ları kullanacağınız sizin kararınız ve yasal sorumluluğunuzdur. Bu kılavuz; kullanıcıları, yolları, izinleri, container ağını ve kurulumun çalıştığını kanıtlayan kontrolleri kapsar.

Daha önce bir Compose dosyası yazmadıysanız önce VPS için Docker Compose temelleri bölümünü okuyun. Bu yazıda docker compose version komutunun sunucunuzda zaten çıktı verdiği varsayılır.

Sabit bağlantılar neden çalışmaz ve asıl önemli nokta neden budur

Sonarr bir indirme işlemini tamamladığında dosyayı kitaplığınıza aktarır. İndirme klasörü ile kitaplık klasörü aynı dosya sistemi üzerindeyse aktarım bir sabit bağlantı oluşturur: diskteki aynı verilere işaret eden ikinci bir ad. Ek alan veya süre gerektirmez. Torrent eski addan seed etmeye devam ederken medya sunucunuz yeni adı okur.

İki klasör farklı dosya sistemleri üzerindeyse kernel bu bağlantıyı oluşturamaz. Sonarr bir kopyalama işlemi gerçekleştirir. 40 GB boyutundaki bir sezon artık diskte 80 GB yer kaplar ve giriş-çıkış işlemleri birkaç dakika sürer. Aktarım günlüğünde sabit bağlantının başarısız olduğu ve bunun yerine dosyanın kopyalandığı belirtilir. Sabit disk kotası olan bir VPS'de alanın bir hafta içinde tükenmesinin nedeni budur.

Sorun burada ortaya çıkar. Bir container içinde bind mount, dosya sistemi sınırıdır. /mnt/data/torrents yolunu /downloads olarak ve /mnt/data/media yolunu /tv olarak mount ederseniz, her ikisi de aynı ana makine diski üzerinde bulunsa bile Sonarr bunları iki ayrı mount olarak görür ve aralarında bağlantı oluşturmayı reddeder. LinuxServer.io resmi image belgelerinde bu durum doğrudan belirtilir: ayrı /downloads ve /tv yollarının kullanılması sabit bağlantı oluşturma olanağından vazgeçilmesine neden olur.

Çözüm tek bir mount kullanmaktır. Medyaya erişen her container aynı tek volume olan /mnt/data:/data değerini kullanır ve kullandıkları her yol bunun içindeki bir klasör olur. Tek mount noktası, tek dosya sistemi ve çalışan sabit bağlantılar.

Kullanıcıyı, grubu ve klasörleri oluşturma

Container'lar dosyaları PUID ve PGID tarafından belirlenen sayısal kullanıcı kimliğiyle yazar. Bu dosyaları SSH üzerinden sudo olmadan okuyup düzenleyebilmek için kendi hesabınızı kullanın.

id -u
id -g

Yeni bir Ubuntu VPS'de her iki komut da genellikle 1000 çıktısını verir. Şimdi klasör ağacını oluşturun. Ağacı medya dosyalarınızı barındıran diskte oluşturun ve ağacın tamamını bu tek diskte tutun.

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

Devam etmeden önce gerçekten tek bir dosya sistemi olduğunu kontrol edin:

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

Her iki satırda da aynı kaynak aygıtı gösterilmelidir. Farklı iki aygıt, container yapılandırmasında ne ayarlarsanız ayarlayın hardlink'lerin çalışmasını engeller.

Kitaplık klasörleri özellikle Movies ve Shows olarak adlandırılmıştır. Medya sunucunuz olarak zaten Jellyfin çalıştırıyorsanız, /mnt/data/media yolunu Jellyfin'e /media olarak bağlayın; kitaplıkları, bu kılavuzun belirttiği şekilde tam olarak /media/Movies ve /media/Shows yollarına yerleşir.

Ortam dosyası

Sunucuya göre değişen değerleri Compose dosyasının yanında bulunan .env içinde tutun.

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

~/arr/.env dosyasını yazın:

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

TZ değerini Europe/Berlin gibi kendi saat diliminiz olarak ayarlayın. arr uygulamaları görevleri bu saat dilimine göre zamanlar ve günlük satırlarına bu bilgiyi ekler. Bu nedenle yanlış bir değer, ileride tüm günlüklerin anlaşılmasını zorlaştırır.

Compose dosyası

~/arr/docker-compose.yml dosyasını yazın:

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

Bu dosyada dört unsur önemli işlev görür.

${DATA_ROOT}:/data, medyaya erişen üç container'da aynıdır. Prowlarr bu değişkeni almaz, çünkü Prowlarr hiçbir medya dosyasını açmaz.

Her web portu 127.0.0.1 adresine bağlanır. Böylece Docker bu portu yalnızca loopback adresinde yayımlar. Sade bir 8989:8989, portu tüm arayüzlerde yayımlar ve Docker'ın kendi firewall kuralları bu trafiği bir ufw deny kuralını doğrudan aşarak iletir. Bu davranış sürekli sürpriz yaratır. Docker'ın portları ufw üzerinden doğrudan yayımlamasının nedeni bölümünde açıklanır.

6881 portu özellikle tüm arayüzlerde yayımlanır. Bu, torrent dinleme portudur ve gelen eş bağlantıları için erişilebilir olması gerekir. sudo ufw allow 6881 ile izin verin. Bu komut yeni ise VPS için ufw firewall temelleri bölümünü okuyun.

Yapılandırma dizinleri uygulama başına ayrıdır ve yalnızca medya volume'u paylaşılır. İlk başlatmadan önce bunları oluşturun. Böylece dizinlerin sahibi root yerine kullanıcınız olur:

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

Dört servisin tümü running değerini okumalıdır. Temmuz 2026 itibarıyla bu image'lar lscr.io üzerinde yayımlanır ve latest etiketi güncel stable sürümü izler. Yükseltmelerin sürpriz yerine bilinçli bir karar olmasını istiyorsanız bunun yerine bir sürüm etiketi sabitleyin.

Web arayüzlerine güvenli şekilde erişme

Bağlantı noktaları loopback üzerinde olduğundan henüz hiçbir şey dışarıya açılmaz. Bunları kendi makinenizden SSH üzerinden yönlendirin:

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

Artık tarayıcınızda http://127.0.0.1:8989 kullanıldığında sunucudaki Sonarr'a erişilir. Kalıcı erişim için yığını birden fazla uygulama için TLS sertifikalarına sahip Traefik arkasına yerleştirin veya sunucuya kendi barındırdığınız bir WireGuard VPN üzerinden erişin. Bu uygulamaların hiçbiri yalnızca kendi giriş sayfası önünde olacak şekilde genel internette çalıştırılmamalıdır.

qBittorrent, ilk başlatmada rastgele bir yönetici parolası oluşturur ve bu parolayı container log'una yazar. Parolayı okuyun, ardından web arayüzünden değiştirin:

docker compose logs qbittorrent | grep -i password

Parolayı değiştirmezseniz her yeniden başlatmada yeni bir rastgele parola oluşturulur ve her seferinde log'lara yeniden bakmanız gerekir.

Her uygulamanın içindeki yolları ayarlama

qBittorrent'te Options'ı, ardından Downloads'ı açın ve varsayılan kayıt yolunu /data/torrents olarak ayarlayın. Tamamlanmamış indirmeler klasörünü /data/torrents/incomplete gibi aynı klasör ağacının içinde tutun. /data dışında herhangi bir konumda tamamlanan indirme, sabit bağlantı kullanılarak kitaplığa eklenemez.

Sonarr'da Settings'ı, ardından Media Management'ı açın ve /data/media/Shows kök klasörünü ekleyin. Radarr'da kök klasör /data/media/Movies olur. Bunlar container içindeki yollardır. /mnt/data/media/Shows host yolu reddedilir, çünkü bu klasör container açısından mevcut değildir.

Sonarr ve Radarr'da Settings'ı, ardından Download Clients'ı açın ve qBittorrent'i ekleyin. Host qbittorrent, port ise 8080 olur. Compose, dört container'ın tamamını dahili bir DNS (domain name system) hizmetine sahip tek bir ağa bağladığı için hizmet adı hostname olarak çalışır. Burada localhost kullanmayın: Sonarr container'ı içinde localhost, Sonarr'dır.

Remote Path Mappings alanını boş bırakın. Bu özellik, download client'ın bildirdiği yolu arr uygulamasının görebileceği bir yola dönüştürmek için kullanılır. Her iki container da tek bir ortak /data mount kullandığı için tüm yolları zaten aynı şekilde yorumlar. Bu, bu düzenin uygulanmaya değer olmasının ikinci nedenidir.

Prowlarr'ı Sonarr ve Radarr'a bağlama

Prowlarr, dizin oluşturucu tanımlarını diğer uygulamalara aktarır. Böylece bir dizin oluşturucuyu iki kez yapılandırmak yerine bir kez yapılandırılır. Her uygulamadan bir API (application programming interface) anahtarı gerekir.

Sonarr'da Settings'i, ardından General'i açın ve API anahtarını kopyalayın. Prowlarr'da Settings'i, ardından Apps'i açın. Bir Sonarr uygulaması ekleyin ve üç alanı doldurun. Prowlarr Server değeri http://prowlarr:9696 olur. Sonarr Server değeri http://sonarr:8989 olur. API Key alanına kopyaladığınız değeri girin. Test'e basın. Sonucun yeşil olması, Prowlarr'ın Compose ağı üzerinden Sonarr'a ulaştığını gösterir. Radarr için işlemi http://radarr:7878 adresiyle tekrarlayın.

Bağlantının reddedildiğini belirten kırmızı sonuç, neredeyse her zaman yanlış bir hizmet adı veya eksik http:// ön eki anlamına gelir. Adın container içinden çözümlendiğini doğrulayın:

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

Bir HTTP durum kodu, ağ yolunun çalıştığını kanıtlar. Ad çözümleme hatası, hizmet adının yanlış olduğunu kanıtlar.

Sabit bağlantıların gerçekten oluşturulduğunu kanıtlama

Bağlantı sayısını görmeden kuruluma güvenilmemelidir. Bir öğe içe aktarıldıktan sonra indirilen dosya ile kitaplık dosyası karşılaştırılmalıdır:

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

İlk sayı inode'u, ikinci sayı ise bağlantı sayısını gösterir. Sabit bağlantıyla oluşturulan dosyada her iki konumda da aynı inode ve 2 bağlantı sayısı görülür. Her birinde 1 bağlantı sayısı bulunan iki farklı inode, Sonarr'ın dosyayı kopyaladığını gösterir. İçe aktarma günlüğünde sabit bağlantının başarısız olduğu belirtilir.

Diski de izleyin. İçe aktarma sırasında df -h /mnt/data değerinin neredeyse hiç değişmemesi gerekir. Bunun nedeni, sabit bağlantının veri eklemeden yalnızca bir ad eklemesidir.

Gerçekte ne bozulur

İçe aktarma sırasında oluşan izin hataları, container içindeki kullanıcı kimliğinin library klasörüne yazamadığı anlamına gelir. Mesaj Access to the path ... is denied şeklindedir. Sahip kimliğinin PUID ile eşleştiğini ls -ln /mnt/data/media kullanarak kontrol edin. Ayrıca container'ın bu klasörlere girebilmesi için dizinlerde execute biti bulunması gerektiğini unutmayın.

root tarafından sahiplenilmiş görünen dosyalar, container'ın host dizini mevcut olmadan önce başlatıldığı anlamına gelir. Bu nedenle Docker dizini root olarak oluşturmuştur. Stack'i durdurun, dizini chown ve yeniden başlatın.

qBittorrent'ten bir torrent'i sildikten sonra library dosyasının da kaybolması, içe aktarmanın sonradan silinmiş bir kopya işlemi olduğu veya torrent girdisi yerine verilerin silindiği anlamına gelir. Gerçek bir hardlink kullanıldığında, bir adın silinmesi diğerini etkilemez. Veriler, link sayısı sıfıra ulaştığında serbest bırakılır.

Diskin, eklediğiniz medyadan daha hızlı dolması, kopyalama sorununun en maliyetli biçimidir. Daha fazla depolama alanı satın almadan önce yukarıdaki stat denetimini çalıştırın.

Bu yığının bir VPS'den gereksinimleri

Üç arr uygulaması hafif çalışır. Dizinleyicileri sorgular, küçük bir SQLite veritabanına yazar ve dosyaları yeniden adlandırır. 2 GB RAM'e sahip bir sunucu, dört container'ın tümünü rahatça çalıştırır. Yük başka kaynaklardan gelir. Bir download client, büyük torrent'lerde disk giriş ve çıkışını tamamen kullanır. Aynı sunucuda video dönüştüren bir media server CPU'yu kullanır. Medyayı gerçek aktarım kapasitesi sunan bir volume üzerinde tutun. Sunucu üzerinde önem verdiğiniz başka işlemler de çalışıyorsa download client için bir bant genişliği sınırı belirleyin.

FAQ

Bunun nedeni, kaynak ve hedefin container açısından farklı dosya sistemlerinde bulunmasıdır. /downloads ve /tv gibi iki ayrı bind mount, aynı host diskinden gelse bile iki farklı dosya sistemidir. Her container içinde tek bir üst dizini /data olarak mount edin ve downloads ile library dizinlerini bunun içine yerleştirin. Böylece link oluşturulabilir. Sonucu her iki dosyada da stat -c '%i %h %n' ile doğrulayın: aynı inode ve 2 link sayısı görülmelidir.

Hangi PUID ve PGID değerlerini kullanmalıyım?

Media tree'nin sahibi olan host hesabının id -u ve id -g ile elde edilen sayısal kimliklerini kullanın. Yeni bir Ubuntu VPS üzerinde bu değerler genellikle her ikisi için de 1000 olur. Stack içindeki her container aynı ikiliyi kullanmalıdır. Aksi hâlde bir uygulamanın yazdığı dosyaları başka bir uygulama değiştiremez. Değerleri değiştirdikten sonra docker compose up -d --force-recreate ile container'ları yeniden oluşturun ve mevcut dosyaların sahipliğini chown -R ile düzeltin.

Bu web arayüzlerini internete açmam gerekir mi?

Hayır. Açılmamalıdır. Compose dosyasında yayımlanan her portu 127.0.0.1 adresine bind edin. Ardından arayüzlere SSH tunnel, VPN veya TLS'yi (transport layer security) sonlandıran ve kendi kimlik doğrulamasını ekleyen bir reverse proxy üzerinden erişin. Arayüzleri doğrudan yayımlamak göründüğünden daha risklidir. Docker kendi firewall kurallarını ekler ve bir ufw deny kuralı bu trafiği durdurmaz.

qBittorrent parolasını nerede bulabilirim?

LinuxServer.io image, admin kullanıcısı için geçici parolayı başlangıç loguna yazar. Parolayı okumak için docker compose logs qbittorrent | grep -i password komutunu çalıştırın. Ardından Options ve Web UI altında kalıcı bir parola belirleyin. Kendi parolanızı belirleyene kadar her yeniden başlatmada yeni bir geçici parola oluşturulur.

Jellyfin aynı dizinleri kullanabilir mi?

Evet. Düzenin amacı budur. /mnt/data/media dizinini media server içine /media olarak mount edin. Böylece kütüphaneleri /media/Movies ve /media/Shows altında bulunur. Sonarr ve Radarr bu dizinlere /data/media üzerinden yazar. Media server'a Sonarr ve Radarr'ın yazdığı dosyaları okuyabilmesi için aynı PUID ve PGID değerlerini verin.

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