انتقل إلى المحتوى الرئيسي

تمرين 2 – إدارة مواقع ويب متعددة باستخدام reverse proxy (وكيل عكسي) في بيئة Linux

جدول المحتويات​


السياق​

أنت مسؤول نظام في شركة خدمات رقمية. مهمتك هي تكوين بيئة محلية تستضيف ثلاثة مثيلات مستقلة من Wiki.js، كل منها يمثل بيئة تطوير برمجيات كلاسيكية:

  • بيئة التطوير (dev.site1.local)
  • بيئة الاختبار (test.site1.local)
  • بيئة الإنتاج (prod.site1.local)

يجب تثبيت كل مثيل من Wiki.js يدويًا على جهاز واحد يعمل بنظام Ubuntu Server 24.04 LTS، متصل بقاعدة بيانات MariaDB الخاصة به ومكشوف عبر reverse proxy NGINX.


أهداف الاختبار​

  • إتقان التثبيت اليدوي لمحرك wiki قائم على Node.js
  • إدارة قواعد بيانات SQL منفصلة بشكل صحيح
  • أتمتة بدء الخدمات عبر systemd
  • تكوين reverse proxy HTTP مع نطاقات فرعية داخلية
  • تشخيص أخطاء النشر الشائعة
  • تطبيق أفضل الممارسات في مجال عزل الخدمة

العودة إلى جدول المحتويات


التعليمات العامة​

  • تعمل على جهاز افتراضي واحد يعمل بنظام Ubuntu 24.04
  • يجب أن تكون جميع المثيلات مستقلة، بدون تعارض في المنافذ
  • لا يجب أن يكون أي خادم مكشوفًا مباشرة: فقط الوكيل NGINX يستمع على المنفذ 80
  • يجب أن تعمل العناوين *.site1.local عبر /etc/hosts
  • يجب عليك اتباع نهج احترافي، مع هيكلية ووضوح ودقة

العودة إلى جدول المحتويات


الجزء 1 – تثبيت وتكوين WIKI.JS (40 نقطة)​

  1. أنشئ ثلاثة مستخدمين مخصصين في Linux: wikijs_dev, wikijs_test, wikijs_prod

  2. أنشئ ثلاث قواعد بيانات منفصلة تحت MariaDB:

    • wikidb_dev, wikidb_test, wikidb_prod
  3. قم بتثبيت Wiki.js يدويًا في:

    • /var/www/dev.site1
    • /var/www/test.site1
    • /var/www/prod.site1
  4. عدل ملف config.yml لكل مثيل:

    • منفذ مختلف (3000, 3001, 3002)
    • bindIP: 127.0.0.1
    • معلومات اتصال صحيحة بقاعدة البيانات
  5. أنشئ وفعّل خدمات systemd:

    • wikijs-dev.service, wikijs-test.service, wikijs-prod.service

العودة إلى جدول المحتويات


الجزء 2 – تكوين REVERSE PROXY NGINX (30 نقطة)​

  1. قم بتكوين NGINX لخدمة النطاقات الفرعية التالية:
اسم المضيفالمنفذ الداخليالمسار المحلي
dev.site1.local3000/var/www/dev.site1
test.site1.local3001/var/www/test.site1
prod.site1.local3002/var/www/prod.site1
  1. عدل /etc/hosts لتوجيه هذه النطاقات إلى 127.0.0.1

  2. اختبر الوصول إلى المواقع باستخدام متصفح أو curl

العودة إلى جدول المحتويات


الجزء 3 – التحقق، استكشاف الأخطاء وإصلاحها والتحليل (30 نقطة)​

  1. صحح الأخطاء التالية إذا ظهرت:

    • سوء تنسيق YAML
    • مشاكل اتصال MariaDB
    • منفذ مشغول بالفعل
    • حقوق ملفات غير كافية
  2. برر القرارات التالية:

    • لماذا تستخدم مستخدمين مختلفين لكل Wiki.js؟
    • لماذا تفضل reverse proxy بدلاً من التعرض المباشر؟
    • ما هي مخاطر الأمان إذا تم كشف المنافذ بدون NGINX؟
  3. اقترح طريقة لتأمين التثبيت باستخدام HTTPS:

    • استخدام certbot
    • تكوين bindIP
    • دور DNS العام

