SSD Nodes Learn 8GB RAM — $66/سنة
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-01

تثبيت Paperless-ngx على VPS عبر Docker Compose

شغّل Paperless-ngx على VPS عبر Docker Compose مع حزمة Postgres الرسمية، واضبط PAPERLESS_URL ومجلد consume ولغات OCR وHTTPS والنسخ الاحتياطية.

ما الذي ستبنيه

يحوّل Paperless-ngx على VPS مجلدًا يحتوي على مستندات ورقية ممسوحة ضوئيًا إلى أرشيف قابل للبحث. تضع ملف PDF في دليل تتم مراقبته، فيشغّل الخادم OCR (التعرّف الضوئي على الحروف)، ويستخرج النص، ويخمّن التاريخ والمراسل، ثم يؤرشف الملف. يتكوّن التثبيت من ملف Docker Compose واحد يضم أربع خدمات. بعد ذلك، يتعلق كل شيء بالتهيئة. ويخصص هذا الدليل معظم طوله لها، لأن التهيئة هي أكثر مواضع فشل التثبيت.

Paperless-ngx هو التفرع المجتمعي الذي تتم صيانته من مشروع Paperless الأصلي. وهو مجاني ومستضاف ذاتيًا، ويخزّن مستنداتك كملفات عادية على القرص، لذلك لا تُحرم أبدًا من الوصول إلى أرشيفك الخاص. يتيح تشغيله على VPS الوصول إلى المستندات الممسوحة ضوئيًا من أي مكان، من دون فتح منفذ على موجّهك المنزلي. كما يتكامل جيدًا مع مثيل Nextcloud خاص بالملفات غير الورقية.

ما الذي تُشغِّله الحزمة فعليًا

يبدأ ملف compose الرسمي أربعة حاويات. يساعدك فهم وظيفة كل حاوية على قراءة السجلات.

  • webserver: صورة paperless-ngx نفسها. تشغّل واجهة الويب وواجهة API والـ consumer الذي يراقب مجلد الإدخال، إضافة إلى عمّال مهام Celery الذين ينفّذون OCR.
  • db: PostgreSQL. يخزّن البيانات الوصفية والعلامات والمراسلات وجداول فهرس البحث النصي الكامل. لا يخزّن ملفات PDF.
  • broker: Valkey، وهو مخزن أزواج مفتاح-قيمة متوافق مع 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 مسبقًا. إذا كان هذا الجزء جديدًا عليك، فابدأ بـ أساسيات 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. إذا لم تتطابق القيم، فلن يتمكن consumer من قراءة الملفات التي تنسخها إلى مجلد consume، وسيعرض السجل خطأ في الأذونات بدلًا من تنفيذ عملية الاستيراد.

بدء تشغيل الحزمة وإنشاء المستخدم الأول

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 (أمان طبقة النقل) في وكيل عكسي، ووجّه الطلبات إلى 127.0.0.1:8000. إذا كان هذا هو التطبيق الوحيد على الخادم، فسيكفي أي وكيل يتضمن عميل ACME (بيئة إدارة الشهادات تلقائيًا). إذا كنت تشغّل عدة حاويات خلف إعداد شهادة واحد، فاتبع نمط الوكيل العكسي Traefik لتطبيقات Docker Compose متعددة، وألحق خدمة webserver بشبكة الوكيل من دون نشر أي منفذ على الإطلاق.

أيًا كان الوكيل الذي تستخدمه، يجب أن يرسل X-Forwarded-Proto: https. من دونه، يعتقد Django أن الطلب وصل عبر HTTP، ويفشل فحص المصدر في نموذج تسجيل الدخول، وتظهر لك CSRF verification failed. Request aborted. في صفحة تبدو صحيحة. والجزء الآخر من هذا الإصلاح هو ضبط PAPERLESS_URL على عنوان https:// المطابق تمامًا لما تكتبه في المتصفح.

ارفع أيضًا حد حجم التحميل في الوكيل. سيرفض الوكيل فحصًا بحجم 40 MB إذا كان يحدّ حجم نص الطلبات إلى 1 MB، وذلك قبل أن يراه paperless، وسيعرض المتصفح فشلًا عامًا في التحميل.

