لماذا جهاز واحد لأربع مكتبات
الخروج من Plex أو Google Photos أو Spotify أو Audible يقود غالبًا إلى التنظيم نفسه: خدمة لكل نوع من الوسائط، على خادم صغير مستقل أو على جهاز التخزين في غرفة الجلوس. والنتيجة أربعة تحديثات للمتابعة وأربع شهادات وأربع نسخ احتياطية للتخطيط. أما خادم VPS واحد فيختصر ذلك في نقطة دخول واحدة وشبكة Docker واحدة وخطة نسخ احتياطي واحدة.
الصعوبة ليست في التثبيت، فأدلتنا عن Immich وJellyfin وNavidrome وAudiobookshelf تشرحه بالتفصيل. الصعوبة في التحجيم: فـ Immich وتحويل ترميز الفيديو يرهقان الخادم الصغير، بينما يمر Navidrome وAudiobookshelf دون أن يُلاحَظا تقريبًا. يجيب هذا المقال عن سؤال واحد: أي جهاز لأي مكتبة.
ما تكسبه من جمع كل شيء
- نقطة دخول واحدة — وكيل عكسي واحد، ونطاق فرعي لكل خدمة، وشهادات تُصدر وتُجدد تلقائيًا.
- ذاكرة مشتركة — يستهلك Navidrome وAudiobookshelf القليل، والذاكرة التي يتركها أحدهما حرة تفيد ذروة الآخر.
- خطة نسخ احتياطي واحدة — أربعة مجلدات إعداد، ونسخة واحدة من PostgreSQL، ونص برمجي واحد.
- توسعة عمودية — حين تكبر المكتبة ترفع الذاكرة والمعالجات والقرص على الخادم نفسه دون إعادة تثبيت.
- وصول root كامل — تختار التوزيعة وتضبط النواة وتثبّت ما تتطلبه الحزمة.
ميزانية الذاكرة والمعالج، خدمة بخدمة
الأرقام الخاصة بـ Immich وJellyfin وحدها مصدرها توثيق رسمي؛ أما بقية الأسطر فهي إعدادات انطلاق يجب قياسها على جهازك. خذ قياساتك بعد تشغيل الحزمة باستخدام docker stats --no-stream ثم عدّل.
Immich هو البند الأكبر. توثيقه يعطي 6 غيغابايت من الذاكرة حدًّا أدنى و8 غيغابايت موصى بها، ونواتين حدًّا أدنى وأربع موصى بها. ويوضح أيضًا أن Immich يعمل على جهاز بذاكرة 4 غيغابايت مع تعطيل التعلم الآلي، وأن قاعدة PostgreSQL تحتاج إلى 2 غيغابايت على الأقل إذا وضعت حدودًا للموارد في Docker. ومنذ الإصدار 3، تتطلب صورة التعلم الآلي على amd64 مستوى مجموعة التعليمات x86-64-v2: تأكد من أن الخطة التي تختارها توفره.
أما المعالج فالفهرسة الأولية هي ما يرهقه: يعمل اكتشاف الوجوه والبحث الدلالي على كل النوى المتاحة لساعات ثم يهدأ كل شيء. وتبقى الخدمات الأخرى شبه غير مرئية ما دمت لا تحوّل الترميز.
ميزانية الحجز لكل خدمة
مرّر الجدول أفقيًا
| الخدمة | الذاكرة المطلوب حجزها | ما يرفعها |
|---|---|---|
| Caddy (الوكيل العكسي) | إعداد انطلاق: 100 ميغابايت، يُقاس | لا شيء تقريبًا: عدد النطاقات الفرعية لا يغيّرها كثيرًا |
| Navidrome | إعداد انطلاق: 250 ميغابايت، يُقاس | مسح مكتبة كبيرة وعملاء يطلبون تحويل ترميز الصوت |
| Audiobookshelf | إعداد انطلاق: 250 ميغابايت، يُقاس | البودكاست المنزَّل تلقائيًا ومسح البيانات الوصفية |
| Jellyfin بالتشغيل المباشر | إعداد انطلاق: 1 غيغابايت، يُقاس (يذكر Jellyfin أن 4 غيغابايت قد تكفي لخادم Linux بلا واجهة رسومية، و8 موصى بها لنشر متوسط) | تحليل المكتبة والصور المولَّدة في المرور الأولي |
| Jellyfin مع تحويل الترميز برمجيًا | لا رقم رسمي لكل بث: قِس ببث تجريبي | كل بث يُحوَّل بالتوازي، خصوصًا HEVC أو الترجمة المدمجة في الصورة |
| Immich (الخادم، التعلم الآلي، PostgreSQL، Valkey) | 6 غيغابايت حدًّا أدنى، 8 موصى بها | الفهرسة الأولية والتعرف على الوجوه والبحث الدلالي |
| الحزمة الكاملة على جهاز واحد | 8 غيغابايت على الأقل (القيمة الموصى بها لـ Immich)، و16 للهامش: تقدير يجب التحقق منه | مهام Immich التي تعمل أثناء تحويل ترميز فيلم |
ميزانية القرص: احسب بالغيغابايت قبل الاختيار
القرص هو السقف الأول لخادم VPS للوسائط، ويمكن حسابه. بالنسبة للفيديو، المعادلة: معدل البت بالميغابت في الثانية مضروبًا في المدة بالثواني ومقسومًا على 8. فيلم مدته ساعتان بمعدل 8 ميغابت في الثانية يزن نحو 7 غيغابايت، وبمعدل 4 ميغابت نحو 3.6 غيغابايت. وبالنسبة للموسيقى، ألبوم مدته 45 دقيقة بصيغة MP3 بمعدل 320 كيلوبت في الثانية يقارب 110 ميغابايت، وبصيغة FLAC احسب من 300 إلى 500 ميغابايت. وكتاب صوتي مدته 10 ساعات بمعدل 64 كيلوبت في الثانية يزن نحو 290 ميغابايت.
وبالنسبة للصور، ابدأ من 3 ميغابايت للقطة: فـ 10000 صورة تشغل نحو 30 غيغابايت، دون احتساب مقاطع الفيديو من الهاتف. ويضيف توثيق Immich أن الصور المصغرة ومقاطع الفيديو المحوَّلة ترفع حجم مكتبة الصور بنسبة 10 إلى 20 بالمئة في المتوسط.
ثم افصل ما يجب أن يكون سريعًا عمّا يجب أن يكون كبيرًا. تزن قاعدة PostgreSQL الخاصة بـ Immich عادة من 1 إلى 3 غيغابايت، ويجب أن تعيش على قرص SSD محلي وليس على مشاركة شبكية أبدًا. وينطبق الأمر نفسه على إعداد Jellyfin وAudiobookshelf: ينصح Audiobookshelf صراحة بعدم وضع مجلد الإعداد على مشاركة شبكية، لما فيه من خطر تلف قاعدة SQLite. أما الوسائط نفسها فيمكن وضعها على وحدة تخزين منفصلة وأكبر.
لا تحوّل الترميز: القاعدة التي تحمي الخادم الصغير
يميّز Jellyfin أربعة أنماط للتشغيل، من الأخف إلى الأثقل: التشغيل المباشر، وإعادة التغليف (remux)، والبث المباشر، وتحويل الترميز. ويصف توثيقه التشغيل المباشر بأنه تسليم الملف دون تعديل وبلا حمل إضافي تقريبًا على الخادم، بينما يُعد تحويل ترميز الفيديو النمط الأكثر كلفة.
وبلا بطاقة رسومية يمر كل تحويل ترميز للفيديو عبر المعالج، ويذكّر توثيق Jellyfin بأن استخدام GPU موصى به دائمًا لذلك. ويحذر أيضًا من أن HEVC وVP9 وAV1 قد تكون مرهقة جدًا في فك الترميز برمجيًا، وأن تحويل محتوى HDR إلى SDR (tone-mapping) يستخدم دائمًا مرمّزًا برمجيًا عند غياب GPU.
تتلخص القاعدة العملية في ثلاث خطوات. احفظ أفلامك بصيغة تقرؤها أجهزتك أصلًا، وهي عادة H.264 داخل MP4 أو MKV. حوّل الملفات المشكلة مرة واحدة مسبقًا بدل تحويلها في كل تشغيل. واستخدم إعداد Jellyfin لكل مستخدم لمنع تحويل ترميز الصوت والفيديو عن الحسابات التي لا تحتاجه. وللتأكد من أن البث لا يستهلك شيئًا، ابدأ تشغيلًا وراقب لوحة التحكم: يظهر فيها نمط التشغيل، ويجب أن يبقى المعالج في حالة راحة.
تركيب الحزمة: شبكة واحدة ووكيل واحد ونطاق فرعي لكل خدمة
إنشاء المجلدات والصلاحيات والشبكة المشتركة
افصل الوسائط والصور والإعدادات، وامنح الملكية للمستخدم 1000، وأنشئ الشبكة التي ستتشاركها كل الحاويات:
sudo mkdir -p /srv/media/video /srv/media/music /srv/media/audiobooks /srv/photos /srv/stack/media /srv/stack/immichsudo mkdir -p /srv/stack/jellyfin/config /srv/stack/jellyfin/cache /srv/stack/navidrome/data /srv/stack/audiobookshelf/config /srv/stack/audiobookshelf/metadatasudo chown -R 1000:1000 /srv/stack /srv/photossudo chmod -R a+rX /srv/mediadocker network create edgeتوجيه أربعة نطاقات فرعية إلى الخادم
أنشئ أربعة سجلات A (jellyfin وmusic وbooks وphotos) تشير إلى عنوان IPv4 للخادم. لا يحصل Caddy على الشهادات إلا إذا كانت سجلات A أو AAAA تشير إلى الخادم وكان المنفذان 80 و443 مفتوحين من الخارج.
كتابة ملف compose للخدمات الثلاث الخفيفة
في
/srv/stack/media/compose.yamlعرّف Jellyfin وNavidrome وAudiobookshelf. لا يُنشر أي منفذ: Caddy وحده يتحدث مع الشبكةedge. تُركَّب الوسائط للقراءة فقط في Jellyfin وNavidrome.services:jellyfin:image: jellyfin/jellyfinuser: 1000:1000volumes:- /srv/stack/jellyfin/config:/config- /srv/stack/jellyfin/cache:/cache- /srv/media/video:/media:rorestart: unless-stoppednetworks: [edge]navidrome:image: navidrome/navidrome:latestuser: 1000:1000volumes:- /srv/stack/navidrome/data:/data- /srv/media/music:/music:rorestart: unless-stoppednetworks: [edge]audiobookshelf:image: ghcr.io/advplyr/audiobookshelf:latestuser: 1000:1000volumes:- /srv/stack/audiobookshelf/config:/config- /srv/stack/audiobookshelf/metadata:/metadata- /srv/media/audiobooks:/audiobooksrestart: unless-stoppednetworks: [edge]إضافة Caddy إلى الملف نفسه
أكمل الملف بخدمة الوكيل، ثم تعريفات الشبكة الخارجية ووحدة تخزين الشهادات:
caddy:image: caddy:2ports:- "80:80"- "443:443"volumes:- ./Caddyfile:/etc/caddy/Caddyfile:ro- caddy_data:/datarestart: unless-stoppednetworks: [edge]networks:edge:external: truevolumes:caddy_data:كتابة Caddyfile بكتلة لكل خدمة
في
/srv/stack/media/Caddyfileيكفي اسم النطاق لتفعيل TLS التلقائي، ويحوّل Caddy طلبات HTTP إلى HTTPS من تلقاء نفسه:jellyfin.your-domain.com {reverse_proxy jellyfin:8096}music.your-domain.com {reverse_proxy navidrome:4533}books.your-domain.com {reverse_proxy audiobookshelf:80}photos.your-domain.com {reverse_proxy immich_server:2283}تثبيت Immich بملف compose الرسمي
نزّل ملفَي آخر إصدار ولا تعدّل ملف compose نفسه:
cd /srv/stack/immichwget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.ymlwget -O .env https://github.com/immich-app/immich/releases/latest/download/example.envفي
.envاضبط القيم الثلاث التالية (كلمة المرور لا تقبل إلا الحروف والأرقام):UPLOAD_LOCATION=/srv/photos/libraryDB_DATA_LOCATION=/srv/stack/immich/postgresDB_PASSWORD=<mot-de-passe-A-Za-z0-9>ربط Immich بالشبكة المشتركة
أنشئ
/srv/stack/immich/docker-compose.override.yml. يدمجه Docker Compose تلقائيًا مع الملف الرسمي الذي يبقى سليمًا وقابلًا للاستبدال عند كل تحديث:services:immich-server:networks: [default, edge]networks:edge:external: trueالتشغيل والتحقق من كل مدخل
شغّل الحزمتين وانتظر إصدار الشهادات، ثم اختبر ترويسات HTTP وTLS. يجب أن تحصل على رمز 2xx أو 3xx عبر HTTPS، وليس خطأ شهادة أبدًا:
cd /srv/stack/media && docker compose up -dcd /srv/stack/immich && docker compose up -dcurl -I https://jellyfin.your-domain.comcurl -I https://photos.your-domain.comالقياس ثم ضبط Immich
أثناء الفهرسة اقرأ
docker stats --no-streamوحمل المعالج. إذا اقتربت الذاكرة من السقف فعطّل ميزة من التعلم الآلي (البحث الذكي أو التعرف على الوجوه) في إعدادات الإدارة، أو خفّض تزامن المهام دون رفعه فوق عدد النوى.
انسخ كل خدمة احتياطيًا واختبر الاستعادة قبل أن تحتاجها
لحزمة من أربعة تطبيقات أربع طرق لفقدان البيانات. الفخ الكلاسيكي هو نسخ الصور دون قاعدة البيانات: لا يفحص Immich مجلد مكتبته، بل يعتمد على قاعدته ليعرف ما هو موجود. ويميّز التوثيق بين المجلدات الأصلية (library وupload وprofile) التي يجب نسخها، والمجلدات القابلة لإعادة التوليد (thumbs وencoded-video).
ينتج Immich أيضًا نسخه الخاصة من القاعدة، افتراضيًا كل يوم عند الثانية فجرًا، ويحتفظ بآخر 14 نسخة في مجلد backups ضمن موقع الرفع. وهي تحتوي على البيانات الوصفية فقط، وليس الصور أبدًا. ولضمان الاتساق أوقف حاوية الخادم أثناء النسخ؛ وإلا فانسخ القاعدة أولًا ثم الملفات.
تتم الاستعادة على جهاز اختبار وفق الإجراء الرسمي (ثم حقن النسخة في psql). تنبيه: الأمر down -v يمحو كل بيانات Immich على الجهاز الذي تنفذه عليه:
docker compose down -vdocker compose pulldocker compose createdocker start immich_postgres
خطة النسخ الاحتياطي لكل خدمة
- Immich، القاعدة — نسخة مضغوطة خارج الخادم:
docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=immich --username=postgres | gzip > "/srv/backup/immich-db.sql.gz"، مع مواءمة اسم القاعدة والمستخدم مع ملف.envلديك. - Immich، الملفات — تُنسخ
libraryوuploadوprofileبواسطةrsyncإلى تخزين بعيد؛ ويمكن إعادة توليدthumbsوencoded-video. - Jellyfin — مجلد
/srv/stack/jellyfin/config(المكتبات والمستخدمون والبيانات الوصفية) والحاوية متوقفة أثناء الأرشفة. أما الذاكرة المؤقتة فتُعاد بناءً. - Navidrome — المجلد
/srv/stack/navidrome/data(القاعدة وقوائم التشغيل والذاكرة المؤقتة)؛ والموسيقى نفسها هي مصدر الحقيقة وتُنسخ كأي مجلد ملفات. - Audiobookshelf —
/configو/metadata: قاعدة SQLite وتقدم الاستماع في الأول، والنسخ الداخلية في الثاني. - الاستعادة تُختبر — أعد تنفيذ إجراء Immich الرسمي المفصَّل أعلاه على جهاز اختبار قبل الاعتماد عليه.
استكشاف الأخطاء: ذاكرة ممتلئة وصلاحيات مرفوضة وعمليات رفع مقطوعة
تنقسم أعطال هذه الحزمة إلى عائلتين: الذاكرة، حين يتنازع Immich وعملية تحويل ترميز على الغيغابايتات نفسها، والصلاحيات، حين لا تستطيع حاوية غير root قراءة مجلد مركَّب أو الكتابة فيه. في الأولى ابدأ بالبحث عن أثر في النواة عبر dmesg -T | grep -i "out of memory": إذا ظهرت عملية من Immich فقد قتلتها النواة لنقص الذاكرة وتعيد الحاوية التشغيل في حلقة. وفي الثانية قارن دائمًا معرّف مستخدم الحاوية بمالك المجلدات المركَّبة.
الأخطاء المصادَفة وعلاجها
- Immich يعيد التشغيل في حلقة على خطة صغيرة — تقتل النواة حاوية التعلم الآلي (ابحث عن
out of memoryفيdmesg). عطّل البحث الذكي والتعرف على الوجوه، أو انتقل إلى خطة بذاكرة 8 غيغابايت على الأقل. can't set healthcheck.start_interval as feature require Docker Engine v25 or later— إصدار Docker لديك قديم جدًا. حدّثه أو علّق السطرstart_intervalفي قسمdatabaseمن ملف compose كما يشير توثيق Immich.- رفع الفيديو ينقطع بعد دقيقة — يشير توثيق Immich إلى الرمز 499 خلف Traefik مع مهلة القراءة الافتراضية البالغة 60 ثانية، ويوصي بـ 600 ثانية. تحقق من مهلة الوكيل لديك.
- Navidrome:
unable to open database file— لا يمكن الكتابة في مجلد/data. امنح الملكية للمعرّف المحدد في التوجيهuser. - يعمل Navidrome لكن المكتبة تبقى فارغة مع
permission deniedفي السجلات — مجلد الموسيقى غير مقروء: نفّذchmod -R a+rXعلى/srv/media/music. - Jellyfin لا يرى الأفلام — لا يستطيع المستخدم 1000 في الحاوية قراءة المجلد المركَّب. اختبر بالأمر
docker exec jellyfin ls /mediaوصحّح الصلاحيات؛ فالمتغيرانPUIDوPGIDلا يعملان مع هذه الصور، والمعتمد هو التوجيهuserوحده.
أي خطة لأي مكتبة
مرّر الجدول أفقيًا
| ملف المكتبة | الخطة الموصى بها | الهامش والحد |
|---|---|---|
| موسيقى وكتب صوتية وبعض الأفلام بالتشغيل المباشر، وImmich دون تعلم آلي، ومستخدم أو اثنان | VPS Start: 2 vCPU، 4 GB، 50 GB SSD، بسعر 99 درهم/شهر | ذاكرة ضيقة: يبقى Immich دون تعلم آلي ويُفضَّل تجنب تحويل الترميز؛ والقرص يحدّ من عدد الأفلام إلى بضعة أفلام (≈ 7 غيغابايت لفيلم مدته ساعتان بسرعة 8 ميغابت/ث) |
| مكتبة صور عائلية تقارب 10000 لقطة (30 إلى 36 غيغابايت) مع تعلم آلي مفعّل، وموسيقى وكتب صوتية، وتشغيل مباشر | VPS Power: 4 vCPU، 8 GB، 100 GB SSD، بسعر 299 درهم/شهر | تبلغ الـ 8 غيغابايت الموصى بها لـ Immich وحده؛ والفهرسة الأولية تبطئ الباقي |
| الحزمة الكاملة بأربع خدمات، ومستخدمان أو ثلاثة، وتحويل ترميز عرضي | VPS Business: 8 vCPU، 16 GB، 200 GB SSD، بسعر 499 درهم/شهر | مريحة؛ ويصبح القرص هو السقف حين يتجاوز الفيديو بضع مئات من الغيغابايت |
| عدة بثوث يُحوَّل ترميزها في الوقت نفسه | VPS Business كحد أدنى، مع تحويل الملفات مسبقًا | دون GPU لا تكفي إضافة المعالجات: الأفضل أن تحوّل مرة واحدة بدل التحويل في كل تشغيل |
قِس قبل أن تدفع أكثر
ابدأ بالخطة التي يشير إليها الجدول، وشغّل فهرسة Immich واقرأ الذاكرة بالأمر docker stats --no-stream خلال يوم ذروة. إذا تجاوز الهامش 30 بالمئة فالحجم مناسب؛ وإذا قتلت النواة حاوية فانتقل إلى خطة أعلى. والتوسعة العمودية للخادم تجنبك إعادة التثبيت: ترتفع الذاكرة والقرص وتبقى مجلدات /srv وملفات compose في مكانها.
التوثيق الرسمي والخطوة التالية
قيم هذا الدليل مستمدة من توثيق المطورين: متطلبات Immich والنسخ الاحتياطي والاستعادة في Immich واختيار العتاد لـ Jellyfin وتحويل الترميز في Jellyfin وNavidrome مع Docker وHTTPS التلقائي في Caddy.
لاختيار وكيل غير Caddy اقرأ مقارنتنا بين Caddy وTraefik وNginx Proxy Manager. وإذا كنت تغادر Plex فالخطوات مفصلة في دليل الانتقال إلى Jellyfin وNavidrome.