العودة إلى جدول المحتويات


الجزء 4 – سؤال التحليل المعماري (10 نقاط)​

البيان​

هناك نهجان ممكنان لكشف عدة بيئات:

النهج A : نطاقات فرعية → http://dev.site1.local, http://test.site1.local, http://prod.site1.local

النهج B : مسارات داخلية → http://site1.local/dev, http://site1.local/test, http://site1.local/prod

السؤال​

  1. قارن بين النهجين:

    a) الآثار التقنية الرئيسية (4 نقاط) b) حالات الاستخدام حيث يكون النهج B مقبولًا، ومتى يكون غير مستحسن (3 نقاط) c) أي نهج توصي به ولماذا؟ (3 نقاط)

العودة إلى جدول المحتويات


جدول التقييم​

المعاييرالنقاط
Wiki.js (x3) مثبت ويعمل15
قواعد بيانات منفصلة10
تكوين config.yml صحيح10
خدمات systemd تعمل5
تم تكوين NGINX reverse proxy15
/etc/hosts محرر بشكل صحيح5
تشخيص وحل الأخطاء10
تبرير تقني10
اقتراح HTTPS مدعوم10
المجموع90
تحليل الهيكليةالنقاط
عرض الفروقات2
حالات الاستخدام لكل نهج2
تحليل المخاطر والتوافق2
توصية واضحة ومدعومة4
المجموع الفرعي10

الوحدة الإضافية 1 – مستخدمو النظام مقابل المستخدمين العاديين (البشريين) على Linux​

اتفاقية UID على Linux​

في معظم توزيعات Linux الحديثة، يتم تصنيف المستخدمين وفقًا لـ UID (معرف المستخدم):

نطاق UIDنوع الحسابأمثلة
0المستخدم الجذرroot
1 – 999حسابات النظام / الخدماتdaemon, www-data, sshd, systemd-*, apache
≥ 1000مستخدمون عاديون (بشريون)alice, bob, etudiant
معلومات

يتم تحديد هذا النطاق في ملف /etc/login.defs لتوزيعتك. ليست قاعدة عالمية، ولكنها اتفاقية معتمدة على نطاق واسع (Debian, Ubuntu, RHEL, Fedora, إلخ).

كيفية التحقق من النطاقات على جهازك​

# عرض نطاقات UID المحددة على توزيعتك
grep -E '^(UID_MIN|UID_MAX|SYS_UID_MIN|SYS_UID_MAX)' /etc/login.defs

نتيجة نموذجية على Ubuntu:

SYS_UID_MIN    100
SYS_UID_MAX 999
UID_MIN 1000
UID_MAX 60000

حسابات النظام (UID < 1000) – الخصائص​

تم إنشاء حسابات النظام لتشغيل الخدمات/الشياطين، وليس للاتصالات البشرية.

المؤشرات النموذجية لحساب النظام:

  • UID منخفض (< 1000)
  • Shell = /usr/sbin/nologin أو /bin/false (لا يوجد اتصال تفاعلي)
  • لا يوجد مجلد home حقيقي للمستخدم (أو home "تقني")
  • تم إنشاؤه باستخدام useradd -r (علامة حساب النظام)

أمثلة شائعة:

الحسابالخدمةUID نموذجيShell
rootالمستخدم الجذر0/bin/bash
www-dataApache / Nginx (Debian/Ubuntu)33/usr/sbin/nologin
apacheApache (RHEL/CentOS)48/sbin/nologin
sshdخادم SSH105/usr/sbin/nologin
mysqlMariaDB / MySQL27/bin/false

تحقق سريع:

# عرض UID و shell لـ www-data
id www-data
getent passwd www-data
# النتيجة: uid=33(www-data) gid=33(www-data) groups=33(www-data)

حسابات عادية / بشرية (UID ≥ 1000) – الخصائص​

تم إنشاء الحسابات البشرية للأشخاص الذين يتصلون بالنظام.

