تثبيت Paperless-ngx على VPS عبر Docker Compose
ثبّت Paperless-ngx على VPS عبر Docker Compose، واضبط Postgres الرسمي وPAPERLESS_URL ومجلد الاستيراد وOCR وHTTPS والنسخ الاحتياطية دون أخطاء شائعة.
ما الذي ستبنيه
يحوّل Paperless-ngx على VPS مجلداً من المستندات الورقية الممسوحة ضوئياً إلى أرشيف قابل للبحث. تضع ملف PDF في مجلد تتم مراقبته، فيجري الخادم OCR (التعرّف الضوئي على الحروف)، ويستخرج النص، ويخمّن التاريخ والمراسِل، ثم يفهرس الملف. يتكوّن التثبيت من ملف Docker Compose واحد يضم أربع خدمات. بعد ذلك، كل ما تحتاج إليه هو الإعداد، ولذلك يخصص هذا الدليل معظم طوله له، لأن الإعداد هو الموضع الذي تتعطل فيه عمليات التثبيت. هذا البرنامج ليس مكتبة صور: لا يفيد OCR وتخمين المراسِل في مجلد يضم ملفات JPEG لرحلات العطلات، لذا ضعها في خادم صور مخصص لها، واترك Paperless للمستندات الورقية. وينطبق الأمر نفسه على الفيديو: مكان مجموعة الأفلام المنسوخة هو خادم وسائط، حيث يجعل شيء مثل واجهة Jellyfin الأمامية المصممة على هيئة متجر تأجير من التسعينيات التصفح هو الغرض بدلاً من البحث.
Paperless-ngx هو fork مجتمعي مُصان من مشروع Paperless الأصلي. وهو مجاني ومستضاف ذاتياً، ويخزّن مستنداتك كملفات عادية على القرص، لذلك لا تُحرم أبداً من الوصول إلى أرشيفك الخاص. تشغيله على VPS بدلاً من جهاز منزلي يعني أن عمليات المسح الضوئي لديك متاحة من أي مكان دون فتح منفذ على موجّه منزلك، كما يتكامل جيداً مع مثيل Nextcloud خاص لملفاتك غير الورقية. وينطبق المنطق نفسه على الجهاز المكتبي الموصول به الماسح الضوئي، إذ يتيح لك مرحل RustDesk تملكه على VPS نفسه التحكم في ذلك الجهاز من مكان آخر دون فتح منفذ في الموجّه أيضاً.
ما الذي تُشغّله المكدسة فعلياً
يبدأ ملف Compose الرسمي أربعة containers. يساعدك فهم وظيفة كل منها على قراءة السجلات.
webserver: صورة paperless-ngx نفسها. تشغّل واجهة الويب وواجهة API والمستهلك الذي يراقب مجلد الإدخال والعاملين في مهام Celery الذين ينفذون OCR.db: PostgreSQL. يحتفظ بالبيانات الوصفية والوسوم والمراسلات وجداول فهرس البحث بالنص الكامل. ولا يحتفظ بملفات PDF.broker: Valkey، وهو مخزن key-value متوافق مع Redis. يعمل كقائمة مهام بين عملية الويب والعاملين.gotenbergوtika: اختياريان، ولا يظهران إلا في متغيرات Compose التي تحمل-tika. يحوّلان مستندات Office (.docxو.xlsxو.odt) إلى PDF حتى يتمكن paperless من فهرستها.
اعتباراً من July 2026، يثبّت ملف Compose الخاص بـ postgres الإصدارين docker.io/library/postgres:18 وdocker.io/valkey/valkey:9-alpine، ويسحب التطبيق من ghcr.io/paperless-ngx/paperless-ngx:latest.
المتطلبات الأساسية
- خادم VPS يعمل بنظام Ubuntu 24.04 عبر KVM، مع وصول عبر sudo، وDocker مع تثبيت Compose plugin مسبقاً. إذا كان هذا الجزء جديداً عليك، فابدأ بـ أساسيات Docker Compose لخادم VPS ثم عد إلى هنا.
- اسم نطاق يحتوي على سجل A يشير إلى خادم VPS. يرفض Paperless تقديم الخدمة على اسم مضيف لم تُضبط الخدمة للسماح به، لذلك يجب إعداد ذلك في وقت أبكر مما تتوقع.
- الذاكرة هي القيد الفعلي. يمكن أن تعمل PostgreSQL وValkey وgunicorn وعامل Tesseract OCR جميعاً في الوقت نفسه ضمن 2 GB للاستخدام الخفيف. خصص 4 GB إذا كنت تخطط لاستيراد تراكم يضم مئات عمليات المسح، لأن معالجة OCR لملف PDF كبير متعدد الصفحات ترفع استهلاك الذاكرة وقد تؤدي إلى إنهاء العامل بواسطة قاتل نفاد الذاكرة في النواة.
- القرص: تُخزَّن أرشفتك مرتين، مرة للملف الأصلي ومرة لملف PDF مؤرشف بعد تطبيق OCR، لذلك احسب مساحة تعادل تقريباً ضعف حجم ملفات المسح.
الحصول على ملفات compose الرسمية
يوجد مُثبّت تفاعلي:
bash -c "$(curl --location --silent --show-error https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"يطرح المُثبّت أسئلة ويكتب الملفات نيابةً عنك. تنفيذ ذلك يدوياً يتطلب أربعة أوامر، ويجعلك تعرف مكان كل شيء. هذا هو المطلوب على خادم ستتولى صيانته.
mkdir -p ~/paperless && cd ~/paperless
curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.postgres.yml
curl -fsSL -o docker-compose.env https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.env
curl -fsSL -o .env https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/.envتوجد المتغيرات في الدليل نفسه: docker-compose.sqlite.yml وdocker-compose.mariadb.yml، وإصدار -tika من كل منهما. اختر postgres عند إجراء تثبيت جديد. يكفي SQLite لبضع مئات من المستندات، لكن فهرس البحث في النص الكامل يصبح بطيئاً قبل PostgreSQL بوقت طويل.
يحتوي الملف .env على سطر واحد هو COMPOSE_PROJECT_NAME=paperless. يصبح هذا الاسم البادئة لكل حاوية ووحدة تخزين، لذلك لا تحذفه ثم تتساءل عن سبب عدم تمكّن docker compose down -v من العثور على بياناتك.
اضبط docker-compose.env قبل التشغيل الأول
هناك إعدادان إلزاميان. أنشئ المفتاح السري باستخدام الأمر الموثّق في المشروع:
python3 -c "import secrets; print(secrets.token_urlsafe(64))"ثم حرّر docker-compose.env:
PAPERLESS_SECRET_KEY=<the long string you just generated>
PAPERLESS_URL=https://paperless.example.com
PAPERLESS_TIME_ZONE=Europe/Berlin
PAPERLESS_OCR_LANGUAGE=deu+eng
USERMAP_UID=1000
USERMAP_GID=1000تأتي PAPERLESS_SECRET_KEY بالقيمة الحرفية change-me. تُستخدم لتوقيع ملفات تعريف ارتباط الجلسة. إذا تركتها، يمكن لأي شخص يعرف القيمة الافتراضية تزوير جلسة. اضبطها قبل التشغيل الأول، لأن تغييرها لاحقاً يؤدي إلى تسجيل خروج جميع المستخدمين.
PAPERLESS_URL هو الإعداد الذي يوفر عليك ساعة من العمل. Paperless تطبيق Django، ويتحقق Django من رأس Host لكل طلب. اضبط PAPERLESS_URL، وسيملأ لك ALLOWED_HOSTS وCORS_ALLOWED_HOSTS وCSRF_TRUSTED_ORIGINS. إذا تركته فارغاً ووجّهت نطاقاً إلى الخادم، فستعيد كل صفحة Bad Request (400)، وسيظهر DisallowedHost في سجل الحاوية. اكتب القيمة من دون شرطة مائلة في النهاية ومن دون مسار.
يحدد USERMAP_UID وUSERMAP_GID المستخدم الذي تعمل به الحاوية. اجعلهما مطابقين لحسابك، وتحقق من ذلك باستخدام id -u وid -g. إذا لم تتطابق القيم، فلن يتمكن المستهلك من قراءة الملفات التي تنسخها إلى مجلد الاستهلاك، وسيعرض السجل خطأ في الصلاحيات بدلاً من إجراء عملية استيراد.
شغّل الحزمة وأنشئ المستخدم الأول
docker compose pull
docker compose up -d
docker compose run --rm webserver createsuperuser
docker compose logs -f webserverيطالبك createsuperuser بإدخال اسم مستخدم وبريد إلكتروني وكلمة مرور. لا يوجد تسجيل دخول افتراضي، لذلك يؤدي تخطي هذه الخطوة إلى صفحة تسجيل دخول لن تقبل أي بيانات أبداً. انتظر ظهور سطر السجل الذي يفيد بأن الخادم يستمع على المنفذ 8000 قبل تجربة المتصفح. يشغّل البدء الأول أيضاً عمليات ترحيل قاعدة البيانات، وتستغرق هذه العملية دقيقة أو دقيقتين.
اختبره محلياً قبل ربطه بنطاق:
curl -I http://127.0.0.1:8000تعني إعادة التوجيه من 302 إلى /accounts/login/ أن الحزمة تعمل بشكل سليم.
ضع HTTPS أمامه
ينشر ملف Compose الافتراضي المنفذ 8000:8000، ويربطه بكل الواجهات. على VPS عام، يتيح ذلك لأي شخص يعثر على العنوان الوصول إلى أرشيف مستنداتك بالكامل عبر HTTP غير المشفّر. غيّر سطر المنفذ ليرتبط بواجهة loopback فقط:
ports:
- "127.0.0.1:8000:8000"بعد ذلك، أنهِ TLS (أمن طبقة النقل) في reverse proxy، وأعد توجيه الطلبات إلى 127.0.0.1:8000. إذا كان هذا هو التطبيق الوحيد على الخادم، فسيعمل أي proxy يتضمن عميل ACME (بيئة إدارة الشهادات تلقائياً). إذا كنت تشغّل عدة حاويات خلف إعداد شهادة واحد، فاتبع نمط Traefik لـ reverse proxy مع عدة تطبيقات Docker Compose، وأضف خدمة webserver إلى شبكة proxy من دون نشر أي منفذ على الإطلاق.
أياً كان proxy الذي تستخدمه، يجب أن يرسل X-Forwarded-Proto: https. من دونه، يعتقد Django أن الطلب وصل عبر HTTP، ويفشل فحص المصدر في نموذج تسجيل الدخول، وتحصل على CSRF verification failed. Request aborted. في صفحة تبدو صحيحة. والجزء الآخر من الإصلاح هو ضبط PAPERLESS_URL على عنوان https:// المطابق تماماً للعنوان الذي تكتبه في المتصفح.
ارفع أيضاً حد حجم الرفع في proxy. فإذا كان حجم المستند الممسوح 40 MB، وكان proxy يفرض حداً أقصى لحجم الطلبات يبلغ 1 MB، فسيُرفض الطلب قبل أن يصل إلى paperless، وسيعرض المتصفح خطأ رفع عاماً.
آلية عمل مجلد consume
يربط ملف compose عبر bind mount المسار ./consume من مجلد compose داخل الحاوية. يُستورَد أي ملف تضعه هناك، ثم يُحذف من المجلد، لأن الملف يصبح موجوداً الآن في media volume التي يديرها paperless.
cp ~/scan-2026-07-14.pdf ~/paperless/consume/
docker compose logs -f webserverينبغي أن ترى consumer يلتقط اسم الملف، ويشغّل OCR، وينتهي بسطر يفيد بإضافة المستند. تستغرق الدورة كاملةً ثوانيَ لمسح من صفحة واحدة، وقد تستغرق دقيقة أو أكثر لمستند طويل.
يغيّر إعدادان طريقة العثور على الملفات. يجعل PAPERLESS_CONSUMER_RECURSIVE=true paperless يبحث في المجلدات الفرعية، ويحوّل PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=true اسم كل مجلد فرعي إلى وسم، لذلك يؤدي إسقاط ملف في consume/invoices/2026/ إلى وسمه بالوسمين invoices و2026. هذا أبسط نظام أرشفة يمكنك إنشاؤه.
الاكتشاف هو النصف الآخر من العملية. افتراضياً، تكون PAPERLESS_CONSUMER_POLLING_INTERVAL مضبوطة على 0، ما يعني أن paperless يستخدم إشعارات نظام الملفات في kernel، وهي إشعارات تحدث فوراً. لا تنتقل هذه الإشعارات عبر نظام ملفات شبكي. إذا كان مجلد consume لديك مشاركة NFS أو SMB لكي يتمكن ماسح شبكي من الكتابة إليها، فلن يُكتشف أي ملف على الإطلاق. ويكون الحل بضبط الفاصل الزمني على عدد موجب من الثواني، لكي يفحص paperless المجلد بدلاً من ذلك.
لغات OCR وتكلفتها
يتطلب PAPERLESS_OCR_LANGUAGE رمز Tesseract المؤلف من ثلاثة أحرف، ويستخدم eng افتراضياً. ادمج اللغات باستخدام علامة الجمع، كما في deu+eng. يحاول Tesseract استخدام كل لغة، ثم يحتفظ بأفضل نتيجة. لذلك تضاعف كل لغة إضافية وقت CPU المستغرق في معالجة كل صفحة. على VPS ذي vCPU مشترك، قد يكون الفرق بين انتهاء المسح خلال عشر ثوانٍ وانتهائه خلال دقيقة. أدرج اللغات التي كُتبت بها مستنداتك فعلياً فقط.
تتضمن صورة الحاوية الإنجليزية والألمانية والإيطالية والإسبانية والفرنسية. لإضافة أي لغة أخرى، أضفها إلى PAPERLESS_OCR_LANGUAGES في قائمة مفصولة بمسافات، مثل PAPERLESS_OCR_LANGUAGES=tur ces، ثم أعد التشغيل. تنزّل الحاوية حزم بيانات Tesseract عند بدء التشغيل، لذلك يكون الإقلاع الأول بعد هذا التغيير أبطأ.
أنشئ نسخة احتياطية من قاعدة البيانات والوسائط
يؤدي نسخ Docker volumes أثناء تشغيل PostgreSQL إلى إنشاء نسخة احتياطية قد يتعذر استعادتها. يتضمن Paperless أداة تصدير خاصة به، تكتب المستندات وبيان JSON يتضمن جميع البيانات الوصفية داخل bind mount ./export:
docker compose exec webserver document_exporter ../export --delete --no-progress-barيزيل --delete الملفات المصدَّرة التي لم تعد تطابق مستنداً حالياً، لذلك يظل المجلد نسخة مطابقة بدلاً من أن يستمر في النمو إلى ما لا نهاية. ويحافظ --no-progress-bar على نظافة المخرجات عند تشغيل ذلك من cron.
تتم الاستعادة باستخدام document_importer من المجلد نفسه على stack جديد، ما يعني أن مجلد التصدير هو الشيء الوحيد الذي يجب عليك الحفاظ عليه بأمان. أرسله إلى موقع خارجي وفق جدول زمني باستخدام نسخ restic الاحتياطية المشفَّرة والمزالة التكرارات من VPS، ونفّذ التصدير أولاً حتى لا يلتقط restic أرشيفاً كُتب جزء منه فقط.
تحقّق من النسخة الاحتياطية بالتأكد من وجود export/manifest.json ومن تطابق عدد الملفات مع عدد المستندات الظاهر في الواجهة. النسخة الاحتياطية التي لم تتحقق من محتوياتها قط ليست نسخة احتياطية. والأسوأ من ذلك أن يبدأ التصدير الليلي بالفشل دون أن تلاحظ، لذلك اجعل مهمة cron ترسل حالة الخروج إلى خادم ntfy الخاص بك، وستعرف خلال الأسبوع الذي يحدث فيه العطل بدلاً من اليوم الذي تحتاج فيه إلى الاستعادة.
FAQ
لماذا تُرجع كل صفحة الخطأ "Bad Request (400)" بعد توجيه نطاقي إليها؟
رفض Django ترويسة Host لأن نطاقك غير موجود في ALLOWED_HOSTS. اضبط PAPERLESS_URL=https://paperless.example.com في docker-compose.env من دون شرطة مائلة في النهاية، ثم شغّل docker compose up -d لإعادة إنشاء الحاوية. تعديل ملف البيئة وحده لا يغيّر شيئاً، لأن الحاوية قيد التشغيل تحتفظ ببيئة التشغيل التي بدأت بها.
وضعت ملف PDF في مجلد الاستهلاك ولم يحدث شيء. ما المشكلة؟
تحقق من docker compose logs webserver أولاً. يعني خطأ الصلاحيات أن USERMAP_UID وUSERMAP_GID لا يتطابقان مع الحساب الذي يملك الملف، لذلك أصلح القيمتين ثم أعد إنشاء الحاوية. عدم ظهور أي سطر في السجل يعني أن حدث الملف لم يصل، ويحدث ذلك في المشاركات الشبكية لأن إشعارات kernel لا تعبرها. اضبط PAPERLESS_CONSUMER_POLLING_INTERVAL على قيمة مثل 30، وسيجري paperless فحص المجلد كل 30 ثانية بدلاً من ذلك.
هل يمكنني تشغيل paperless-ngx باستخدام SQLite بدلاً من PostgreSQL؟
نعم، docker-compose.sqlite.yml مدعوم ويستهلك ذاكرة أقل، ولذلك يناسب VPS صغيراً. يظهر المقابل عندما ينمو الأرشيف: يتباطأ البحث في النص الكامل وتعديلات الوسوم المجمّعة بوضوح عند الوصول إلى آلاف المستندات. تتطلب الهجرة لاحقاً تصديراً واستيراداً، لذلك اختر PostgreSQL الآن إذا كنت تتوقع استمرار نمو الأرشيف.
ما مقدار مساحة القرص التي يحتاجها أرشيف عمليات المسح فعلياً؟
تحتاج تقريباً إلى ضعف حجم ملفات المصدر. يحتفظ Paperless بالملف الأصلي من دون تعديل، ويخزّن PDF ثانياً خضع لـOCR ويحتوي على طبقة نص قابلة للبحث، إضافة إلى صور مصغّرة صغيرة. يبقى مستند ممسوح ضوئياً نصّي فقط بحجم 200 KB صغيراً. أما مستند ملوّن بحجم 30 MB لعقد طويل، فيستهلك نحو 60 MB. أضف مجلد التصدير إذا كنت تحتفظ به على القرص نفسه، وعندها سيشغل الأرشيف نفسه ثلاثة أضعاف المساحة على القرص.
هل أحتاج إلى حاويتي Tika وGotenberg؟
فقط إذا أردت فهرسة ملفات Word وExcel وOpenDocument إلى جانب ملفات PDF. تحوّل هاتان الحاويتان هذه التنسيقات إلى PDF لكي يتمكن paperless من إجراء OCR والبحث فيها. كما تضيفان حاويتين قيد التشغيل وبضع مئات من الميغابايتات من الذاكرة، لذلك تخطّهما على خادم صغير إذا كانت كل الملفات التي تحفظها PDF أو صوراً.