استضافة HRConvert2 ذاتياً لتحويل الملفات بأمان
شغّل HRConvert2 على خادمك الخاص كي لا تصل ملفات العملاء إلى مواقع التحويل المجانية. تعرّف إلى تثبيت Docker أو Apache، والعزل بـ bubblewrap، وحدود الرفع والتنظيف.
لماذا تستضيف محوّل ملفات بنفسك
يُبقي محوّل الملفات المستضاف ذاتياً الملف على قرصك الخاص. هذا هو السبب الكامل لتشغيله. يأخذ موقع التحويل المجاني الملف المرفوع، ولا يتيح لك معرفة ما حدث له بعد ذلك. وعندما يكون الملف عقداً موقّعاً مع عميل أو سجلاً طبياً ممسوحاً ضوئياً، فإن رفعه بحد ذاته هو الحادث الأمني. HRConvert2 هو خادم لتحويل الملفات بالسحب والإفلات، مكتوب بلغة PHP ومرخّص بموجب GPLv3. أُصدرت النسخة 3.7.4 في 18 August 2026، ويذكر المشروع أنه يدعم 488 تنسيقاً.
لا يستخدم قاعدة بيانات أو حسابات أو ملفات cookies. يحصل كل مستخدم على مجلد مؤقت. تنفّذ أداة سطر أوامر محلية كل عملية تحويل: LibreOffice للمستندات، وFFmpeg للصوت والفيديو، وImageMagick للصور، وTesseract للتعرّف البصري على المحارف (OCR)، إضافةً إلى مجموعة كبيرة من الأدوات الأصغر التي تتولى بقية العمليات. يتولى HRConvert2 صفحة الرفع وخط المعالجة وعمليات التنظيف المرتبطة بهما.
يحوّل ملفاً من تنسيق إلى آخر. وليس حزمة office تعمل في المتصفح. لذلك، إذا كان ما تريده هو أن يحرّر الأشخاص المستندات في علامة تبويب، فقارن بين 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. تحقّق من مساحة القرص الحرة قبل تنفيذ pull.
تُعدّ الوسوم مهمة هنا. أحدث وسم نُشر على 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 لقواعد firewall الخاصة به.
ثبّته على 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هذا برنامج نصي من المورّد يُمرَّر إلى 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 على تشغيل كل تبعية داخل مساحة أسماء معزولة باستخدام bubblewrap. يرى كل تحويل مجلدين: المجلد الذي يحتوي على الإدخال، ويُركَّب للقراءة فقط، والمجلد الذي يستقبل الإخراج. وتكون الشبكة غير مشتركة، وبحسب صياغة المشروع، closes every URL handler in every dependency at once. وهذا أهم مما قد يبدو. يقبل كل من ImageMagick وGhostscript مراجع تجلب عنوان URL، وبذلك قد يتحول المحوِّل إلى أداة لطلب التزوير من جانب الخادم (SSRF)، للوصول إلى نقطة نهاية البيانات الوصفية السحابية من داخل شبكتك. عند تعطيل الشبكة داخل مساحة الأسماء، لا يمكن تنفيذ عملية الجلب.
أما الرفض فهو النصف الآخر: A server that cannot build a sandbox refuses the conversion rather than quietly running without one.. الأداة التي تفشل بطريقة آمنة أفضل من أداة تحذرك في سجل لا يقرأه أحد. وهذا يوضح أيضاً سبب عدم كون خطوة AppArmor أعلاه اختيارية، وسبب استحقاق $RequireSandboxOnDocker للمراجعة قبل تعريض الحاوية للإنترنت.
تدعيم ImageMagick باستخدام policy.xml
يُعد ملف policy الخاص بـImageMagick طبقة ثانية ضمن الـsandbox، ومن المفيد ضبطه. في 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 كعملية خارجية، ويكمن مصدر ثغرات تنفيذ التعليمات البرمجية عن بُعد المعروفة في ImageMagick داخل ذلك الـdelegate. عند منع الـ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"/>ملف decompression bomb هو ملف صغير يعلن عن أبعاد هائلة. ترفض حدود 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 بضع عشرات من الميغابايت، ولا تكون الملفات الثنائية الخاصة بالتحويل قيد التشغيل إطلاقاً. تظهر التكلفة كاملة دفعة واحدة عند وصول ملف.
يبدأ تحويل المستند LibreOffice، الذي يبدأ بدوره بيئة تشغيل Java. ويمنح تحويل الصور ImageMagick مقدار 256 MiB من الذاكرة، إضافةً إلى خريطة ذاكرة بحجم 512 MiB وفق السياسة السابقة. أما تحويل الفيديو، فيمنح FFmpeg جميع الأنوية المتاحة لديك، لأن هذه هي طريقة FFmpeg في معالجة الفيديو. وتبلغ قيمة memory_limit الخاصة بـPHP مقدار 512M في إعدادات المشروع. تتراكم هذه القيم أثناء مهمة واحدة، فوق استهلاك نظام التشغيل وخادم الويب.
لذلك يبدأ VPS بسعة 1 GB باستخدام swap عند أول مستند فعلي، ثم يدخل في حالة thrashing. وعند نفاد الذاكرة، ينهي قاتل نفاد الذاكرة في kernel العملية التي تملك أكبر حجم مقيم. تكون تلك العملية عادةً soffice.bin، ويرى المستخدم أن التحويل فشل من دون رسالة مفيدة. وأحياناً تكون apache2، فيتوقف الموقع بالكامل. يمكنك تأكيد ذلك بعد وقوعه باستخدام dmesg -T | grep -i "killed process".
هذه إرشادات لتحديد السعة وليست اختبار أداء: توفّر ذاكرة RAM بسعة 4 GB ونواتان راحةً لفريق صغير، كما يمكن استخدام 2 GB مع ملف swap إذا كان الحمل يقتصر على المستندات والصور وكنت تقبل الانتظار. لا يجعل ملف swap التحويل أسرع. بل يجعل الزيادة المفاجئة في الحمل بطيئة بدلاً من أن تكون قاتلة، وهذا هو الفرق بين صفحة متوقفة وانقطاع الخدمة. اترك على القرص مساحة أكبر مما تظن أنك تحتاج إليه، لأن صورة بحجم 3 GB، وحدّ رفع كبير، والملف الناتج عن التحويل تملأ القرص معاً قبل وقت طويل من نفاد أي مورد آخر.
تتسم عمليات التحويل بطبيعتها باندفاعية الحمل. سيستخدم شخصان يرفعان فيديو في الوقت نفسه جميع الأنوية، وسينتظر الطلب التالي خلفهما. لا توجد قائمة انتظار للمهام أمام هذه العملية، لذلك فإن وسيلة التحكم الوحيدة المتاحة لك هي الحدود.
اضبط الحدود التي تمنع عملية رفع واحدة من ملء القرص
خفّض قيم 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 إلى المتصفح. أما بقية كتلة الخادم، بما في ذلك إنهاء TLS (أمان طبقة النقل)، فتجد شرحها في إعداد reverse proxy في nginx مشروحاً سطراً بسطر.
حذف الملفات المحوّلة
تترك كل عملية تحويل نسخة من ملف حساس في دليل يستطيع خادم الويب قراءته. والتنظيف هو ما يميز أداة التحويل عن أرشيف يضم كل ما حوّله أي شخص عليها.
تحدد $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 النمط العام، وينطبق هنا بدرجة أكبر من المعتاد.
ضعه خلف المصادقة ما لم يكن الهدف إتاحته للعامة
لا يتضمن التثبيت الافتراضي أي حسابات، وهذا مقصود. يمكن لأي شخص يصل إلى الصفحة تحميل ملف وتشغيل الملفات التنفيذية الخاصة بالمحوّل، كما أن حدود المعدل تؤدي فقط إلى إبطاء ذلك. لذلك حدّد الحالة التي تنطبق عليك.
إذا كان الاستخدام لك ولعدد قليل من الزملاء، فلا تعرّضه للإنترنت إطلاقاً. اربط الحاوية بعنوان loopback كما هو موضح أعلاه، ثم صِل إليها عبر شبكة خاصة أو نفق SSH. عندئذ لن يتمكن أي شيء على الإنترنت العام من إرسال ملف إليها، وبذلك تزيل سطح الهجوم بالكامل بدلاً من تصفيته.
إذا كان يجب الوصول إليها من متصفح، فضع المصادقة أمام الـ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 مستضافاً ذاتياً مصادقة forward أمام تطبيق لا يوفّر تسجيل دخول خاصاً به.
إذا كان الهدف هو إتاحة المحوّل للعامة فعلاً، فتقبّل ما يترتب على ذلك وخطّط وفقاً له. افترض أن 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. تكون قيمة nginx client_max_body_size أصغر من حجم الملف. توجد ثلاثة حدود في سلسلة المعالجة: حد واحد في 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 من الذاكرة وmap بحجم 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 حتى لا يعتمد الحذف على زيارة أي شخص للموقع.