المؤشرات النموذجية لحساب بشري:

  • UID ≥ 1000
  • Shell = /bin/bash أو /bin/sh
  • مجلد home في /home/<username>
  • تم إنشاؤه باستخدام useradd (بدون العلم -r) أو adduser

أوامر مفيدة لقائمة وتمييز أنواع المستخدمين​

قائمة المستخدمين البشريين (UID ≥ 1000):

UID_MIN=$(awk '/^UID_MIN/{print $2}' /etc/login.defs)
awk -F: -v m="$UID_MIN" '$3>=m {print $1" (uid="$3")"}' /etc/passwd | sort -t'=' -k2 -n

قائمة المستخدمين النظاميين (UID < 1000):

UID_MIN=$(awk '/^UID_MIN/{print $2}' /etc/login.defs)
awk -F: -v m="$UID_MIN" '$3<m {print $1" (uid="$3")"}' /etc/passwd | sort -t'=' -k2 -n

قائمة الحسابات بدون تسجيل دخول (عادةً للخدمات):

awk -F: '($7 ~ /(nologin|false)$/) {print $1" -> "$7}' /etc/passwd

قائمة الحسابات "البشرية المحتملة" (home في /home + shell bash/sh):

awk -F: '($6 ~ /^\/home\//) && ($7 ~ /(bash|sh)$/) {print $1" home="$6" shell="$7}' /etc/passwd

الرابط مع التمرين: لماذا wikijs_dev, wikijs_test, wikijs_prod هي حسابات نظام؟​

في هذا التمرين، تم إنشاء مستخدمي Wiki.js باستخدام الأمر:

sudo useradd -r -m -s /bin/bash wikijs_dev
sudo useradd -r -m -s /bin/bash wikijs_test
sudo useradd -r -m -s /bin/bash wikijs_prod
الخيارالدور
-rينشئ حساب نظام → UID مخصص في النطاق النظامي (< 1000)
-mينشئ دليل home (مفيد لملفات التكوين)
-s /bin/bashيحدد shell (هنا bash لتسهيل التصحيح في التمرين)
تلميح

إنه العلم -r الذي يحدث الفرق! بدون -r، سيكون الحساب مستخدمًا عاديًا (UID ≥ 1000). العلم -s يحدد فقط shell، ولا يجعل الحساب "نظاميًا".

هذه الحسابات هي "حسابات خدمة": هي مسؤولة عن تشغيل خدمات Wiki.js، كما هو محدد في ملفات systemd:

[Service]
User=wikijs_dev # ← الخدمة تعمل تحت هذا الحساب النظامي

تحقق:

# عرض UID المخصص (يجب أن يكون < 1000)
id wikijs_dev
id wikijs_test
id wikijs_prod

# عرض المستخدم الذي يشغل كل عملية Wiki.js
ps -eo user,pid,cmd | grep '[n]ode'

# تحقق من حالة الخدمة
systemctl status wikijs-dev

توصية في الإنتاج​

في الإنتاج، من الأفضل عدم إعطاء shell تفاعلي لحسابات الخدمة:

# أفضل ممارسة (shell nologin)
sudo useradd -r -m -s /usr/sbin/nologin wikijs_dev
sudo useradd -r -m -s /usr/sbin/nologin wikijs_test
sudo useradd -r -m -s /usr/sbin/nologin wikijs_prod

مع /usr/sbin/nologin، لا يمكن لأحد فتح جلسة تفاعلية مع هذا الحساب، ولكن systemd و sudo -u wikijs_dev <command> يعملان بشكل طبيعي. هذا هو مبدأ الأقل امتيازًا.

ملخص
  • useradd -r → حساب نظام (UID < 1000، مخصص لخدمة)
  • useradd (بدون -r) → حساب بشري (UID ≥ 1000، مخصص لشخص)
  • -s → يحدد shell، لا يغير نوع الحساب
  • حسابات wikijs_* في هذا التمرين هي حسابات نظام مسؤولة عن تشغيل خدمة Wiki.js
  • في الإنتاج: استخدم دائمًا -s /usr/sbin/nologin لحسابات الخدمة

العودة إلى جدول المحتويات


تم إنشاء التمرين في: ديسمبر 2024