SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-08-13

איך להפוך את Jellyfin לחנות וידאו משנות ה-90 עם Halcyon

הפכו את ספריית ה-Jellyfin שלכם לחנות וידאו וירטואלית עם Halcyon. המדריך כולל פקודת Docker, הגדרת Reverse Proxy ודגשים קריטיים על יציבות הגרסאות וניהול ה-API.

מה Halcyon עושה לספריית ה-Jellyfin שלך

Halcyon Video מציג מחדש את ספריית ה-Jellyfin שלך כחנות וידאו משנות ה-90 שניתן להסתובב בה בתוך הדפדפן. כל סרט שבבעלותך הופך למארז על מדף. אתה מהלך במעברים תחת תאורת הפלואורסצנט, מוריד קופסה מהמדף, הופך אותה כדי לקרוא את המפרט בגב האריזה, ונושא אותה לדלפק כדי להתחיל את הניגון. דיווחי הניגון – התחלה, התקדמות ועצירה – מסונכרנים חזרה ל-Jellyfin, כך שנקודות ההמשך והיסטוריית הצפייה נשארות מעודכנות.

Halcyon קורא שרת Jellyfin קיים דרך ה-API של Jellyfin ואינו מנהל ספרייה משל עצמו. מדריך זה מניח ש-Jellyfin כבר פועל ומבצע סריקה תקינה. אם לא, הגדר תחילה את Jellyfin כשרת מדיה על גבי VPS וחזור לכאן ברגע שהספרייה שלך נראית כראוי בלקוח האינטרנט הרגיל. זהו סוג השירות שמתקינים כי הספרייה כבר קיימת, ולא כי נזקקת לשירות נוסף ב-רשימת האירוח העצמי שלך.

הפרויקט מופץ תחת רישיון GPL-3.0 ונכתב על ידי אדם אחד, וה-README מצהיר בבירור כי הוא אינו מקבל Pull requests. הפיתוח מתקדם במהירות ואין מתחזק נוסף שיזהה נסיגה (regression), לכן קבע (pin) את גרסת ה-image לפני שאתה מציג את החנות לאחרים. החלק האחרון מסביר כיצד לעשות זאת.

היכן מתבצע הרינדור?

בדפדפן. Halcyon הוא יישום Vite ו-TypeScript הבנוי על three.js, ספריית JavaScript המציגה גרפיקה תלת-ממדית באמצעות WebGL (ממשק הדפדפן ל-GPU). הגיאומטריה של החנות ואמנות העטיפה מורכבות על ידי המכונה שמציגה את המסך.

הקונטיינר מבצע פעולות מעטות בלבד. הוא מריץ את npm run serve, שהוא vite preview --port 1420 --strictPort --host, ומגיש את הקבצים המקומפלים בתוספת כמה נתיבי middleware קטנים. Halcyon אינו מוסיף טרנסקודינג ואינו מריץ מנוע כלשהו בשרת.

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

תכונה אחת חורגת מכלל זה. Remote Play מפעיל מופעי Chromium ללא ממשק גרפי (headless) בשרת ומזרים את החנות המרונדרת לטלפון או לממיר (set top box) באמצעות WebRTC (תקשורת זמן אמת ברשת). נתיב זה מרנדר בשרת, עם הגבלה של שני מופעים כברירת מחדל, הניתנת לכוונון באמצעות REMOTE_PLAY_MAX_INSTANCES. ללא מיפוי של התקן /dev/dri, מופעים אלו מרונדרים על ה-CPU, כך ש-VPS בעל שתי ליבות ירגיש כל צופה נוסף.

מה החנות קוראת מהספרייה שלך

המעברים נוצרים מתוך המבנה הפנימי של Jellyfin. התוסף Halcyon מסדר את המדורים מתוך הספריות והז'אנרים שלך, ומקבץ סרטי המשך מתוך ה-BoxSets שלך. המפרט הטכני המודפס על גב כל מארז נלקח מנתוני ה-MediaStreams ש-Jellyfin כבר מחזיק, מה שאומר שכל מידע שחסר ב-Jellyfin יחסר גם על המדף.

משמעות הדבר היא שהחנות מהווה השתקפות נאמנה של המטא-דאטה שלך. ספרייה שמוזנת על ידי מערך arr ב-Docker Compose, עם עטיפות וז'אנרים שכבר מוגדרים בה, תיראה כאן הרבה יותר טוב מאשר תיקייה של קבצים בודדים עם שמות גנריים.

נסו את הדגמת חנות הווידאו לפני שתתקינו דבר מה

הפרויקט מפרסם את החנות המלאה כשהיא פועלת מול ספרייה סינתטית ב-הדגמה המארחת. הוספת ?demo=1 לכל כתובת URL של Halcyon תבצע את אותה הפעולה בהתקנה העצמית שלכם.

