SSD Nodes Learn 8GB RAM — $66/שנה
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-08-01

מחסנית arr בקובץ Docker Compose אחד

הפעילו Prowlarr, Sonarr, Radarr ו־qBittorrent בקובץ Docker Compose אחד על VPS, עם PUID, PGID ונתיבים משותפים ששומרים על קישורים קשיחים.

מה אתם בונים

מחסנית arr של Docker Compose היא אוסף של ארבעה מכלים שמנהלים ספריית מדיה: Prowlarr להגדרות אינדקסרים, Sonarr לסדרות, Radarr לסרטים ו־qBittorrent כלקוח ההורדות. הם מתקשרים זה עם זה דרך רשת ה־Compose לפי שם השירות, ומשתפים עץ תיקיות אחד במארח. ההתקנה קצרה. הגדרת אמצעי האחסון היא שקובעת אם המחסנית תעבוד במשך שנים או תדרוש טיפול מדי שבוע, ולכן רוב המדריך עוסק בכך.

המחסנית אינה מאתרת תוכן בעצמה. Prowlarr מכיל את האינדקסרים שאתם מוסיפים אליו, והבחירה באילו אינדקסרים להשתמש היא באחריותכם ובאחריותכם המשפטית. המדריך עוסק בתשתית: משתמשים, נתיבים, הרשאות, תקשורת בין מכלים והבדיקות שמוכיחות שהמערכת פועלת.

אם מעולם לא כתבתם קובץ Compose, קראו תחילה את היסודות של Docker Compose עבור VPS. המדריך הזה מניח ש־docker compose version כבר מציג פלט בשרת שלכם.

מדוע קישורים קשיחים נכשלים, ומדוע זהו כל העניין

כאשר Sonarr מסיים הורדה, הוא מייבא את הקובץ לספרייה שלך. אם תיקיית ההורדות ותיקיית הספרייה נמצאות באותה מערכת קבצים, הייבוא מתבצע באמצעות קישור קשיח: שם נוסף שמצביע לאותם נתונים בדיסק. הוא אינו צורך שטח נוסף ואינו דורש זמן נוסף. הטורנט ממשיך להעלות נתונים בשם הישן, בעוד שרת המדיה קורא אותם בשם החדש.

אם שתי התיקיות נמצאות במערכות קבצים שונות, הליבה אינה יכולה ליצור את הקישור. Sonarr עובר להעתקה. עונה בגודל 40 GB צורכת כעת 80 GB בדיסק ודורשת כמה דקות של פעולות קלט ופלט, ויומן הייבוא מציין שהקישור הקשיח נכשל ושהקובץ הועתק במקום זאת. ב-VPS עם מכסת שטח דיסק קבועה, כך נגמר המקום בתוך שבוע.

כאן נמצאת המלכודת. בתוך קונטיינר, עגינת bind היא גבול של מערכת קבצים. עגנו את /mnt/data/torrents אל /downloads ואת /mnt/data/media אל /tv, ואף ששניהם נמצאים באותו דיסק של המארח, Sonarr רואה שתי עגינות נפרדות ומסרב ליצור קישור ביניהן. בתיעוד הרשמי של תמונת LinuxServer.io מצוין הדבר במפורש: שימוש בנתיבים הנפרדים /downloads ו-/tv מונע יצירת קישורים קשיחים.

הפתרון הוא עגינה אחת. כל קונטיינר שניגש למדיה מקבל את אותו אמצעי אחסון יחיד, /mnt/data:/data, וכל נתיב שבו הוא משתמש הוא תיקייה בתוכו. נקודת עגינה אחת, מערכת קבצים אחת, וקישורים קשיחים שפועלים.

יצירת המשתמש, הקבוצה והתיקיות

הקונטיינרים כותבים קבצים באמצעות מזהה משתמש מספרי, שנקבע על ידי PUID ו־PGID. השתמשו בחשבון שלכם, כדי שתוכלו לקרוא את הקבצים האלה ולערוך אותם באמצעות SSH, בלי sudo.

id -u
id -g

בדרך כלל שתי הפקודות מדפיסות 1000 ב־Ubuntu VPS חדש. כעת צרו את העץ. הציבו אותו בדיסק שמכיל את המדיה שלכם, והשאירו את העץ כולו בדיסק הזה.

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