كيفية عمل مجلد الاستهلاك

يربط ملف Compose المجلد ./consume الموجود في مجلد Compose بالمجلد داخل الحاوية. يستورد البرنامج أي ملف تضعه هناك، ثم يحذفه من المجلد، لأن الملف يصبح موجودًا في وحدة تخزين الوسائط التي يديرها 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، والتي تعمل فورًا. لا تعبر هذه الإشعارات أنظمة الملفات عبر الشبكة. إذا كان مجلد الاستهلاك لديك مشاركة NFS أو SMB بحيث يستطيع ماسح ضوئي عبر الشبكة الكتابة فيها، فلن يكتشف البرنامج أي ملف. ولحل المشكلة، اضبط الفاصل الزمني على عدد موجب من الثواني لكي يفحص paperless المجلد بدلًا من ذلك.

لغات OCR وتكلفتها

يأخذ PAPERLESS_OCR_LANGUAGE رمز Tesseract المكوّن من ثلاثة أحرف، ويستخدم eng افتراضيًا. ادمج اللغات باستخدام علامة الجمع، كما في deu+eng. يحاول Tesseract استخدام كل لغة، ثم يحتفظ بأفضل نتيجة. لذلك، تضاعف كل لغة إضافية وقت CPU المستغرق لمعالجة كل صفحة. في VPS يستخدم vCPU مشتركًا، قد يكون الفرق بين انتهاء الفحص خلال عشر ثوانٍ وانتهائه خلال دقيقة. أدرج اللغات التي كُتبت مستنداتك بها فعليًا فقط.

تتضمن image اللغات الإنجليزية والألمانية والإيطالية والإسبانية والفرنسية. لإضافة أي لغة أخرى، أضفها إلى PAPERLESS_OCR_LANGUAGES في قائمة مفصولة بمسافات، مثل PAPERLESS_OCR_LANGUAGES=tur ces، ثم أعد التشغيل. تنزّل الحاوية حزم بيانات Tesseract عند بدء التشغيل، لذلك يكون الإقلاع الأول بعد هذا التغيير أبطأ.

نسخ قاعدة البيانات والوسائط احتياطيًا

يؤدي نسخ وحدات Docker أثناء تشغيل PostgreSQL إلى إنشاء نسخة احتياطية قد يتعذر استعادتها. يتضمن Paperless أداة تصدير خاصة به. تكتب هذه الأداة المستندات وبيان JSON يضم جميع البيانات الوصفية في نقطة الربط ./export:

docker compose exec webserver document_exporter ../export --delete --no-progress-bar

يحذف --delete الملفات المصدَّرة التي لم تعد تطابق مستندًا حاليًا، لذلك يظل المجلد نسخة مطابقة بدلًا من أن ينمو باستمرار. ويحافظ --no-progress-bar على نظافة المخرجات عند تشغيل هذا الأمر من cron.

تتم الاستعادة باستخدام document_importer من المجلد نفسه على مكدس جديد. وهذا يعني أن مجلد التصدير هو الشيء الوحيد الذي يجب عليك الحفاظ عليه بأمان. أرسله إلى موقع خارجي وفق جدول زمني باستخدام نسخ restic الاحتياطية المشفَّرة والمزالة التكرارات من VPS، وشغّل التصدير أولًا حتى لا يلتقط restic أرشيفًا كُتبت بياناته جزئيًا.

تحقق من النسخة الاحتياطية بالتأكد من وجود export/manifest.json، ومن تطابق عدد الملفات مع عدد المستندات الظاهر في الواجهة. النسخة الاحتياطية التي لم تتحقق من إمكانية سردها ليست نسخة احتياطية.

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 لا يتطابقان مع الحساب الذي يملك الملف، لذا صححهما وأعد إنشاء الحاوية. عدم ظهور أي سطر في السجل يعني أن حدث الملف لم يصل أصلًا. يحدث ذلك على المشاركات الشبكية لأن إشعارات النواة لا تعبرها. اضبط 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 أو صورًا أصلًا.

#paperless-ngx#documents#استضافة ذاتية#Docker#ocr