השתמשו בזה כבדיקת חומרה. ספריית ההדגמה מכילה כ-2,000 כותרים ודורשת בערך 2 GB של זיכרון דפדפן, מה שהופך אותה לכבדה יותר מרוב הספריות האישיות. אם ההדגמה מקרטעת במכשיר שממנו אתם מתכננים לגלוש, גם הספרייה שלכם תקרטע. הפתרון במקרה כזה הוא מצב 2.5D המתואר להלן, ולא שדרוג ל-VPS חזק יותר.

הרצה באמצעות Docker

זהו הפקודה המתועדת על ידי המפתחים.

docker run -d --name halcyon --network host --restart unless-stopped \
  ghcr.io/halcyon-video/halcyon-video

לאחר מכן, ודאו שהשירות עלה.

docker logs halcyon
curl -I http://127.0.0.1:1420

הלוגים צריכים להראות ששרת ה-preview מאזין בפורט 1420, ו-curl אמור להשיב ל-HTTP/1.1 200 OK. מכולה שנסגרת תוך שניות ספורות מעידה כמעט תמיד על בעיית פורט. --strictPort משמעותו שהשרת מסרב לעבור ל-1421 כאשר 1420 תפוס, ולכן הוא נעצר.

--network host נועד עבור Remote Play, לא עבור החנות. WebRTC חייב לפרסם את הכתובת האמיתית של המכונה למכשיר שמבקש את הזרמת המדיה. מאחורי ה-bridge המוגדר כברירת מחדל ב-Docker, המכולה מכירה רק את כתובת ה-172.x שלה, שאף טלפון ברשת שלכם לא יכול להגיע אליה, ולכן הזרמת המדיה לעולם לא מתחברת. אם אתם מעוניינים רק בחנות דרך דפדפן, פרסמו את הפורט במקום זאת.

docker run -d --name halcyon -p 1420:1420 --restart unless-stopped \
  ghcr.io/halcyon-video/halcyon-video

זוהי ברירת המחדל העדיפה ב-VPS, כיוון ש-host networking מציב את המכולה על כל ממשק שיש למכונה, כולל הממשק הציבורי. הרצת Docker על גבי VPS מכסה את שאר ההיבטים של פשרה זו. --restart unless-stopped הוא מה שמחזיר את החנות לפעולה לאחר אתחול, באותו אופן המתואר ב-שירותי Compose שעולים באתחול.

שכפול המאגר (cloning) והרצת docker compose up -d בונים את ה-image באופן מקומי. קובץ ה-Compose המצורף בונה את השירות ממקורות (source) כברירת מחדל, ושורת ה-image: המוכנה מראש מופיעה בו כהערה; בטלו את ההערה בשורה זו אם ברצונכם להשתמש ב-image המפורסם תחת Compose.

מגבלה אחת נכון לאוגוסט 2026: ה-image המפורסם הוא בגרסת linux/amd64 בלבד. חצי ה-arm64 של ה-multi-architecture push נכשל תחת אמולציה וממתין ל-runners מקוריים מסוג arm. ב-VPS מסוג arm64, ה-pull נכשל עם no matching manifest for linux/arm64/v8 in the manifest list entries, ובנייה מתוך השכפול היא הדרך לעקוף זאת.

הפניית השירות לשרת ה-Jellyfin שלכם

פתחו את http://<host>:1420 והתחברו באמצעות כתובת שרת ה-Jellyfin, שם המשתמש והסיסמה שלכם. הקובץ .env.local.example במאגר מיועד לפיתוח מקומי בלבד. Vite חושף משתנים בעלי תחילית VITE_ לקוד צד-לקוח, ולכן סיסמת Jellyfin שנכתבת שם תעבור הידור לתוך חבילת ה-JavaScript שכל מבקר מוריד. בשרת שנגיש לאנשים אחרים, בצעו התחברות דרך הממשק.

הדפדפן מתקשר עם Jellyfin ישירות. הקונטיינר של Halcyon אינו משמש כ-proxy עבור ה-API של Jellyfin, ויש לכך שתי השלכות שכדאי להכיר לפני שמתחילים בפתרון תקלות.

ראשית, Jellyfin חייב להיות נגיש מהדפדפן, ולא רק מה-VPS שמגיש את Halcyon. שירות Jellyfin שמאזין ל-127.0.0.1:8096 מתאים לבדיקה מקומית, אך ישאיר את המדפים ריקים עבור כל השאר.