בשתי השורות חייב להופיע אותו התקן מקור. שני התקנים שונים פירושם ש־hardlinks לעולם לא יפעלו, בלי קשר להגדרות בקובץ התצורה של הקונטיינר.

תיקיות הספרייה נקראות Movies ו־Shows בכוונה. אם אתם כבר מפעילים את Jellyfin כשרת המדיה שלכם, הרכיבו את /mnt/data/media ב־Jellyfin בתור /media, והספריות שלו ימוקמו ב־/media/Movies וב־/media/Shows, בדיוק במיקומים שמדריך זה מגדיר.

קובץ הסביבה

שמרו את הערכים שמשתנים בין שרתים ב-.env, לצד קובץ Compose.

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

כתבו את ~/arr/.env:

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

הגדירו את TZ לאזור הזמן שלכם, לדוגמה Europe/Berlin. יישומי arr מתזמנים משימות ומוסיפים חותמות זמן לשורות היומן באזור זמן זה, ולכן ערך שגוי יגרום בהמשך לבלבול בכל היומנים.

קובץ 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 רגיל יפרסם אותה בכל הממשקים, וכללי חומת האש של Docker יעבירו את התעבורה ישירות מעבר לכלל deny של ufw. התנהגות זו מפתיעה משתמשים ללא הרף, והיא מוסברת ב־מדוע Docker מפרסם יציאות ישירות דרך ufw.

יציאה 6881 מפורסמת בכל הממשקים בכוונה. זו יציאת ההאזנה של torrent, והיא חייבת להיות נגישה לחיבורי עמיתים נכנסים. אפשרו אותה באמצעות sudo ufw allow 6881, וקראו את היסודות של חומת האש ufw עבור VPS אם הפקודה הזו אינה מוכרת לכם.

ספריות התצורה נפרדות לכל יישום, ורק אמצעי האחסון של המדיה משותף. צרו אותן לפני ההפעלה הראשונה, כדי שיהיו בבעלות המשתמש שלכם ולא בבעלות root:

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

כל ארבעת השירותים צריכים לקרוא את running. נכון ליולי 2026, תמונות אלה מפורסמות ב־lscr.io, והתגית latest עוקבת אחר המהדורה היציבה הנוכחית. לכן, אם ברצונכם שהשדרוגים יהיו החלטה ולא הפתעה, הצמידו תגית גרסה במקום זאת.

גישה בטוחה לממשקי האינטרנט

מכיוון שהיציאות מאזינות על ממשק הלולאה החוזרת, שום דבר עדיין אינו חשוף. העבירו אותן דרך SSH מהמחשב שלכם:

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 מאחורי Traefik עם אישורי TLS עבור כמה יישומים, או התחברו לשרת באמצעות VPN מסוג WireGuard שאתם מארחים בעצמכם. אין להפעיל אף אחד מהיישומים האלה באינטרנט הציבורי כאשר דף הכניסה שלו בלבד מגן עליו.

qBittorrent יוצר סיסמת מנהל אקראית בהפעלה הראשונה ומציג אותה ביומן של ה-container. קראו אותה ולאחר מכן שנו אותה בממשק האינטרנט:

docker compose logs qbittorrent | grep -i password

אם תדלגו על שינוי הסיסמה, בכל הפעלה מחדש תיווצר סיסמה אקראית חדשה, ותצטרכו לחזור ליומנים בכל פעם.

הגדרת הנתיבים בתוך כל יישום

ב־qBittorrent, פתחו את Options ולאחר מכן את Downloads, והגדירו את נתיב השמירה המוגדר כברירת מחדל ל־/data/torrents. השאירו את תיקיית ההורדות החלקיות בתוך אותו עץ, לדוגמה /data/torrents/incomplete. הורדה שמסתיימת בכל מקום מחוץ ל־/data אינה יכולה לקבל קישור קשיח אל הספרייה.

ב־Sonarr, פתחו את Settings ולאחר מכן את Media Management, והוסיפו את תיקיית הבסיס /data/media/Shows. ב־Radarr תיקיית הבסיס היא /data/media/Movies. אלה נתיבים בתוך הקונטיינר. נתיב המארח /mnt/data/media/Shows נדחה, משום שהתיקייה אינה קיימת מנקודת המבט של הקונטיינר.

