استضافة HRConvert2 ذاتياً لتحويل الملفات بأمان
شغّل HRConvert2 على VPS خاص كي لا تلمس ملفاتك مواقع التحويل المجانية. تعرّف إلى تثبيت Docker أو Apache، وعزل bubblewrap، وحدود الرفع والتنظيف.
لماذا تستضيف محوّل ملفات بنفسك
يحافظ محوّل الملفات المستضاف ذاتياً على الملف في وحدة التخزين الخاصة بك. وهذا هو السبب الكامل لتشغيله. يستقبل موقع التحويل المجاني الملف المرفوع، ولا يتيح لك معرفة ما حدث له بعد ذلك. وإذا كان الملف عقداً موقّعاً مع عميل أو سجلاً طبياً ممسوحاً ضوئياً، فإن رفعه بحد ذاته يمثل حادثة أمنية. HRConvert2 هو خادم لتحويل الملفات يعتمد على السحب والإفلات، ومكتوب بلغة PHP ومرخّص بموجب GPLv3. أُصدرت الإصدار 3.7.4 في 18 August 2026، ويدّعي المشروع دعم 488 تنسيقاً.
لا يستخدم قاعدة بيانات أو حسابات أو ملفات cookies. المستخدم عبارة عن دليل مؤقت. تنفّذ أداة سطر الأوامر المحلية كل عملية تحويل: LibreOffice للمستندات، وFFmpeg للصوت والفيديو، وImageMagick للصور، وTesseract للتعرّف الضوئي على الحروف (OCR)، إضافةً إلى مجموعة كبيرة من الأدوات الأصغر التي تتولى بقية التنسيقات. يتولى HRConvert2 صفحة الرفع وخط المعالجة والتنظيف المرتبط بهما.
يحوّل ملفاً من تنسيق إلى آخر. وهو ليس حزمة مكتبية تعمل في المتصفح. إذا كان ما تريده هو أن يحرّر المستخدمون المستندات داخل علامة تبويب، فقارن بدلاً من ذلك بين OnlyOffice وCollabora المستضافين ذاتياً. وهو ليس أيضاً وحدة تخزين. من المفترض حذف الملفات الناتجة عن التحويل، لذلك إذا كان يجب الاحتفاظ بالملفات في مكان ما، فتلك مهمة مدير ملفات مستضاف ذاتياً.
ما تحتاج إليه
Debian أو Ubuntu، وApache 2.4، وPHP 8 أو إصدار أحدث، وbubblewrap. يُستخدم bubblewrap (bwrap) كبيئة عزل، وهو مطلوب ولا يمكن الاستغناء عنه: يرفض الخادم الذي لا يستطيع إنشاء بيئة عزل عملية التحويل بدلاً من تشغيلها من دونها. يذكر ملف README الأساسي أن Raspberry Pi Model B+ يكفي، وهذا صحيح بالنسبة إلى جزء PHP. أما ثنائيات التحويل فهي التي تحدد متطلبات العتاد الفعلية، وسنتناول ذلك بمزيد من التفصيل أدناه.
يمكنك البدء بإحدى طريقتين. تعمل صورة Docker فوراً. أما تثبيت Apache وPHP فيستغرق أمسية، ويتيح لك معرفة كل ما هو موجود على الخادم.
شغّله الليلة باستخدام Docker
تتضمن الصورة كل الملفات الثنائية لمحولات التنسيق، لذلك حجمها كبير: نحو 3 GB حتى August 2026. تحقّق من مساحة القرص الحرة قبل سحب الصورة.
الوسوم مهمة هنا. أحدث وسم نُشر على Docker Hub حتى 17 August 2026 هو v3.7.2، بينما أحدث إصدار على GitHub هو v3.7.4. يتحرك الوسم latest دون تثبيت إصدار محدد، كما أن هذا التطبيق يوفّر مساحة كبيرة لتحليل المدخلات، لذلك ثبّت إصداراً محدداً وحدّثه عمداً.
docker pull zelon88/hrconvert2:v3.7.2
docker run -d --name hrconvert2 \
-p 127.0.0.1:8080:80 \
--security-opt seccomp=unconfined \
zelon88/hrconvert2:v3.7.2docker ps
curl -I http://127.0.0.1:8080/تبقى الحاوية السليمة في الحالة Up، ويُرجع curl القيمة HTTP/1.1 200 OK. الحاوية التي تستمر في إعادة التشغيل لديها مشكلة عند بدء التشغيل، لذلك اقرأ docker logs hrconvert2 قبل تغيير أي شيء آخر.
هناك خياران مهمان. ينشر -p 127.0.0.1:8080:80 المنفذ على loopback فقط، لذلك لا يصل أي شيء إلى المحوّل حتى تضع proxy أمامه عن قصد. يربط المثال الخاص بالمشروع -p 8080:80 -p 8443:443، الذي يستمع على كل الواجهات، بما فيها الواجهة العامة. يوجد --security-opt seccomp=unconfined لأن bubblewrap ينشئ sandbox باستخدام استدعاءات نظام user namespace وmount التي يحظرها ملف seccomp الافتراضي في Docker. من دون هذا الخيار، تفشل عمليات التحويل، ويخبرك التطبيق بالسبب: A sandbox blocks the required syscalls unless it was started with the correct options.
هذا الخيار ينطوي على مفاضلة فعلية. فأنت تخفف مرشح استدعاءات النظام الخاص بالحاوية حتى يتمكن التطبيق من إنشاء sandbox أكثر تقييداً داخلها. الإعدادان اللذان يحددان السلوك هما $RequireSandbox و$RequireSandboxOnDocker في Resources/config.php، وقيمتهما الافتراضية TRUE وFALSE. وبما أن متطلب Docker معطّل افتراضياً، يمكن لحاوية لا تستخدم خيار seccomp تنفيذ التحويل من دون sandbox إطلاقاً. بعد إضافة الخيار، اضبط $RequireSandboxOnDocker = TRUE;، وبذلك تستعيد سلوك الرفض داخل الحاوية.
إذا كان Docker جديداً على هذا الجهاز، فأعد إعداد daemon أولاً. يشرح تشغيل Docker على VPS التثبيت، وبرنامج تشغيل التخزين، وطريقة كتابة Docker لقواعد جدار الحماية الخاصة به.
ثبّته باستخدام Apache وPHP بدلاً من ذلك
يُعد الملف Documentation/INSTALLATION_INSTRUCTIONS.txt في المستودع المرجع المعتمد، ويتكوّن من تسع خطوات. هذا هو هيكله. ابدأ بخادم الويب واللغة وبيئة العزل:
sudo apt update
sudo apt install -y apache2 php libapache2-mod-php php-all-dev php8.3-zip php8.3-gd bubblewrapتتوافق أسماء php8.3-* مع Ubuntu 24.04. شغّل php -v واستخدم السابقة التي تطابق إصدارك، لأن أسماء هذه الحزم تتغير مع كل إصدار من PHP، واستخدام الاسم الخاطئ يعطيك Unable to locate package.
ثم ثبّت المحوّلات. يغطي ذلك المستندات والصور والصوت والفيديو والتعرّف الضوئي على الحروف، وهي معظم الأنواع التي يحوّلها المستخدمون فعلياً:
sudo apt install -y imagemagick ffmpeg libreoffice-common libreoffice-java-common \
default-jre ghostscript poppler-utils libgxps-utils tesseract-ocr inkscape \
xvfb clamav curl tar libxcb-cursor0تحتاج تنسيقات الأرشيف والنماذج ثلاثية الأبعاد والكتب الإلكترونية وصور ISO القابلة للإقلاع إلى حزم أكثر من ذلك، وبعضها موجود في مكوّن multiverse في Ubuntu. تتضمن الخطوتان 3 و5 من التعليمات الرسمية القائمة الكاملة بالترتيب. هناك تبعيتان ليستا من حزم apt أصلاً: يوفّر المستودع Documentation/Build/ffmpeg-build.sh وDocumentation/Build/build-imagemagick-v7.sh لمن يحتاجون إلى برامج ترميز أو إلى ImageMagick 7 لا توفره Ubuntu ضمن حزمها. يأتي دعم الكتب الإلكترونية من مُثبّت calibre الخاص، وتعرضه التعليمات في سطر واحد:
sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdinهذا script يوفّره المورّد ويُمرَّر إلى shell بصلاحيات root. هذه هي طريقة upstream، وهي اختيارية: تخطَّها، وما ستفقده هو تحويل الكتب الإلكترونية فقط.
بعد ذلك، اضبط حدود PHP. التحويلات بطيئة والملفات كبيرة، لذلك تكون القيم الافتراضية صغيرة جداً. يضبط المشروع هذه القيم في php.ini:
max_execution_time = 1200
max_input_time = 90
memory_limit = 512M
post_max_size = 5000M
upload_max_filesize = 5000M
max_file_uploads = 100
display_errors = Off
zlib.output_compression = Onتفترض هذه الأرقام وجود مساحة كافية على الجهاز. خفّضها قبل الاقتراب من VPS صغير، لأن upload_max_filesize = 5000M مع max_file_uploads = 100 يصف طلباً واحداً يمكنه كتابة بيانات تتجاوز بكثير سعة قرص تبلغ 40 GB. أعد تشغيل Apache وتحقق مما حمّله PHP فعلياً:
sudo service apache2 restart
php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"الآن أنشئ دليل العمل. يحدده $ConvertLoc في Resources/config.php، والقيمة الافتراضية هي /DATA/HRConvert2. يجب أن يملك مستخدم خادم الويب هذا الدليل:
sudo mkdir -p /DATA/HRConvert2
sudo chmod -R 0755 /DATA/HRConvert2
sudo chown -R www-data:www-data /DATA/HRConvert2فكّ إصدار البرنامج تحت جذر مستندات Apache. يضعه التخطيط الافتراضي في مجلد HRProprietary/HRConvert2، ويجب أن يحدد $InstLoc في Resources/config.php المكان الذي وضعته فيه فعلياً. ثم شغّل أداة التشخيص المضمّنة، فهي أسرع طريقة لاكتشاف تبعية مفقودة قبل أن يكتشفها أحد المستخدمين:
sudo php /path/to/HRConvert2/convertCore.php -vيفحص -v عملية التثبيت كاملة: الإصدارات الأساسية، وفحوصات التبعيات، وحالة بيئة العزل، وحزم اللغات. لا تُدعَم تحويلات الملفات من سطر الأوامر، لذلك تقتصر مجموعة الوسائط هذه على الاستخدام الإداري.
لماذا تفشل كل عمليات التحويل في تثبيت Ubuntu 24.04 جديد؟
بسبب sandbox، وهذه أكثر مشكلة شائعة في اليوم الأول. يقيّد Ubuntu 24.04 وDebian 12 مساحات أسماء المستخدمين غير المميّزين افتراضياً. يحتاج Bubblewrap إلى مساحة أسماء مستخدمين لإنشاء sandbox الخاص به، لذلك يتعذر على bwrap البدء. وبما أن التطبيق يرفض إجراء التحويل من دون sandbox، تفشل كل مهمة.
تحقق من ذلك مباشرة:
bwrap --ro-bind / / --dev /dev /bin/true && echo sandbox okيعني خطأ رفض الإذن أن مساحة الأسماء حُظرت. الحل هو إنشاء ملف تعريف AppArmor للثنائي bwrap. اعرض أولاً ملفات ABI وسجّل أعلى رقم موجود:
ls /etc/apparmor.d/abi/اكتب بعد ذلك /etc/apparmor.d/bwrap، مع استبدال 4.0 بأعلى رقم:
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}حمّله:
sudo apparmor_parser -r /etc/apparmor.d/bwrapيعني عدم ظهور أي مخرجات أن ملف التعريف حُمّل بنجاح. شغّل فحص bwrap مرة أخرى، وينبغي أن يطبع sandbox ok. بعد ذلك ستعمل عمليات التحويل.
المحوّل العام هو محلّل ملفات مكشوف للغرباء
هذا هو الغرض من بقية المقال. يقبل محوّل ملفات يمكن الوصول إليه من الإنترنت ملفاً عشوائياً من شخص مجهول، ثم يمرّره إلى LibreOffice أو ImageMagick أو FFmpeg أو Ghostscript. هذه أدوات مبنية على قواعد شيفرة كبيرة بلغة C وC++، ولها سجل طويل من ثغرات محلّلات الملفات. ويختار الشخص الذي يرفع الملف تنسيقه، ما يعني أنه يختار المحلّل الذي سيعمل ومسار الشيفرة الذي سيُنفّذ داخله.
يعتمد HRConvert2 على تشغيل كل تبعية داخل namespace معزول باستخدام bubblewrap. ولا يرى كل تحويل سوى مجلدين: المجلد الذي يحتوي على ملف الإدخال، ويُركّب للقراءة فقط، والمجلد الذي يستقبل ملف الإخراج. وتكون الشبكة غير مشتركة، ووفقاً لعبارة المشروع، closes every URL handler in every dependency at once. وهذا أهم مما يبدو. يقبل كل من ImageMagick وGhostscript مراجع يمكنها جلب URL، وبذلك يتحول المحوّل إلى أداة لتنفيذ طلبات من جانب الخادم (SSRF) والوصول إلى نقطة نهاية بيانات التعريف السحابية من داخل شبكتك. وعند تعطيل الشبكة داخل namespace، لا يمكن تنفيذ عملية الجلب.
أما الرفض فهو النصف الآخر: A server that cannot build a sandbox refuses the conversion rather than quietly running without one. الأداة التي تفشل بطريقة آمنة أفضل من أداة تحذّرك في سجل لا يقرأه أحد. ولهذا فإن خطوة AppArmor المذكورة أعلاه ليست اختيارية، ولهذا أيضاً تستحق $RequireSandboxOnDocker المراجعة قبل تعريض الحاوية للإنترنت.
تشديد أمان ImageMagick باستخدام policy.xml
يمثّل ملف policy الخاص بـImageMagick طبقة ثانية ضمن بيئة العزل، ومن المفيد ضبطه. في Ubuntu 24.04 مع ImageMagick 6، يوجد الملف في /etc/ImageMagick-6/policy.xml. اطبع الإعداد المفعّل حالياً:
identify -list policyيوفّر المشروع policy في Documentation/Build/policy.xml، وهو نموذج جيد. فهو يمنع coders الخاصة بـPS وPS2 وPS3 وEPS وXPS وMVG، ويمنع delegates الخاصة بـURL وHTTPS وHTTP وgs، مع السماح بـPDF:
<policy domain="coder" rights="none" pattern="PS" />
<policy domain="coder" rights="none" pattern="MVG" />
<policy domain="delegate" rights="none" pattern="URL" />
<policy domain="delegate" rights="none" pattern="gs" />
<policy domain="coder" rights="read|write" pattern="PDF" />يُعد السطر gs هو الأهم. لا يحلل ImageMagick PostScript بنفسه. بل يشغّل Ghostscript كعملية خارجية، وهذا الـdelegate هو موضع ثغرات تنفيذ التعليمات البرمجية عن بُعد المعروفة في ImageMagick. عند منع الـdelegate، لن يمرر ImageMagick الملف المرفوع إلى gs إطلاقاً، مهما كان نوع الملف الذي يعلنه عن نفسه.
تضبط policy نفسها حدوداً للموارد، وبذلك تمنع صورة معدّة خصيصاً من استهلاك موارد الجهاز:
<policy domain="resource" name="memory" value="256MiB"/>
<policy domain="resource" name="map" value="512MiB"/>
<policy domain="resource" name="disk" value="1GiB"/>
<policy domain="resource" name="width" value="16KP"/>
<policy domain="resource" name="height" value="16KP"/>
<policy domain="resource" name="area" value="128MP"/>قنبلة فك الضغط هي ملف صغير يعلن عن أبعاد هائلة. ترفض حدود width وheight وarea هذا الملف قبل حدوث التخصيص، لذلك تنتهي العملية بدلاً من أن يضطر kernel إلى إنهاء عملية أخرى.
توجد مشكلة معاكسة أيضاً. تمنع policy الافتراضية في Ubuntu coder الخاصة بـPDF منعاً كاملاً، لذلك تفشل معالجة PDF في النظام غير المعدّل مع attempt to perform an operation not allowed by the security policy 'PDF'. تعني هذه الرسالة أن policy تؤدي وظيفتها. إن إعادة السماح بهذا coder قرار تتخذه عمداً، وعندها تُبقي delegate الخاص بـgs ممنوعاً.
تكلفة سلسلة التبعيات على VPS صغير
أثناء الخمول، لا يستهلك أيٌّ من هذه المكونات موارد كبيرة. يستهلك Apache وPHP بضع عشرات من الميغابايت، ولا تعمل ملفات converter الثنائية إطلاقاً. تظهر التكلفة كاملة دفعة واحدة عند وصول ملف.
تبدأ عملية تحويل المستند LibreOffice، الذي يبدأ بدوره Java runtime. ويمنح تحويل الصور ImageMagick مقدار 256 MiB من الذاكرة، إضافة إلى memory map بحجم 512 MiB وفقاً للسياسة السابقة. أما تحويل الفيديو، فيمنح FFmpeg جميع الأنوية المتاحة لديك، لأن هذه هي طريقة تعامل FFmpeg مع الفيديو. وتبلغ قيمة memory_limit الخاصة بـPHP مقدار 512M في إعدادات المشروع. تتراكم هذه القيم أثناء مهمة واحدة، فوق استهلاك نظام التشغيل وخادم الويب.
لذلك يبدأ VPS بسعة 1 GB باستخدام swap عند أول مستند فعلي، ثم يدخل في حالة thrashing. عند نفاد الذاكرة، ينهي kernel out of memory killer العملية ذات أكبر resident size. تكون تلك العملية عادةً soffice.bin، فيرى المستخدم أن التحويل فشل من دون رسالة مفيدة. وأحياناً تكون apache2، فيتوقف الموقع بالكامل. أكّد ذلك بعد وقوعه باستخدام dmesg -T | grep -i "killed process".
هذه إرشادات لتحديد الحجم وليست benchmark: تكون سعة 4 GB من RAM مع نواتين مريحة لفريق صغير، كما يعمل 2 GB مع swap file إذا كان الحمل يتكون من المستندات والصور وكنت تقبل الانتظار. لا يجعل swap file عملية التحويل أسرع. بل يجعل الزيادة المفاجئة في الحمل بطيئة بدلاً من أن تكون قاتلة، وهذا هو الفرق بين صفحة متوقفة وانقطاع كامل للخدمة. امنح القرص مساحة أكبر مما يبدو ضرورياً، لأن صورة بحجم 3 GB، وحداً كبيراً للرفع، والملف الناتج بعد التحويل تملأ القرص معاً قبل نفاد أي مورد آخر غالباً.
تتسم عمليات التحويل بطبيعتها بتحميل متقطع. سيستخدم شخصان يرفعان فيديو في الوقت نفسه جميع الأنوية، وينتظر الطلب التالي خلفهما. لا توجد job queue أمام هذه العملية، لذلك فإن وسيلة التحكم الوحيدة المتاحة لك هي الحدود.
حدّد الحدود التي تمنع عملية رفع واحدة من ملء القرص
خفّض قيم PHP أولاً. تُعدّ قيم مثل upload_max_filesize = 512M وpost_max_size = 512M وmax_file_uploads = 20 نقطة بداية مناسبة لخادم مشترك بسعة 4 GB. تذكّر أن max_execution_time = 1200 يسمح لطلب PHP واحد بالعمل لمدة عشرين دقيقة، وهو ما تحتاج إليه عملية تحويل فيديو طويلة فعلاً. وهذا يعني أيضاً أن عملية رفع بطيئة واحدة تشغل عاملاً لمدة عشرين دقيقة.
ثم طبّق حدود الحجم والمعدل في الـproxy، قبل أن يصل الطلب إلى PHP على الإطلاق:
limit_req_zone $binary_remote_addr zone=convert:10m rate=6r/m;
server {
listen 443 ssl;
server_name convert.example.com;
client_max_body_size 512M;
client_body_timeout 300s;
location / {
limit_req zone=convert burst=4 nodelay;
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 1200s;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}يجب أن تكون قيمة client_max_body_size مساوية على الأقل لحجم أكبر ملف تريد تحويله، وإلا سيرسل nginx الاستجابة 413 Request Entity Too Large ولن يرى PHP عملية الرفع. يجب أن تتجاوز قيمة proxy_read_timeout أطول عملية تحويل لديك، وإلا فستعيد مهمة تعمل بصورة سليمة خلف الـproxy الاستجابة 504 Gateway Time-out إلى المتصفح. يوضّح شرح إعداد nginx لـreverse proxy سطراً بسطر بقية كتلة الخادم، بما في ذلك إنهاء TLS (أمن طبقة النقل).
حذف الملفات المحوَّلة
تترك كل عملية تحويل نسخة من ملف حساس في دليل يمكن لخادم الويب قراءته. التنظيف هو ما يميز أداة التحويل عن أرشيف يضم كل ما حوّله أي شخص عليها.
تحدد $DeleteThreshold في Resources/config.php العمر بالدقائق الذي تنتهي بعده الجلسة، وقيمتها الافتراضية هي 60. خفّضها إلى 15 عندما يكون المحتوى حساساً. أما عملية التنظيف نفسها، فهي وسيطة لسطر الأوامر في النواة:
sudo -u www-data php /path/to/HRConvert2/convertCore.php -c
sudo -u www-data php /path/to/HRConvert2/convertCore.php -c=15تحذف -c الجلسات المنتهية من موقعي البيانات باستخدام الحد المكوَّن. وتستخدم -c=15 مدة خمس عشرة دقيقة لهذه العملية فقط. تحذف -c=now كل جلسة بصرف النظر عن عمرها، بما في ذلك الجلسة التي يستخدمها أحد المستخدمين للتحويل في تلك اللحظة، لذلك احتفظ بها لأغراض الصيانة. تعمل الوسيطات نفسها داخل الحاوية عبر docker exec.
أضف عملية التنظيف إلى مؤقت حتى لا تعتمد على تحميل أحدهم لصفحة. يكفي سطر في /etc/cron.d/hrconvert2:
*/10 * * * * www-data php /path/to/HRConvert2/convertCore.php -cتحقق بعد بضع دقائق باستخدام ls /DATA/HRConvert2، وراقب اختفاء أدلة الجلسات القديمة. بما أن مستخدم خادم الويب يملك هذا الدليل، فهذا الحساب هو بالضبط الحساب الذي سيحصل عليه المهاجم إذا استغل محلل الملفات. لذلك يجب ألا يملك أي موارد أخرى مهمة. يُعد حسابات المستخدمين بأقل قدر من الامتيازات على VPS النمط العام، وينطبق هنا بدرجة أكبر من المعتاد.
ضعه خلف المصادقة ما لم يكن الهدف إتاحته للعامة
لا يتضمن التثبيت الافتراضي أي حسابات، وهذا مقصود. يمكن لأي شخص يستطيع الوصول إلى الصفحة تحميل ملف وتشغيل ملفات converter الثنائية لديك، ولا تؤدي حدود المعدل إلا إلى إبطاء ذلك. لذلك حدّد الحالة التي تنطبق عليك.
إذا كان الاستخدام لك ولعدد قليل من الزملاء، فلا تعرّضه للإنترنت إطلاقاً. اربط الحاوية بواجهة loopback كما هو موضح أعلاه، ثم صِل إليها عبر شبكة خاصة أو نفق SSH. لن يتمكن أي شيء على الإنترنت العام من إرسال ملف إليها، وبذلك تزيل سطح الهجوم بالكامل بدلاً من تصفيته. وإذا احتاج هؤلاء الزملاء إلى فتحها في متصفح من دون نشر اسم مضيف أو فتح منفذ، فإن تقديمها كخدمة onion من الإصدار v3 يُبقي converter مربوطاً بواجهة loopback، ويوفّر لهم عنواناً يمكنهم زيارته.
إذا كان يجب الوصول إليها من متصفح، فضع المصادقة أمام proxy. يتطلب Basic auth أمرين فقط، ويمنع نموذج التحميل عن الغرباء:
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd alicelocation / {
auth_basic "Converter";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:8080;
}أعد تحميل nginx وافتح الصفحة. ظهور مطالبة يعني أن الإعداد يعمل، وعدم ظهورها يعني أن كتلة location التي عدّلتها ليست الكتلة التي تعالج الطلب. ولإنشاء حسابات فعلية بدلاً من استخدام كلمة مرور مشتركة، أنهِ الاتصال لدى موفّر single sign-on: يوفّر لك خادم Authentik SSO مستضافاً ذاتياً مصادقة أمامية أمام تطبيق لا يملك وظيفة تسجيل دخول خاصة به.
إذا كان الهدف هو إتاحة converter للعامة فعلاً، فتقبّل ما يعنيه ذلك وخطّط له. افترض أن sandbox سيتعرض للفحص. ثبّت وسم image، وأبقِ سياسة ImageMagick صارمة، واجعل حدود التحميل صغيرة، وشغّله على VPS لا يحتوي على أي شيء آخر تهتم بحمايته.
أنماط الفشل والرسائل التي ستراها
تفشل كل عمليات التحويل فوراً. يتعذّر إنشاء بيئة العزل. في التثبيت العادي، يكون السبب هو ملف تعريف AppArmor. وفي Docker، يكون السبب هو --security-opt seccomp=unconfined المفقود. يذكر التطبيق ذلك صراحةً: A sandbox blocks the required syscalls unless it was started with the correct options. ويشير إلى See --Require Sandbox-- & --Require Sandbox On Docker-- in config.php.
تفشل تحويلات الصور فقط. يعني Bubblewrap is missing or non functional, so this image conversion cannot be isolated! أن bwrap مفقود أو غير متاح ضمن المسار الذي يملكه مستخدم خادم الويب.
يفشل تنسيق واحد وتعمل التنسيقات الأخرى. يظهر الملف التنفيذي المفقود بوضوح في الرسالة: ImageMagick may not be installed, or may not be reachable on the system path used by the web server user. توجد الرسالة نفسها مع FFmpeg وLibreOffice. شغّل convertCore.php -v لمعرفة ما يستطيع التثبيت العثور عليه، وتذكّر أن قيمة PATH لدى عامل Apache ليست قيمة PATH لدى shell تسجيل الدخول.
تفشل معالجة PDF بسبب خطأ في السياسة. يأتي attempt to perform an operation not allowed by the security policy 'PDF' من policy.xml الخاص بـImageMagick، وليس من HRConvert2.
تعيد عمليات الرفع الكبيرة الرمز 413. قيمة client_max_body_size في nginx أصغر من حجم الملف. توجد 3 حدود في سلسلة المعالجة: حد واحد في nginx وحدّان في PHP، وتُطبَّق أصغر قيمة بينها.
تتوقف عمليات التحويل دون حدوث تغيير واضح. The device where data is stored has an insufficient amount of storage space available. تحقّق من المساحة الحرة، وتحقّق من أن مهمة التنظيف الدورية تعمل فعلاً.
يظهر تحذير بشأن التنظيف في السجل. Could not clean the temporary location! وCould not clean the convert location! مشكلتا ملكية. يجب أن يملك مستخدم خادم الويب الدليل الذي يحدده $ConvertLoc.
FAQ
هل من الآمن إتاحة محوّل ملفات مستضاف ذاتياً على الإنترنت؟
يكون ذلك آمناً بدرجة كافية فقط إذا تعاملت معه على أنه محلّل ملفات معروض على أشخاص مجهولين. يُمرَّر كل ملف مرفوع إلى LibreOffice أو ImageMagick أو FFmpeg أو Ghostscript، ويختار الشخص الذي يرفع الملف الأداة المستخدمة. يشغّل HRConvert2 هذه الأدوات داخل مساحة أسماء bubblewrap من دون شبكة، مع دليل إدخال للقراءة فقط. كما يرفض أي تحويل لا يستطيع وضعه داخل sandbox، وهذا إعداد افتراضي قوي. مع ذلك، من الأفضل أن تطلب المصادقة، وأن تبقي حدود الرفع منخفضة، وأن تشغّله على VPS لا يحتوي على أي بيانات أخرى مهمة.
لماذا يفشل كل تحويل عند تثبيت Ubuntu 24.04 حديثاً؟
يقيّد Ubuntu 24.04 وDebian 12 مساحات أسماء المستخدمين غير ذوي الامتيازات، ويحتاج bubblewrap إلى واحدة منها لإنشاء sandbox. ولأن التطبيق يرفض إجراء التحويل من دون sandbox، تفشل كل مهمة بدلاً من فشل بعضها. اكتب ملف تعريف AppArmor لـ /usr/bin/bwrap باستخدام flags=(unconfined)، وحمّله باستخدام sudo apparmor_parser -r /etc/apparmor.d/bwrap، ثم تحقّق منه باستخدام bwrap --ro-bind / / --dev /dev /bin/true.
لماذا تفشل التحويلات في Docker لكنها تعمل في تثبيت عادي؟
يحظر ملف seccomp الافتراضي في Docker استدعاءات النظام التي يستخدمها bubblewrap، لذلك لا يمكن إنشاء sandbox داخل الحاوية. شغّلها باستخدام --security-opt seccomp=unconfined، فهذا هو الأمر الذي يستخدمه المشروع نفسه للتشغيل. لاحظ أن $RequireSandboxOnDocker تكون FALSE افتراضياً، لذلك قد تنفّذ حاوية لم تُضبط بهذا الخيار تحويلات من دون sandbox على الإطلاق. اضبطها على TRUE بعد تفعيل خيار seccomp.
ما مقدار RAM الذي يحتاج إليه خادم تحويل الملفات؟
يكون استهلاك الذاكرة منخفضاً أثناء الخمول، لكن التحويل الفعلي يختلف. يشغّل LibreOffice بيئة تشغيل Java، ويستهلك ImageMagick مقدار 256 MiB من الذاكرة وخريطة بحجم 512 MiB وفق السياسة المرفقة، كما أن حد PHP نفسه هو 512M. على VPS بسعة 1 GB، يؤدي هذا المزيج إلى استخدام swap، وينهي قاتل نفاد الذاكرة soffice.bin أو apache2. خطط لاستخدام 4 GB ونواتين لفريق صغير، وافحص dmesg -T | grep -i "killed process" كلما توقف تحويل من دون رسالة.
أين تُحفظ الملفات المحوّلة، ومتى تُحذف؟
تُحفظ في دليل العمل الذي يحدده $ConvertLoc في Resources/config.php، وتكون قيمته الافتراضية /DATA/HRConvert2. يحدد $DeleteThreshold عمر الجلسة بالدقائق قبل انتهائها، وتكون قيمته الافتراضية 60. تُنفَّذ عملية التنظيف من سطر الأوامر: يمسح php convertCore.php -c الجلسات المنتهية، بينما يمسح -c=now كل الجلسات فوراً، بما فيها الجلسات النشطة. أضف -c إلى مهمة cron أو مؤقت systemd حتى لا يعتمد الحذف على زيارة أي شخص للموقع.