שנית, הקריאה היא מסוג cross origin, מהכתובת של Halcyon לזו של Jellyfin. כברירת מחדל, Jellyfin משיב לבקשות API עם Access-Control-Allow-Origin: *, כך שהדבר עובד ללא הגדרות נוספות. אם צמצמתם את ההגדרה הזו, או שהצבתם proxy לאימות גישה לפני ה-API של Jellyfin, מסוף הדפדפן ידווח על blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource והחנות תיטען עם מדפים ריקים.

הצבת השירות מאחורי reverse proxy, עם אימות גישה בחזית

vite preview הוא שרת תצוגה מקדימה. הוא אינו מבצע TLS termination ואין לו מנגנון בקרת גישה עצמאי, לכן יש להציב אותו מאחורי Nginx או Caddy בכל חשיפה לאינטרנט.

server {
  listen 443 ssl;
  server_name halcyon.example.com;

  location / {
    proxy_pass http://127.0.0.1:1420;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

שם מתחם (domain name) בחזית המכולה דורש הגדרה נוספת. Halcyon מגיב ל-localhost, לכתובות IP גולמיות ולשמות המכונה עליה הוא רץ, כהגנה מפני DNS rebinding. בתוך מכולה, המכונה היא המכולה עצמה, ולכן ה-hostname שלה אינו השם שלכם. בקשה שמגיעה כ-halcyon.example.com נדחית, והתגובה מציינת את שם המארח שנדחה. הוסיפו שם זה.

docker run -d --name halcyon -p 127.0.0.1:1420:1420 --restart unless-stopped \
  -e HALCYON_ALLOWED_HOSTS=halcyon.example.com \
  ghcr.io/halcyon-video/halcyon-video

הערך מופרד בפסיקים; נקודה בתחילת הערך, כמו ב-.example.com, תואמת לכל תת-מתחם, ו-all מבטל את הבדיקה. השתמשו ב-all רק במכונה ששום גורם חיצוני אינו יכול להגיע אליה.

ברגע שהחנות מוגשת מעל https://, כתובת ה-Jellyfin שתקלידו בעת ההתחברות חייבת להיות גם היא https://. דפדפן חוסם קריאת API ב-http:// רגיל שמתבצעת מדף HTTPS, ובקונסולה תופיע השגיאה Mixed Content: The page at 'https://halcyon.example.com/' was loaded over HTTPS, but requested an insecure resource. ההתחברות פשוט תיכשל, ללא הסבר בתוך Halcyon. הגישו את שניהם מעל TLS, או השאירו את שניהם ב-HTTP רגיל בתוך רשת פרטית.

לאחר מכן, אימות הגישה. החנות מבקשת פרטי התחברות של Jellyfin, כך שזר שימצא את ה-URL ייתקל במסך התחברות. תכונה אחת משנה זאת. הפעלת Remote Play, תחת Settings ולאחר מכן Connection, מעבירה את ה-session של Jellyfin שלכם לשרת, כך שמבקרים ב-/remote.html מקבלים מופע משלהם של הספרייה האמיתית שלכם. זו מטרת התכונה, ומשמעות הדבר היא שסודיות ה-URL היא החיץ בין האינטרנט לבין הסרטים שלכם. אם הפעלתם Remote Play, הציבו מנגנון Single Sign-On לפני האתר כולו באמצעות Authentik כ-SSO gateway באירוח עצמי, או וותרו על שם המארח הציבורי וגשו לחנות דרך מנהרת WireGuard המנוהלת עם wg-easy.

שני פרטים נלווים לכך. ה-reverse proxy מעביר את החנות בלבד: הזרמת ה-Remote Play היא WebRTC מעל UDP ואינה עוברת דרך HTTP proxy, לכן היא זקוקה לנתיב משלה בפורט 3478/udp ובטווח 49200 עד 49260/udp כאשר נעשה שימוש ב-TURN relay המצורף. בנוסף, ה-docker run הרגיל לעיל אינו שומר נפח אחסון, לכן ה-seed של ה-Remote Play לא ישרוד docker rm. קובץ ה-Compose מבצע mount לנפח halcyon-data בנתיב /data ומגדיר את REMOTE_PLAY_SEED ל-/data/remote-play-seed.json בדיוק מהסיבה הזו.

מה לעשות כשהחנות פועלת בצורה לקויה

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

עבור לקוחות אלו קיים מצב 2.5D, המבוסס על HTML ו-CSS פשוטים ללא WebGL, המיועד לחומרה דלה כמו Raspberry Pi. ניתן לעבור בין מצב 3D למצב 2.5D דרך ההגדרות או תפריט ההפעלה ללא צורך בטעינה מחדש של הדף, כך שבדיקת שני המצבים על אותו מכשיר אורכת שניות ספורות. היו ריאליים לגבי התוצאות: המחבר מתאר את המצב השטוח כמחוספס ועדיין בתהליך פיתוח. התייחסו אליו כאל פתרון חלופי (fallback) עבור לקוחות חלשים.

כאשר לקוח חלש מדי עבור חנות ה-3D, הכשל יהיה מוחשי. הלשונית תיטען מחדש מעצמה, או שהדפדפן ידווח על אובדן הקשר WebGL, בדרך כלל בזמן שהמדפים עדיין בתהליך מילוי. העבירו מכשיר כזה למצב 2.5D במקום לצמצם את הספרייה שלכם.

נעיצת ה-image ובדיקה לפני ה-pull

התייחסו לחלק זה ברצינות. התגיות v0.1.0 עד v0.3.1 הופיעו כולן בהפרש של ימים ספורים, ו-v0.2.1 קיים רק משום שה-push של ה-image עבור v0.2.0 נכשל. דיווחי באגים מתקבלים בברכה אצל המפתח המקורי (upstream), אך תיקוני קוד (patches) לא, לכן זרם הגרסאות משקף את מצב העבודה של אדם אחד בלבד.

הרצת latest עם הרגל של docker pull משמעותה שה-store עלול להשתנות מתחת לרגליכם בכל יום שלישי שגרתי. בצעו נעיצה (pin) לפי ה-digest, המזהה היחיד שלא יכול להשתנות.

docker buildx imagetools inspect ghcr.io/halcyon-video/halcyon-video:0.3.1

פקודה זו מדפיסה את ה-digest שמאחורי התגית. השתמשו בו במקום בתגית.

docker run -d --name halcyon -p 1420:1420 --restart unless-stopped \
  ghcr.io/halcyon-video/halcyon-video@sha256:747dcc821a3d2fa318b50e76024783c1835609047e84f502e23d021bc1898b20

ה-digest הזה היה 0.3.1 בתאריך 10 באוגוסט 2026. קראו את ה-digest הנוכחי בעצמכם במקום להעתיק אותו, וקראו את הערות השחרור (release notes) לפני שאתם עוברים גרסה, כיוון שגרסת patch כאן יכולה לכלול שינויים במבנה ה-store בנוסף לתיקונים.

FAQ

האם Halcyon זקוק ל-GPU בשרת ה-VPS שלי?

לא לשימוש רגיל. החנות מרונדרת על ידי three.js בדפדפן, לכן מחשב הלקוח מבצע את הרינדור והמכולה רק מגישה קבצים סטטיים בפורט 1420. היוצא מן הכלל הוא Remote Play, שמריץ Chromium במצב headless על השרת ומזרים את התוצאה. נתיב זה מרונדר על ה-CPU אלא אם כן תמפו את /dev/dri לתוך המכולה עבור האצה חומרתית.

האם אני יכול לחשוף את Halcyon לאינטרנט הציבורי?

רק מאחורי אימות. החנות מבקשת פרטי הזדהות של Jellyfin, אך הפעלת Remote Play מעבירה את ה-session של Jellyfin שלכם לשרת, כך שכל מי שטוען את /remote.html מקבל גישה למופע של הספרייה האמיתית שלכם ללא צורך בהתחברות. הציבו reverse proxy עם single sign on לפני השירות, או השאירו את שם המתחם מחוץ ל-DNS הציבורי וגשו לחנות דרך VPN.

מדוע המדפים ריקים לאחר שאני מתחבר?

הדפדפן קורא ל-API של Jellyfin ישירות, לכן Jellyfin חייב להיות נגיש מהדפדפן ולא רק מה-VPS. פתחו את ה-console של הדפדפן. blocked by CORS policy מציין ש-Jellyfin אינו מקבל את הבקשה מהכתובת של Halcyon. הודעת Mixed Content מציינת שהדף נמצא ב-HTTPS בעוד כתובת ה-Jellyfin שהזנתם היא HTTP רגיל.

האם אני זקוק ל---network host?

רק עבור Remote Play. פרוטוקול WebRTC חייב לפרסם את הכתובת האמיתית של המכונה, ומאחורי ה-Docker bridge המכולה יכולה להציע רק כתובת 172.x שאף טלפון ברשת שלכם לא יכול להגיע אליה. עבור גלישה בחנות בדפדפן, -p 1420:1420 עובד וחושף הרבה פחות מהמארח.

באיזה image tag עלי להשתמש?

קבעו גרסה לפי digest ולא לפי latest. קראו את ה-digest עבור גרסה עם docker buildx imagetools inspect ghcr.io/halcyon-video/halcyon-video:0.3.1, הריצו את ה-digest הזה, ועברו גרסה רק לאחר קריאת ה-release notes. נכון לאוגוסט 2026 ה-image שפורסם הוא linux/amd64 בלבד, לכן מארח arm64 חייב לבצע build מה-clone עם docker compose up -d.