ב־Sonarr וב־Radarr, פתחו את Settings ולאחר מכן את Download Clients, והוסיפו את qBittorrent. המארח הוא qbittorrent והפורט הוא 8080. שם השירות פועל כשם מארח, משום ש־Compose מציב את כל ארבעת הקונטיינרים באותה רשת, עם שירות DNS פנימי (מערכת שמות מתחם). אל תשתמשו כאן ב־localhost: בתוך הקונטיינר של Sonarr, localhost הוא Sonarr.

השאירו את Remote Path Mappings ריק. תכונה זו נועדה לתרגם נתיב שלקוח ההורדות מדווח עליו לנתיב שאפליקציית arr יכולה לראות. כאשר יש נקודת עגינה משותפת אחת, /data, שני הקונטיינרים כבר משתמשים באותם נתיבים. זו הסיבה השנייה לכך שהפריסה הזו מצדיקה את המאמץ.

חיבור Prowlarr ל-Sonarr ול-Radarr

Prowlarr מעביר את הגדרות האינדקסרים ליישומים האחרים, כך שמגדירים אינדקסר פעם אחת במקום פעמיים. לשם כך נדרש מפתח API ‏(ממשק תכנות יישומים) מכל אחד מהם.

ב-Sonarr, פתחו את Settings ולאחר מכן את General, והעתיקו את מפתח ה-API. ב-Prowlarr, פתחו את Settings ולאחר מכן את Apps, הוסיפו יישום Sonarr ומלאו שלושה שדות. השדה Prowlarr Server הוא http://prowlarr:9696. השדה Sonarr Server הוא http://sonarr:8989. בשדה API Key הזינו את הערך שהעתקתם. לחצו על Test. תוצאה ירוקה פירושה ש-Prowlarr הצליח להתחבר ל-Sonarr דרך רשת Compose. חזרו על הפעולה עם Radarr בכתובת http://radarr:7878.

תוצאה אדומה המציינת שהחיבור נדחה פירושה כמעט תמיד ששם השירות שגוי או שהקידומת http:// חסרה. ודאו שהשם נפתר מתוך הקונטיינר:

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

קוד סטטוס HTTP מוכיח שנתיב הרשת תקין. שגיאת פתרון שם מוכיחה ששם השירות שגוי.

ודאו שנוצרים קישורים קשיחים בפועל

אל תסתמכו על ההגדרה עד שתראו את מונה הקישורים. לאחר ייבוא פריט אחד, השוו בין הקובץ שהורד לקובץ שבספרייה:

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

המספר הראשון הוא ה-inode, והמספר השני הוא מונה הקישורים. קובץ שאליו נוצר קישור קשיח יציג את אותו inode בשני המיקומים ומונה קישורים של 2. שני inodes שונים, שכל אחד מהם מציג מונה קישורים של 1, מצביעים על כך ש-Sonarr העתיק את הקובץ. ביומן הייבוא יצוין שהקישור הקשיח נכשל.

בדקו גם את שטח הדיסק. df -h /mnt/data אמור להשתנות מעט מאוד בעת ייבוא, מכיוון שקישור קשיח מוסיף שם ללא נתונים.

מה באמת מתקלקל

שגיאות הרשאה בעת הייבוא מציינות שמזהה המשתמש של הקונטיינר אינו יכול לכתוב לתיקיית הספרייה. ההודעה היא Access to the path ... is denied. בדקו באמצעות ls -ln /mnt/data/media שמזהה הבעלים תואם ל־PUID שלכם, וזכרו שלתיקיות נדרשת הרשאת ביצוע לפני שהקונטיינר יכול להיכנס אליהן.

קבצים שנראים כאילו הם בבעלות root מציינים שהקונטיינר הופעל לפני שתיקיית המארח הייתה קיימת, ולכן Docker יצר אותה כ־root. עצרו את ה־stack, chown את התיקייה, והפעילו אותו שוב.

מחיקת torrent מ־qBittorrent וגילוי שקובץ הספרייה נעלם פירושם שהייבוא היה פעולת העתקה שהקובץ שלה נמחק מאוחר יותר, או שמחקתם את הנתונים במקום את רשומת ה־torrent. בקישור קשיח אמיתי, הסרת שם אחד משאירה את השם האחר ללא שינוי, מכיוון שהנתונים משתחררים רק כאשר מונה הקישורים מגיע לאפס.

