دليل فني | التنصيب والتشغيل على خادم الجهة
دليل التشغيل الآمنكيف تُنصَّب المنظومة على خادمكم، ولماذا كل خطوة فيها كذلك
هذا الدليل مكتوب من إعداد تشغيلي قائم ويعمل اليوم، لا من قالب عام. كل خطوة فيه مشروحة بسببها: ماذا تفعل، ولماذا بهذا الترتيب، وما الذي يحميه. الهدف أن يستطيع فريقكم التقني تشغيل المنظومة ومراجعتها دون الرجوع إلينا.
قاعدة البيانات لا تُنشر على الإنترنت إطلاقًا.أول قرار في هذا الإعداد
البنية
كيف تتركّب المنظومة
المنظومة أربع طبقات، لكل واحدة دور واحد. أهم ما في الرسم ليس ما يتصل بما، بل ما لا يتصل بالإنترنت أصلًا.
| الطبقة | ما هي | الدور والقرار الأمني |
|---|---|---|
| 1. البوابة | موزِّع أحمال + شهادة TLS | الطبقة الوحيدة المنشورة. تنهي التشفير، تضيف ترويسات الأمان، وتمرّر للتطبيق. |
| 2. التطبيق | حاوية PHP + Apache | تشغّل الكود. لا تُفتح من الإنترنت مباشرة — فقط عبر البوابة. |
| 3. قاعدة البيانات | MySQL على شبكة داخلية | بلا منفذ عام. لا يمكن الوصول إليها من خارج الخادم بأي حال. |
| 4. التخزين الدائم | أقراص مرتبطة بالحاوية | المرفقات والمستندات ومفتاح التطبيق والنسخ الاحتياطية — تبقى عبر التحديثات. |
قرار التصميم الأهم: المنشور للإنترنت هو المنفذ 443 فقط، وعلى البوابة وحدها. قاعدة البيانات والتطبيق يتخاطبان على شبكة داخلية مغلقة لا تملك عنوانًا عامًا. يعني أن محاولة الاتصال بقاعدة البيانات من خارج الخادم لا تفشل بكلمة مرور خاطئة — بل لا تجد منفذًا تتصل به أصلًا.
وجذر الموقع مقصور على مجلد واحد: الخادم لا يقدّم إلا محتويات public/. الكود والإعدادات وملفات الترحيل والسجلات والمرفقات الحسّاسة كلها خارج هذا المجلد، فلا يوجد رابط يصل إليها مهما كان.
لماذا الفصل مهم عمليًا: أغلب تسريبات قواعد البيانات تحدث لأن القاعدة كانت منشورة على الإنترنت بكلمة مرور ضعيفة أو افتراضية. هذا الاحتمال مغلق هنا بالبنية نفسها، لا بالاعتماد على قوة كلمة المرور.
المواصفات
ما يحتاجه الخادم فعلًا
الأرقام التالية مبنية على قياس حقيقي للمنظومة تحت ضغط، لا على تقدير. القياس جرى على خادم مشترك محمَّل، فالمواصفة المخصَّصة أدناه تعطي هامشًا مريحًا.
| البند | الحد الأدنى | الموصى به | لماذا |
|---|---|---|---|
| المعالج | 4 أنوية | 8 أنوية | العرض يعتمد على المعالج أساسًا. 8 أنوية تكفي لعشرات الموظفين معًا. |
| الذاكرة | 8 جيجابايت | 16 جيجابايت | التطبيق وقاعدة البيانات معًا، مع مساحة للتقارير الكبيرة. |
| القرص | 80 جيجابايت SSD | 200 جيجابايت SSD | القاعدة والمرفقات والنسخ الاحتياطية. المرفقات تنمو مع الوقت. |
| النسخ الاحتياطية | مساحة منفصلة | خارج نفس الخادم | نسخة على نفس القرص لا تحمي من فقد القرص. |
| النظام | Linux حديث + Docker | نفسه | المنظومة تعمل كحاويات، فالتوزيعة لا تهم كثيرًا. |
للتوسّع لاحقًا: المنظومة تعمل كحاويات خلف موزِّع أحمال، فزيادة الطاقة تكون بتشغيل نسخ متوازية من التطبيق لا بتغيير الكود. الشرط الوحيد قبل تشغيل أكثر من نسخة هو نقل تخزين الجلسات إلى مخزن مشترك (Redis أو جدول في القاعدة) بدلًا من ملفات داخل الحاوية — وإلا توزّع الطلبات بين النسخ وتضيع الجلسات.
نوصي بالبدء بنسخة واحدة على المواصفة الموصى بها، ومراقبة زمن الاستجابة لشهر. التوسّع قرار تتخذه الأرقام، لا التوقّع.
العزل الشبكي
ما يُنشر للعالم، وما يبقى في الداخل
قاعدة الإعداد: لا يُنشر شيء إلا إذا كان لا بد من نشره.
| المنفذ / الواجهة | الحالة | الملاحظة |
|---|---|---|
| HTTPS — منفذ 443 | مفتوح | المدخل الوحيد. شهادة تُجدَّد تلقائيًا. |
| HTTP — منفذ 80 | تحويل فقط | يحوّل إلى HTTPS ولا يقدّم محتوى. |
| قاعدة البيانات — منفذ 3306 | مغلق تمامًا | بلا منفذ عام. داخلي فقط. |
| SSH — منفذ 22 | للإدارة فقط | نوصي بحصره على عناوين فريق التقنية، وبمفتاح لا كلمة مرور. |
| لوحة الإدارة | نطاق منفصل | نوصي بحمايتها بكلمة مرور قوية وتقييد عناوين الوصول. |
وعلى مستوى الملفات داخل الخادم، الإعداد يمنع صراحةً: تشغيل أي ملف يُرفع كبرنامج (حتى لو نجح أحد في رفع ملف تنفيذي، لن يُنفَّذ)، وفتح مجلدات الموارد البشرية والتقارير الطبية وعقود النشاط وإثباتات المخالفات بالرابط المباشر، وقراءة أي ملف إعدادات أو نسخة احتياطية أو سجل تُرك داخل المجلد العام، وعرض محتويات المجلدات.
الترويسات الأمنية (سياسة المحتوى، وإلزام التشفير لسنة، ومنع التأطير، ومنع تخمين نوع الملف) مضبوطة في طبقتين: على البوابة وداخل التطبيق نفسه — فلو أُعيد نشر التطبيق خلف بوابة أخرى تبقى الحماية معه.
الخطوات
من خادم فارغ إلى منظومة تعمل
الخطوات بالترتيب. الترتيب مقصود: لا تُشغَّل المنظومة قبل ضبط الأسرار وتثبيت التخزين الدائم.
- جهّز الخادمنظام Linux محدَّث، مع Docker. أغلق كل المنافذ عدا 443 و80 و22 المقيَّد.
- شغّل طبقة البوابةموزِّع الأحمال مع إصدار شهادة TLS تلقائيًا للنطاق، وتفعيل إجبار HTTPS.
- أنشئ قاعدة البيانات كخدمة داخليةMySQL بقرص دائم مرتبط بمجلد بياناتها، ودون نشرها كتطبيق ويب — هذه الخانة هي الفرق بين قاعدة داخلية وقاعدة مكشوفة.
- أنشئ مستخدم قاعدة بيانات للتطبيقمستخدم مخصَّص لقاعدة المنظومة وحدها بكلمة مرور قوية — لا تستخدم حساب الجذر. صلاحياته: قراءة وكتابة وتعديل البنية على قاعدته فقط.
- اربط الأقراص الدائمةقرص لـ
storageوآخر لـpublic/uploads. بدونهما تضيع المرفقات ومفتاح التطبيق مع أول تحديث. - اضبط متغيّرات البيئةبيانات الاتصال بالقاعدة، والنطاق، و
APP_ENV=productionوAPP_DEBUG=false. راجع فصل «الأسرار» قبل هذه الخطوة. - انشر التطبيقادفع الكود أو الصورة. الحاوية عند إقلاعها تكتب ملف البيئة من المتغيّرات، ثم تنتظر قاعدة البيانات، ثم تشغّل ملفات الترحيل تلقائيًا، ثم تبدأ الخدمة.
- تحقق قبل التسليمافتح الموقع، سجّل الدخول، وشغّل قائمة التحقق في آخر هذا الدليل.
ملفات الترحيل تعمل من تلقاء نفسها وبأمان: تُنفَّذ مرة واحدة ومسجَّلة، ومكتوبة لتتحمّل إعادة التشغيل على قاعدة فارغة أو مليئة دون أثر جانبي. لا حاجة لتشغيل أوامر قاعدة بيانات يدويًا عند التحديث.
الأسرار والمفاتيح
أين تُحفظ المفاتيح، ومن يملكها
السر الذي يوجد في مكانين هو سر في مكان واحد زيادة. هذه قواعدنا، ومنها واحدة نوصي الجهة بتنفيذها بنفسها دون أن نعرف نتيجتها.
| السر | أين يُحفظ | الملاحظة |
|---|---|---|
| كلمة مرور قاعدة البيانات | متغيّر بيئة على الخادم | لا تُكتب في الكود ولا في مستودع المصدر. تُحقن عند التشغيل. |
| مفتاح التطبيق | ملف داخل القرص الدائم بصلاحية 600 | يُولَّد تلقائيًا أول مرة. يشفّر سرّ التحقق بخطوتين والنسخ الاحتياطية. |
| كلمات مرور الموظفين | بصمة bcrypt داخل القاعدة | لا رجعة فيها. لا أحد — ولا نحن — يستطيع استخراجها. |
| مفاتيح مزوّد الرسائل | متغيّرات بيئة | ومحجوبة من سجل المراجعة ومن شاشات الإعدادات. |
خطوة نوصي بها عند التسليم، وتنفّذونها أنتم: غيّروا كلمة مرور قاعدة البيانات بعد استلام الخادم، وأنشئوا مستخدمًا مخصَّصًا للتطبيق بدل حساب الجذر، ولا تشاركونا الكلمة الجديدة. بهذا يصبح الوصول للبيانات بيد الجهة وحدها — وهذا هو الوضع الصحيح لمنظومة حكومية.
وللحسابات الإدارية: فعّلوا التحقق بخطوتين لحسابات مديري النظام (المنظومة تدعمه وتستطيع إلزامه)، واحذفوا أي حساب تجريبي قبل التشغيل الفعلي، وراجعوا شاشة الأدوار لتتأكدوا أن كل دور يملك أقل صلاحية تكفي عمله.
النسخ الاحتياطي
النسخة التي تُؤخذ وحدها، وتُستعاد عند الطلب
النسخة الاحتياطية التي لم تُجرَّب استعادتها ليست نسخة احتياطية. هذا ما تفعله المنظومة تلقائيًا، وهذا ما نوصيكم بإضافته.
- تُؤخذ يوميًا دون تدخّلمهمة مجدولة كل ليلة تأخذ نسخة كاملة بمعاملة واحدة متسقة — أي أن النسخة تمثّل لحظة واحدة من عمر القاعدة، لا خليطًا من لحظات.
- تُضغط ثم تُشفَّرتشفير AES-256-GCM بمفتاح مشتق من مفتاح التطبيق المحفوظ خارج القاعدة. نسخة مسروقة بلا المفتاح لا تُقرأ.
- تكشف العبثلو تغيّر بايت واحد في الملف، الاستعادة ترفضه بدل أن تُخرج بيانات تالفة بصمت. الصمت هو الخطر الحقيقي في النسخ الاحتياطية.
- تُنظَّف تلقائيًاتُحفظ نسخ أسبوعين، مع الإبقاء على آخر ثلاث نسخ دائمًا مهما كان عمرها.
- تُستعاد بأمر واحدأمر يفك النسخة إلى ملف قاعدة بيانات جاهز للتحميل. جُرِّبت على القاعدة الفعلية: 442 جدولًا و459 ميجابايت صارت 47 ميجابايت مشفَّرة في أقل من دقيقة، واستُعيدت كاملة.
| الأمر | ماذا يفعل |
|---|---|
php cli.php backup:run | أخذ نسخة مشفَّرة الآن |
php cli.php backup:list | عرض النسخ الموجودة وتواريخها وأحجامها |
php cli.php backup:restore <file> | فك نسخة إلى ملف SQL جاهز |
php cli.php audit:verify | التحقق من سلامة سجل المراجعة |
التوصية المكمِّلة: انسخوا ملفات النسخ الاحتياطية إلى مكان خارج الخادم (تخزين آخر أو خادم ثانٍ). النسخة الموجودة على نفس القرص تحمي من الخطأ البشري، لكنها لا تحمي من فقد الخادم نفسه.
وجرّبوا الاستعادة مرة كل ربع سنة على قاعدة اختبار منفصلة. هذه التجربة هي الفرق بين «عندنا نسخ احتياطي» و«نعرف أننا نستطيع العودة».
التحديث والنشر
كيف ينزل تحديث دون أن يتوقف العمل
التحديث يبني نسخة جديدة كاملة ثم يبدّلها بالقديمة. لا يُعدَّل شيء على خادم يعمل.
- تُبنى صورة جديدةمن الكود المعتمد، بنسخة ثابتة من كل المكتبات.
- تُشغَّل وتُفحصالحاوية الجديدة تقلع، تشغّل ملفات الترحيل، وتتأكد أنها تستجيب.
- يتم التبديلالبوابة تحوّل الطلبات إلى النسخة الجديدة، والقديمة تُوقَف بعدها.
- والرجوع متاحالنسخ السابقة محفوظة، والرجوع إليها قرار من لوحة الإدارة.
ما لا يتأثر بالتحديث: قاعدة البيانات، والمرفقات، ومفتاح التطبيق، والنسخ الاحتياطية — كلها على أقراص دائمة منفصلة عن الحاوية. الحاوية قابلة للاستبدال بالكامل؛ البيانات لا.
المتابعة
ما يستحق نظرة أسبوعية
لائحة قصيرة عمدًا. المتابعة التي تطول لا تُنفَّذ.
| ما تتابعه | كل | لماذا يهم |
|---|---|---|
| مساحة القرص | أسبوعيًا | امتلاء القرص يوقف النسخ الاحتياطي والتحديثات معًا. |
| نجاح النسخة الليلية | أسبوعيًا | تأكد أن آخر نسخة بتاريخ أمس وحجمها معقول. |
| سلامة سجل المراجعة | شهريًا | أمر التحقق يؤكد أن السلسلة لم تُمس. |
| محاولات الدخول الفاشلة | أسبوعيًا | تكرار غير معتاد من عنوان واحد يستحق النظر. |
| الجلسات النشطة | عند الحاجة | شاشة الإدارة تعرضها وتسمح بإنهاء أي جلسة فورًا. |
| زمن الاستجابة | شهريًا | ارتفاعه التدريجي هو إنذار التوسّع المبكر. |
المنظومة تسجّل الطلبات البطيئة وتكرار الاستعلامات غير الطبيعي في سجلاتها تلقائيًا — فالمتابعة غالبًا قراءة، لا بحث.
قائمة التحقق
قبل أن تقولوا: بدأنا التشغيل
قائمة تُعلَّم بندًا بندًا. كل بند فيها إما تحقَّق أو لم يتحقق — لا منطقة رمادية.
| البند | كيف تتأكد |
|---|---|
| الموقع يعمل على HTTPS وشهادته سارية | افتح النطاق وتأكد من القفل في المتصفح |
| قاعدة البيانات غير منشورة على الإنترنت | حاول الاتصال بها من خارج الخادم — يجب أن يفشل |
| كلمة مرور قاعدة البيانات غُيِّرت بعد التسليم | ومستخدم التطبيق ليس حساب الجذر |
APP_DEBUG=false وAPP_ENV=production | تأكد أن صفحات الخطأ لا تُظهر تفاصيل تقنية |
| الأقراص الدائمة مرتبطة | ارفع مرفقًا، حدّث التطبيق، وتأكد أنه ما زال موجودًا |
| النسخة الاحتياطية الليلية تعمل | php cli.php backup:list يُظهر نسخة بتاريخ أمس |
| جُرِّبت استعادة نسخة مرة واحدة | على قاعدة اختبار، قبل الاعتماد عليها |
| النسخ تُنسخ خارج الخادم | إلى تخزين أو خادم آخر |
| التحقق بخطوتين مفعَّل لحسابات الإدارة | ومُلزَم لمديري النظام |
| الحسابات التجريبية حُذفت | ولا يوجد حساب بكلمة مرور افتراضية |
| الأدوار روجعت | كل دور يملك أقل صلاحية تكفي عمله |
| سجل المراجعة سليم | php cli.php audit:verify يؤكد السلامة |
نسلّم هذه القائمة موقَّعة مع المنظومة. ما لم يتحقق منها يُذكر صراحةً بدل أن يُفترض.