דיסק שמתמלא מהר יותר מכמות המדיה שהוספתם הוא הגרסה היקרה ביותר של בעיית ההעתקה. הפעילו את בדיקת stat שלעיל לפני שתרכשו שטח אחסון נוסף.

מה שהמחסנית הזו צריכה מ־VPS

שלושת יישומי arr קלי־משקל. הם שולחים שאילתות מחזוריות ל־indexers, כותבים למסד נתונים קטן של SQLite ומשנים שמות לקבצים. שרת עם 2 GB של RAM מריץ את כל ארבעת ה־containers ללא קושי. העומס מגיע ממקום אחר. לקוח הורדות רווי את פעולות הקלט והפלט של הדיסק בעת הורדת טורנטים גדולים, ו־media server שמבצע transcoding של וידאו באותו שרת יצרוך את כוח העיבוד. אחסנו את המדיה ב־volume עם קצב העברה בפועל, והגדירו מגבלת רוחב פס בלקוח ההורדות אם השרת מבצע פעולה נוספת שחשובה לכם.

FAQ

מדוע Sonarr מעתיק קבצים במקום ליצור עבורם קישורים קשיחים?

הסיבה היא שמנקודת המבט של הקונטיינר, המקור והיעד נמצאים במערכות קבצים שונות. שתי נקודות עיגון נפרדות מסוג bind mount, כגון /downloads ו-/tv, נחשבות לשתי מערכות קבצים גם כאשר שתיהן מגיעות מאותו דיסק של המארח. עגנו את ספריית האב היחידה בתור /data בכל קונטיינר, והציבו בתוכה את ספריית ההורדות ואת ספריית המדיה. כך ניתן ליצור את הקישור. אשרו את התוצאה באמצעות stat -c '%i %h %n' בשני הקבצים: אותו inode ומונה קישורים בערך 2.

באילו PUID ו-PGID עליי להשתמש?

השתמשו במזהה המספרי של חשבון המארח שבבעלותו עץ המדיה. את המזהים מקבלים באמצעות id -u ו-id -g. ב-VPS חדש של Ubuntu הערך הוא בדרך כלל 1000 עבור שניהם. כל קונטיינר בערימה חייב להשתמש באותו זוג ערכים. אחרת, יישום אחד יוצר קבצים שיישום אחר אינו יכול לשנות. לאחר שינוי הערכים, צרו מחדש את הקונטיינרים באמצעות docker compose up -d --force-recreate ותקנו את הקבצים הקיימים באמצעות chown -R.

האם עליי לחשוף את ממשקי האינטרנט האלה לאינטרנט?

לא, ואין לעשות זאת. קשרו כל יציאה שפורסמה ל-127.0.0.1 בקובץ Compose, ולאחר מכן גשו לממשקים באמצעות מנהרת SSH, VPN או reverse proxy שמסיים TLS (אבטחת שכבת התעבורה) ומוסיף מנגנון אימות משלו. פרסום ישיר שלהם מסוכן יותר מכפי שנדמה, משום ש-Docker מוסיף כללי חומת אש משלו, וכלל deny של ufw לא יעצור את התעבורה הזו.

היכן מוצאים את הסיסמה של qBittorrent?

האימג' של LinuxServer.io מציג סיסמה זמנית עבור המשתמש admin ביומן האתחול שלו. הריצו docker compose logs qbittorrent | grep -i password כדי לקרוא אותה, ולאחר מכן הגדירו סיסמה קבועה תחת Options ו-Web UI. סיסמה זמנית חדשה נוצרת בכל הפעלה מחדש, עד שתגדירו סיסמה משלכם.

האם Jellyfin יכול להשתמש באותן ספריות?

כן, וזו מטרת המבנה הזה. עגנו את /mnt/data/media בשרת המדיה בתור /media. ספריות המדיה שלו נמצאות ב-/media/Movies וב-/media/Shows, ואילו Sonarr ו-Radarr כותבים לאותן ספריות באמצעות /data/media. הקצו לשרת המדיה את אותם PUID ו-PGID, כדי שיוכל לקרוא את מה שכותבת ערימת ה-arr.

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