> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# Open edX مع Tutor: منصة مقررات مفتوحة MOOC على سيرفرك
- URL: https://arabroot.io/articles/تثبيت-open-edx-منصة-المقررات-المفتوحة-mooc/
- Published: 2026-10-14T08:00:00.000Z
- Updated: 2026-10-25T08:50:00.000Z
- Description: كيف تثبت Open edX بأداة Tutor، وتبني مقرراً وتسجل المتعلمين، وكم يحتاج السيرفر فعلاً قبل أن يكبر عدد المستخدمين.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, التعليم والبحث العلمي, تطبيقات لفريقك, الاستضافة الذاتية, Open edX

في مقال [أنظمة إدارة التعلم LMS](https://arabroot.io/articles/%D8%A7%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%85-lms-%D9%85%D8%A7%D8%B0%D8%A7-%D8%AA%D8%AD%D8%AA%D8%A7%D8%AC-%D9%85%D9%86%D9%87%D8%A7-%D9%85%D8%A4%D8%B3%D8%B3%D8%AA%D9%83/#open-edx) ذكرنا أن Open edX صمم أصلاً للمقررات المفتوحة MOOC التي يدخلها آلاف المتعلمين في وقت واحد، وأنه يحتاج من اليوم الأول ذاكرة أكبر من غيره، وفي [دليل Moodle](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-moodle-%D9%85%D9%86%D8%B5%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%B9%D9%84%D9%89-%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D9%83/) ثبتنا منصة تقوم على سيرفر ويب وقاعدة بيانات وContainer للمهام المجدولة، والسؤال الآن: كيف يبدو Open edX عندما تشغله بنفسك، وكم يحتاج فعلاً، وما الذي يفعله مصمم المقرر والمتعلم في أول يوم؟ وفي هذا المقال سوف نتناول:

- مكونات المنصة كما يشغلها Tutor، ولماذا هي أكثر من Moodle بكثير.
- التثبيت بأداة Tutor على Docker، مع ما حدث في أول تشغيل وكم استغرقت التهيئة Initialisation.
- بناء مقرر كملفات OLX واستيراده، وتسجيل متعلمين، ومتعلم يحل سؤالاً وتصل درجته إلى صفحة التقدم.
- العربية في الواجهة، واستهلاك الذاكرة وهو خامل، والنسخ الاحتياطي، والترقية، والتوسع Scaling.

## ما الذي تثبته عندما تثبت Open edX؟

[Open edX](https://openedx.org/?ref=arabroot.io) منصة مفتوحة المصدر مكتوبة بلغة Python وإطار Django، وكودها في مستودع [openedx-platform](https://github.com/openedx/openedx-platform?ref=arabroot.io) بترخيص AGPL-3.0، وهي ليست تطبيقاً واحداً وإنما مجموعة خدمات تعمل معاً، وأهم ما يجب أن تفهمه قبل التثبيت أنها مقسومة إلى منصتين: منصة التعلم LMS التي يدخلها المتعلم، والاستوديو Studio (ويسمى في الكود CMS) الذي يبني فيه الفريق المقررات، ولكل منهما نطاق مستقل وعملية مستقلة ومهام خلفية Worker مستقلة. والصورة التالية تبين ما يشغله Tutor على سيرفر واحد:

![مخطط مكونات Open edX كما يشغلها Tutor: المتعلم ومصمم المقرر يصلان إلى Caddy الذي يوزع الطلبات حسب النطاق إلى منصة التعلم LMS على local.openedx.io والاستوديو Studio على studio.local.openedx.io والواجهات الأمامية MFE على apps.local.openedx.io، ولكل من LMS وCMS عامل خلفية Celery، وطبقة البيانات فيها MySQL للحسابات والتسجيل والدرجات وMongoDB لمحتوى المقررات وRedis للذاكرة المؤقتة وطابور المهام وMeilisearch للبحث وخادم بريد صادر SMTP، وأداة Tutor تولد ملفات docker compose من config.yml](https://arabroot.io/content/images/2026/10/open-edx-01-architecture.webp)

ثلاثة نطاقات تمر عبر Caddy، وخلفها تطبيقان وعاملان وأربع قواعد بيانات

في المخطط أعلاه لاحظ التالي:

- **الواجهات الأمامية MFE:** اختصار Micro-Frontends، وهي صفحات React مستقلة مثل صفحة الدخول وصفحة المقرر وصفحة التقدم، يخدمها Container خاص بها على نطاق ثالث، وأغلب ما يراه المتعلم اليوم يأتي منها وليس من قوالب Django القديمة.
- **قاعدتا بيانات أساسيتان:** MySQL تحمل الحسابات والتسجيل في المقررات والدرجات، وMongoDB تحمل محتوى المقررات نفسه، لذلك فالنسخة الاحتياطية الكاملة هي الاثنتان معاً كما سيأتي.
- **Meilisearch:** محرك البحث في المحتوى، و[توثيق Tutor عن التوسع](https://docs.tutor.edly.io/sysadmin/scale.html?ref=arabroot.io) يذكر أنه ليس مصدراً للحقيقة، أي أنك تستطيع حذف فهرسه وإعادة بنائه دون خسارة بيانات.

وقد يتساءل البعض: لماذا لا نثبت كل هذا بأنفسنا كما فعلنا مع Moodle؟ والإجابة أن ذلك ممكن نظرياً، ولكن عدد الخدمات وإعدادات كل منها والترحيل Migrations الذي يتغير مع كل إصدار يجعل التثبيت اليدوي مشروعاً بحد ذاته، لذلك صار [Tutor](https://docs.tutor.edly.io/?ref=arabroot.io) هو الطريقة التي يعتمدها مجتمع Open edX، فهو أداة سطر أوامر بلغة Python تحفظ إعداداتك في ملف `config.yml` واحد، وتولد منه ملفات Docker Compose، وتشغل التهيئة والترقية بالترتيب الصحيح.

## الإصدار Release والمتطلبات Requirements

يصدر Open edX إصدارين رئيسيين في السنة بأسماء أشجار مرتبة أبجدياً، و[ملاحظات إصدار Verawood](https://docs.openedx.org/en/latest/community/release%5Fnotes/verawood.html?ref=arabroot.io) تذكر أنه صدر في 30 يوليو 2026، و[صفحة الإصدارات](https://docs.openedx.org/en/latest/community/release%5Fnotes/index.html?ref=arabroot.io) تقول إن الإصدار الأحدث هو الوحيد المدعوم، وإن الإصدار التالي Willow مخطط له في ديسمبر 2026\. ولكل إصدار رئيسي إصدار رئيسي من Tutor، فـ [صفحة التثبيت](https://docs.tutor.edly.io/gettingstarted/installation.html?ref=arabroot.io) تربط Verawood بـ Tutor 22، والإصدار الذي جربناه هو Tutor 22.0.2.

و[متطلبات Tutor](https://docs.tutor.edly.io/gettingstarted/requirements.html?ref=arabroot.io) هي كما يلي:

| البند       | الحد الأدنى                                                                                              | الموصى به |
| ----------- | -------------------------------------------------------------------------------------------------------- | --------- |
| الذاكرة RAM | 4GB                                                                                                      | 8GB       |
| المعالج CPU | 2                                                                                                        | 4         |
| القرص       | 8GB                                                                                                      | 25GB      |
| البرامج     | Docker 24.0.5 أو أحدث، وDocker Compose 2، ونظام Linux بمعمارية AMD64 أو ARM64، والمنفذان 80 و443 مفتوحان |           |

ولاحظ أن ال Docker Images وحدها تأخذ مساحة كبيرة، ففي تجربتنا كان Docker Image الأساسي `overhangio/openedx:22.0.2-indigo` بحجم 5.04GB، ومعه MySQL بحجم 1.12GB وMongoDB بحجم 1.19GB، والمجموع مع الباقي نحو 8.1GB قبل أن تضيف مقرراً واحداً، لذلك اعتبر 25GB هي البداية الواقعية وليست رفاهية.

## التثبيت بأداة Tutor

### تثبيت Tutor في بيئة Python مستقلة

توثيق Tutor ينصح بتثبيته في بيئة افتراضية Virtual Environment حتى لا يختلط بحزم Python الخاصة بالنظام، وسوف نثبت الإصدار بالرقم، ومعه إضافتان Plugins: `tutor-mfe` التي تشغل الواجهات الأمامية، و`tutor-indigo` وهي القالب Theme الافتراضي:

```bash
python3 -m venv ~/tutor-venv
. ~/tutor-venv/bin/activate
pip install "tutor==22.0.2" "tutor-mfe>=22,<23" "tutor-indigo>=22,<23"
tutor --version
tutor plugins list
```

```text
tutor, version 22.0.2
NAME  	STATUS   	VERSION
indigo	✅ enabled	22.0.0
mfe   	✅ enabled	22.1.0
```

والطريقة التي في التوثيق هي `pip install "tutor[full]"`، وهي تثبت معه 13 إضافة منها المنتديات Forum والملاحظات Notes وMinIO، وفي تجربتنا بقي pip يحاول حل اعتماديات هذه الحزمة أكثر من عشر دقائق دون نتيجة، فثبتنا الإضافتين اللتين نحتاجهما فقط. ولاحظ أن غياب إضافة `tutor-forum` يعني أن النقاشات داخل المقرر لا تعمل، فإذا كانت مؤسستك تعتمد عليها فأضفها بالقيد نفسه `>=22,<23`.

### الإعداد Configuration قبل التشغيل

نضبط اسم المنصة واللغة الافتراضية والمنفذ، وكل قيمة تكتبها هنا تحفظ في `config.yml`:

```bash
tutor config save \
  --set PLATFORM_NAME="Lab Academy" \
  --set LANGUAGE_CODE=ar \
  --set CONTACT_EMAIL=admin@example.com \
  --set CADDY_HTTP_PORT=127.0.0.1:27080
tutor config printvalue LMS_HOST
tutor config printvalue CMS_HOST
tutor config printvalue MFE_HOST
```

```text
local.openedx.io
studio.local.openedx.io
apps.local.openedx.io
```

في الإعداد أعلاه لاحظ التالي:

- النطاقات الافتراضية تنتهي بـ `local.openedx.io`، وهو نطاق يشير إلى `127.0.0.1`، فيصلح للتجربة على جهازك، وفي الإنتاج تغيرها إلى نطاقك كما في قسم النطاق والشهادة.
- الإعداد `CADDY_HTTP_PORT=127.0.0.1:27080` من [دليل تشغيل Open edX خلف Reverse Proxy](https://docs.tutor.edly.io/sysadmin/proxy.html?ref=arabroot.io)، ويجعل Caddy يستمع على الجهاز نفسه فقط، وسوف نرى بعد قليل لماذا لا يكفي هذا وحده لتصفح المنصة على منفذ غير 80.
- كلمات مرور MySQL وMongoDB والمفاتيح السرية يولدها Tutor عشوائياً في `config.yml`، لذلك احم هذا الملف كما تحمي كلمات المرور، ولا تضعه في مستودع Git عام.

### التشغيل والتهيئة Initialisation

الأمر الذي في التوثيق يقوم بكل شيء: يولد الملفات، ويسحب ال Images، ويشغل ال Containers، ثم يشغل التهيئة التي تنشئ قواعد البيانات وتطبق الترحيل:

```bash
tutor local launch --non-interactive
```

وفي أول تشغيل لنا توقف الأمر بالخطأ التالي:

```text
ERROR 2003 (HY000): Can't connect to MySQL server on 'mysql:3306' (111)
    [7/10] Waiting for MySQL service (this may take a while)...
...
MySQL initialisation error
Error: Command failed with status 1: docker compose ... run --rm -T mysql-job sh -e -c echo "Initialising MySQL..."
```

وعند قراءة سجل MySQL تبين السبب، فالتشغيل الأول لقاعدة بيانات جديدة يمر بخادم مؤقت ثم إعادة تشغيل، وتهيئة InnoDB وحدها أخذت 40 ثانية على سيرفر مشغول، بينما مهمة التهيئة في Tutor تحاول الاتصال عشر مرات فقط ثم تستسلم:

```text
[Note] [Entrypoint]: MySQL init process done. Ready for start up.
2026-10-21T09:32:02.259505Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2026-10-21T09:32:41.829854Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
[System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.4.11'  port: 3306
```

والحل أن تترك MySQL حتى يكتمل، ثم تشغل التهيئة وحدها، فهي آمنة للتكرار لأن كل خطوة فيها تتحقق مما سبق:

```bash
tutor local do init
```

وفي تجربتنا استغرقت التهيئة 6085 ثانية، أي نحو 101 دقيقة، وأنشأت 609 جدولاً في قاعدة `openedx`، و1378 سجلاً في جدول الترحيل `django_migrations`. وهذا الرقم ليس ما سوف تراه على سيرفر مخصص، فالسيرفر الذي جربنا عليه كان مشغولاً بأعمال أخرى، و[صفحة البداية السريعة](https://docs.tutor.edly.io/gettingstarted/quickstart.html?ref=arabroot.io) تتحدث عن أقل من عشر دقائق على سيرفر باتصال جيد، ولكنه يبين نقطة مهمة: الترحيل في Open edX عمل ثقيل على المعالج، لأن Django يحسب حالة مئات النماذج Models قبل كل خطوة، لذلك لا تجرب الترقية على سيرفر الإنتاج في ساعات العمل.

⚠️

إذا توقفت التهيئة برسالة `Killed` فالسبب نقص الذاكرة كما يذكر [دليل النشر المحلي](https://docs.tutor.edly.io/local.html?ref=arabroot.io)، وأما رسالة `MySQL initialisation error` في أول تشغيل فغالباً سببها بطء MySQL في أول إقلاع، فانتظره ثم أعد `tutor local do init` بدلاً من حذف كل شيء والبدء من جديد.

### حساب المدير Admin

```bash
tutor local do createuser --staff --superuser --password='Lab-Admin-2026!' admin admin@example.com
```

والخيار `--staff` يعطيه صلاحية الدخول إلى الاستوديو، و`--superuser` يعطيه لوحة إدارة Django، وفي الإنتاج اترك الخيار `--password` واكتب كلمة المرور عندما يطلبها الأمر، حتى لا تبقى في سجل أوامر ال Shell.

### نجرب العطل: المنصة على منفذ Port غير 80

بعد التهيئة طلبنا النطاقات الثلاثة على المنفذ 27080 من الجهاز نفسه:

```bash
for h in local.openedx.io studio.local.openedx.io apps.local.openedx.io; do
  curl -s -o /dev/null -w "$h %{http_code} %{redirect_url}\n" \
    --resolve $h:27080:127.0.0.1 http://$h:27080/
done
```

```text
local.openedx.io 301 http://apps.local.openedx.io/catalog/
studio.local.openedx.io 302 http://studio.local.openedx.io:27080/home/
apps.local.openedx.io 302 http://local.openedx.io/
```

لاحظ أن منصة التعلم حولت الطلب إلى صفحة الفهرس في الواجهات الأمامية بعنوان **دون المنفذ**، فيذهب المتصفح إلى المنفذ 80 ولا يجد شيئاً، بينما حافظ الاستوديو على المنفذ، والسبب أن عناوين الواجهات الأمامية مبنية من `MFE_HOST` و`LMS_HOST` كما هي، والقاعدة هنا: Open edX مصمم ليعمل على 80 و443 مباشرة أو خلف Reverse Proxy يستقبل عليهما ويمرر إلى `CADDY_HTTP_PORT` كما يشرح دليل Tutor، ولا تحاول نشره للمستخدمين على منفذ آخر. وفي التجربة اكتفينا بتوجيه المتصفح إلى المنفذ الصحيح لأخذ الصور.

## بناء المقرر Course: من الاستوديو Studio أو من ملفات OLX

يبنى المقرر في Open edX من أربعة مستويات، و[توثيق الوحدات](https://docs.openedx.org/en/latest/educators/concepts/open%5Fedx%5Fplatform/about%5Fcourse%5Funits.html?ref=arabroot.io) يعرف الوحدة Unit بأنها الصفحة الواحدة التي يراها المتعلم، وفيها مكون أو أكثر Component مثل نص أو سؤال أو فيديو. والصورة التالية تبين المستويات على المقرر الذي سوف نبنيه:

![مخطط هيكل المقرر في Open edX: المقرر Course مقدمة في الشبكات بالمعرف course-v1:LabX+NET101+2026 فيه القسم Section الأسبوع الأول أساسيات الشبكات، وفيه القسم الفرعي Subsection نظام أسماء النطاقات DNS وهو المستوى الذي يحدد التقييم Homework، وفيه وحدتان Unit هما تعريف DNS وتمرين قصير، وفي الأولى مكون نص HTML وفي الثانية سؤال اختيار من متعدد، وبجانب كل مستوى اسم مجلده في تصدير OLX: course وchapter وsequential وvertical وhtml وproblem](https://arabroot.io/content/images/2026/10/open-edx-02-course-outline.webp)

المستوى الذي يحمل التقييم هو القسم الفرعي، والوحدة هي الصفحة التي يفتحها المتعلم

الطريقة البسيطة هي أن يبني المعلم كل هذا بالنقر في الاستوديو، وهي مناسبة لمقرر واحد، ولكن إذا كان لديك عشرات المقررات أو تريد مراجعة التغييرات قبل نشرها فالأنسب أن تعرف أن المقرر في Open edX له صيغة ملفات اسمها OLX، وهي مجلد فيه ملفات XML، كل مستوى في مجلد باسمه، وهي نفسها الصيغة التي يخرجها الاستوديو عند تصدير المقرر. وفيما يلي المقرر الذي استخدمناه كاملاً:

```text
net101/
  course.xml
  course/2026.xml
  chapter/week1.xml
  sequential/dns.xml
  vertical/dns-intro.xml
  vertical/dns-quiz.xml
  html/dns-text.xml
  html/dns-text.html
  problem/dns-q1.xml
  policies/2026/policy.json
  policies/2026/grading_policy.json
```

الملف الرئيسي `course.xml` يحدد المؤسسة ورمز المقرر والدورة Run، ومنها يتكون معرف المقرر `course-v1:LabX+NET101+2026`:

```xml
<course url_name="2026" org="LabX" course="NET101"/>
```

```xml
<!-- course/2026.xml -->
<course display_name="مقدمة في الشبكات" language="ar" start="2026-01-01T00:00:00Z">
  <chapter url_name="week1"/>
</course>

<!-- chapter/week1.xml -->
<chapter display_name="الأسبوع الأول: أساسيات الشبكات">
  <sequential url_name="dns"/>
</chapter>

<!-- sequential/dns.xml -->
<sequential display_name="نظام أسماء النطاقات DNS" graded="true" format="Homework">
  <vertical url_name="dns-intro"/>
  <vertical url_name="dns-quiz"/>
</sequential>

<!-- vertical/dns-intro.xml -->
<vertical display_name="تعريف DNS">
  <html url_name="dns-text"/>
</vertical>

<!-- vertical/dns-quiz.xml -->
<vertical display_name="تمرين قصير">
  <problem url_name="dns-q1"/>
</vertical>

<!-- html/dns-text.xml -->
<html filename="dns-text" display_name="شرح DNS"/>
```

ونص الشرح في `html/dns-text.html`:

```html
<p>نظام أسماء النطاقات DNS يحول اسم النطاق مثل example.com إلى عنوان IP يستطيع جهازك الاتصال به.</p>
```

ثم السؤال في `problem/dns-q1.xml`، بمحاولتين ودرجة واحدة:

```xml
<problem display_name="سؤال عن DNS" max_attempts="2" weight="1">
  <multiplechoiceresponse>
    <label>ما وظيفة DNS؟</label>
    <choicegroup type="MultipleChoice">
      <choice correct="true">تحويل اسم النطاق إلى عنوان IP</choice>
      <choice correct="false">توزيع عناوين IP على الأجهزة</choice>
      <choice correct="false">تشفير الاتصال بين المتصفح والسيرفر</choice>
    </choicegroup>
  </multiplechoiceresponse>
</problem>
```

وأخيراً سياسة التقييم في `policies/2026/grading_policy.json`، وهي هنا نوع واحد من التقييم هو الواجبات Homework بوزن 100%، ودرجة النجاح 50%، ثم `policy.json` بالاسم واللغة وتاريخ البداية:

```json
{"GRADER": [{"type": "Homework", "min_count": 1, "drop_count": 0, "short_label": "HW", "weight": 1.0}], "GRADE_CUTOFFS": {"Pass": 0.5}}
```

```json
{"course/2026": {"display_name": "مقدمة في الشبكات", "language": "ar", "start": "2026-01-01T00:00:00Z"}}
```

الآن نقوم بنسخ المجلد إلى Container الاستوديو واستيراده بأمر `import`، والوسيط الأول هو المجلد الأب والثاني اسم مجلد المقرر:

```bash
docker cp net101 edu1-openedx-cms-1:/tmp/net101
docker exec edu1-openedx-cms-1 bash -c 'cd /openedx/edx-platform && ./manage.py cms import /tmp net101'
```

والمخرج طويل، وهذه أهم أسطره:

```text
Importing...
    Importing static content? True
    Importing python lib? True
Seeding forum roles for course course-v1:LabX+NET101+2026
... Course import course-v1:LabX+NET101+2026: No tags.csv file present.
... Extracting dates from 8 items in course-v1:LabX+NET101+2026
```

واستغرق الاستيراد 57 ثانية، ولاحظ أن اسم ال Container يبدأ باسم مشروع Docker Compose، وهو عندنا `edu1-openedx` لأننا غيرنا الإعداد `LOCAL_PROJECT_NAME`، والقيمة الافتراضية `tutor_local`، فاعرف الاسم عندك بالأمر `tutor local status`. والصورة التالية للمقرر بعد الاستيراد كما يراه المدير في الاستوديو:

![صفحة مخطط المساق في استوديو Open edX بالعربية لمقرر مقدمة في الشبكات: القسم الأسبوع الأول أساسيات الشبكات، وتحته القسم الفرعي نظام أسماء النطاقات DNS بعلامة نشطة ونوع Homework، وتحته وحدتان تعريف DNS وتمرين قصير، وتاريخ البداية 01 يناير 2026 الساعة 00:00 UTC، وأزرار Course info وأضف وشاهد النسخة الحية، وفي الجانب ملخص المحتوى](https://arabroot.io/content/images/2026/10/open-edx-07-studio-outline.webp)

المقرر المستورد في الاستوديو: المستويات نفسها التي في ملفات OLX، والتواريخ بتوقيت UTC

وقد يتساءل البعض: هل يغني هذا عن الاستوديو؟ لا، فالمعلم سوف يعدل في الاستوديو، وإذا عدلت أنت الملفات بعد ذلك ثم استوردتها فوق المقرر فسوف تكتب فوق تعديلاته، لذلك اتفق مع الفريق على مصدر واحد للحقيقة: إما الاستوديو، وتصدر منه نسخة OLX للحفظ والمراجعة، وإما الملفات في Git، ولا يعدل أحد في الاستوديو.

## المتعلمون والتسجيل Enrollment والدرجة Grade

أنشأنا متعلمين وسجلناهما في المقرر من سطر الأوامر، وفي الإنتاج سوف يسجل المتعلمون أنفسهم من صفحة المقرر أو يأتون من الدخول الموحد SSO، ولكن التسجيل من سطر الأوامر يفيدك عندما تستلم قائمة من القبول والتسجيل:

```bash
tutor local do createuser --password='Lab-Stud-2026!' student1 student1@example.com
tutor local do createuser --password='Lab-Stud-2026!' student2 student2@example.com
docker exec edu1-openedx-lms-1 bash -c 'cd /openedx/edx-platform && \
  ./manage.py lms enroll_user_in_course -e student1@example.com -c course-v1:LabX+NET101+2026 && \
  ./manage.py lms enroll_user_in_course -e student2@example.com -c course-v1:LabX+NET101+2026'
```

ثم تحققنا من التسجيل من داخل Django:

```text
[('student1', 'audit', True), ('student2', 'audit', True)]
```

ولاحظ أن نوع التسجيل `audit`، وهو التسجيل المجاني الافتراضي، وفي Open edX أنواع تسجيل Enrollment Modes أخرى مثل `verified` المرتبط بالشهادات والدفع، وهي من الأشياء التي ورثتها المنصة من طبيعة المقررات المفتوحة، وفي مدرسة أو جامعة تكتفي غالباً بنوع واحد.

بعد ذلك دخلنا بحساب `student1`، وهذه صفحة المقرر كما رآها:

![صفحة المقرر للمتعلم student1 في Open edX بالعربية: عنوان مقدمة في الشبكات، والتبويبات المساق والتقدم والتواريخ، وزر ابدأ المساق، والقسم الأسبوع الأول أساسيات الشبكات، وأدوات المساق: الإشارات المرجعية وابدأ الجولة، ونافذة ترحيب بعنوان مرحباً بك في مساق Lab Academy مع زري ابدأ الجولة والتخطي مؤقتاً](https://arabroot.io/content/images/2026/10/open-edx-04-course-home.webp)

أول دخول للمتعلم: الواجهة بالعربية، والمقرر يسمى «مساق» في الترجمة

ثم أجاب عن السؤال إجابة صحيحة، فظهرت علامة الصح ودرجة 1 من 1، وبقيت له محاولة واحدة:

![وحدة تمرين قصير في واجهة المتعلم: سؤال عن DNS بدرجة 1,0 من 1,0، والسؤال ما وظيفة DNS وثلاثة خيارات والخيار المختار تحويل اسم النطاق إلى عنوان IP بإطار أخضر وعلامة صح، وتحته زر أرسل وعبارة إنجليزية You have used 1 of 2 attempts وGrading method، وفي الجانب قائمة الأسبوع الأول ووحدتا تعريف DNS وتمرين قصير](https://arabroot.io/content/images/2026/10/open-edx-05-learner-problem.webp)

إجابة صحيحة بمحاولة واحدة من اثنتين، ولاحظ السطر الذي بقي بالإنجليزية

وصفحة التقدم Progress حسبت الدرجة مباشرة بحسب سياسة التقييم التي كتبناها: 100% في الواجبات Homework، ودرجة النجاح 50%، ورسالة «أنت ناجح حالياً في هذا المساق»، بينما إكمال المحتوى 50% لأن المتعلم فتح وحدة واحدة من اثنتين:

![صفحة التقدم للمتعلم في Open edX بالعربية: دائرة إكمال المساق 50% مكتمل، وشريط الدرجات بدرجتك الحالية 100% ودرجة النجاح 50%، ورسالة أنت ناجح حالياً في هذا المساق، وجدول ملخص الدرجات بنوع الواجب Homework والوزن 100% والدرجة 100%، وسطر إنجليزي عن Hidden Scores، والدرجات التفصيلية للأسبوع الأول نظام أسماء النطاقات DNS بدرجة 1 من 1](https://arabroot.io/content/images/2026/10/open-edx-06-progress.webp)

الدرجة تصل إلى صفحة التقدم فوراً، والفرق واضح بين إكمال المحتوى ونسبة النجاح

## العربية واتجاه الكتابة RTL بصراحة

بعد ضبط `LANGUAGE_CODE=ar` انقلبت الواجهة كلها إلى اليمين، والصورة التالية لصفحة الفهرس قبل الدخول:

![الصفحة الرئيسية لمنصة Open edX بالعربية: عنوان مرحباً بك في Lab Academy، وتحته عبارة إنجليزية It works! Powered by the Open edX Platform، ومربع بحث ابحث عن مساق بزر إنجليزي search، وبطاقة مقرر مقدمة في الشبكات NET101 من LabX يبدأ في 1 يناير 2026، وروابط تسجيل الدخول والتسجيل واستكشف المساقات](https://arabroot.io/content/images/2026/10/open-edx-03-catalog-ar.webp)

الواجهة من اليمين إلى اليسار، مع عبارات بقيت بالإنجليزية

وأثناء التجربة وجدنا التفاصيل التالية، وهي التي سوف يسألك عنها الفريق:

- **عبارات إنجليزية:** زر `search` وعبارة «It works! Powered by the Open edX Platform» في الصفحة الرئيسية، وروابط التذييل Footer كلها، وسطر «You have used 1 of 2 attempts» تحت السؤال، وفقرة Hidden Scores في صفحة التقدم، و[صفحة الإعدادات](https://docs.tutor.edly.io/configuration.html?ref=arabroot.io) في Tutor تعترف بذلك وتقول إن بعض النصوص لن تكون مترجمة إذا لم يساهم ما يكفي من المترجمين في لغتك، وتشرح كيف تضيف ترجماتك.
- **المصطلح:** الترجمة تستخدم «مساق» للمقرر Course في كل مكان، فإذا كانت مؤسستك تقول «مقرر» فهذا من أول ما تعدله في الترجمات المخصصة.
- **التوقيت:** الاستوديو يعرض التواريخ بتوقيت UTC، فاضبط تواريخ البدء والتسليم وأنت تعرف الفرق مع توقيت مؤسستك.
- **الأرقام:** درجة السؤال ظهرت «1,0/1,0» بفاصلة عشرية، والنسب في صفحة التقدم «%100» بالعلامة قبل الرقم.

والخلاصة أن العربية صالحة للمتعلم من اليوم الأول، ولكنها أقل اكتمالاً من Moodle الذي رأينا حزمته العربية مترجمة بنسبة 99%، فاجمع هذه العبارات في قائمة واحدة قبل الإطلاق.

## كم يستهلك من الذاكرة RAM وهو خامل؟

بعد التهيئة والتجربة، وبلا أي متعلم متصل، قسنا الذاكرة بالأمر `docker stats --no-stream`:

| ال Container | الذاكرة               |
| ------------ | --------------------- |
| lms-worker   | 1.445GiB              |
| cms-worker   | 1.449GiB              |
| lms          | 840MiB                |
| cms          | 738MiB                |
| mysql        | 687MiB                |
| meilisearch  | 132MiB                |
| mongodb      | 123MiB                |
| mfe          | 54MiB                 |
| caddy        | 44MiB                 |
| redis وsmtp  | أقل من 5MiB لكل منهما |

المجموع نحو 5.4GB والمنصة خاملة، وهذا ما يجعل 4GB حداً أدنى نظرياً فقط. ولاحظ أن أكبر رقمين هما العاملان Workers وليس منصة التعلم، والسبب أن كل عامل Celery يشغل افتراضياً عملية لكل معالج كما في [توثيق Celery](https://docs.celeryq.dev/en/stable/userguide/workers.html?ref=arabroot.io#concurrency)، والسيرفر الذي جربنا عليه فيه 8 معالجات، فوجدنا داخل كل عامل 9 عمليات: عملية رئيسية وثماني عمليات فرعية:

```bash
docker exec edu1-openedx-lms-worker-1 sh -c 'ps -eo args | grep -c "[c]elery"'
```

```text
9
```

وكنا قد وضعنا حداً للذاكرة 1500MB لكل عامل عبر ملف `docker-compose.prod.override.yml` الذي يقرؤه Tutor من مجلد `env/local` إذا وجده، فوصل العاملان إلى الحد تقريباً. لذلك على سيرفر فيه معالجات كثيرة وذاكرة قليلة راقب العاملين أولاً، وفيما يلي ملف الحدود الذي استخدمناه، وهو مثال تعدل أرقامه بحسب سيرفرك:

```yaml
# $(tutor config printroot)/env/local/docker-compose.override.yml
services:
  lms:
    mem_limit: 3g
  cms:
    mem_limit: 3g
  mysql:
    mem_limit: 1500m
  mongodb:
    mem_limit: 1g
  meilisearch:
    mem_limit: 512m
```

## النطاق Domain والشهادة HTTPS

في الإنتاج تحتاج سجلات DNS للنطاقات كلها، و[صفحة المتطلبات](https://docs.tutor.edly.io/gettingstarted/requirements.html?ref=arabroot.io) تقترح سجل A للنطاق الرئيسي وسجل CNAME لكل النطاقات الفرعية تحته:

```text
learn    1800 IN A     203.0.113.10
*.learn  1800 IN CNAME learn.example.com.
```

ثم تعيد ضبط النطاقات وتفعل HTTPS:

```bash
tutor config save \
  --set LMS_HOST=learn.example.com \
  --set CMS_HOST=studio.learn.example.com \
  --set ENABLE_HTTPS=true \
  --set CADDY_HTTP_PORT=80
tutor local launch
```

وعند `ENABLE_HTTPS=true` يصدر Caddy داخل Tutor شهادات Let's Encrypt تلقائياً كما تذكر [صفحة الإعدادات](https://docs.tutor.edly.io/configuration.html?ref=arabroot.io)، بشرط أن يكون المنفذان 80 و443 مفتوحين وأن تشير السجلات إلى السيرفر، وهذه خطوة لا يمكن تجربتها على جهاز محلي. وإذا كان لديك Reverse Proxy على السيرفر مثل [Caddy](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-caddy-reverse-proxy/) أو Nginx Proxy Manager فأبق `ENABLE_HTTPS=true`، واضبط `ENABLE_WEB_PROXY=false` و`CADDY_HTTP_PORT=127.0.0.1:81`، ووجه إليه النطاقات كلها مع الترويسات `X-Forwarded-Proto` و`X-Forwarded-Port` كما في [دليل Tutor](https://docs.tutor.edly.io/sysadmin/proxy.html?ref=arabroot.io)، وتذكر أن النطاقات أكثر من ثلاثة، فهناك أيضاً `meilisearch.learn.example.com` الذي تستخدمه الواجهات الأمامية للبحث.

## التحقق Verification من النجاح

- `tutor local status` يظهر كل ال Containers بحالة `Up`، ولا يوجد Container يعيد التشغيل Restarting.
- النطاق الرئيسي يحول إلى `/catalog/` في الواجهات الأمامية، والمقرر يظهر في الفهرس.
- الدخول إلى الاستوديو بحساب المدير يفتح صفحة المقررات، والمقرر المستورد فيه مستوياته كلها.
- متعلم مسجل يحل سؤالاً فتظهر درجته في صفحة التقدم دون انتظار.

## النسخ الاحتياطي Backup والاستعادة Restore

كل بيانات Tutor في مجلد واحد هو `$(tutor config printroot)`، وفيه `config.yml` ومجلد `env` المولد ومجلد `data` لقواعد البيانات والملفات، و[دليل النسخ الاحتياطي ونقل البيانات](https://docs.tutor.edly.io/sysadmin/datamigration.html?ref=arabroot.io) يعطي أمرين لأخذ نسخة من قاعدتي البيانات وهما تعملان:

```bash
tutor local exec \
  -e USERNAME="$(tutor config printvalue MYSQL_ROOT_USERNAME)" \
  -e PASSWORD="$(tutor config printvalue MYSQL_ROOT_PASSWORD)" \
  mysql sh -c 'mysqldump --all-databases --user=$USERNAME --password=$PASSWORD > /var/lib/mysql/dump.sql'
tutor local exec mongodb mongodump --out=/data/db/dump.mongodb
```

```text
... done dumping `openedx.modulestore.definitions` (12 documents)
... done dumping `openedx.modulestore.structures` (6 documents)
... done dumping `openedx.modulestore.active_versions` (1 document)
```

وفي منصتنا الصغيرة كان ملف `dump.sql` بحجم 6.4MB، ونسخة MongoDB بحجم 68KB لأن فيها مقرراً واحداً، والمجلد كله 634MB. والنسختان تقعان داخل `data/mysql` و`data/mongodb`، فانقلهما بعد ذلك خارج السيرفر، ومعهما `config.yml` ومجلد `data/openedx-media` الذي يحمل الملفات المرفوعة، كما في [النسخ الاحتياطي بقاعدة 3-2-1 واختبار الاستعادة](https://arabroot.io/articles/%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-3-2-1-%D9%88%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D8%A7%D8%AF%D8%A9/). وأما النسخة الأبسط والأكثر اكتمالاً فهي التي يذكرها الدليل قبل الترقية: إيقاف المنصة ثم نسخ المجلد كله بأمر `rsync`، وعلى سيرفر آخر بالإصدار نفسه من Tutor تضعه في مكانه وتشغل `tutor local start -d`.

🛑

نسخة MySQL وحدها لا تحمي المقررات، لأن محتوى المقررات في MongoDB، ونسخة MongoDB وحدها لا تحمي المتعلمين ودرجاتهم، لأنها في MySQL، فخذ الاثنتين في الوقت نفسه واختبر استعادتهما معاً.

## التحديث Upgrade إلى إصدار أحدث

التحديثات داخل الإصدار الرئيسي نفسه، مثل الانتقال من 22.0.1 إلى 22.0.2، هي تحديث حزمة Tutor ثم إعادة `launch`، وأما الانتقال من إصدار رئيسي إلى آخر، مثل Verawood إلى Willow، فهو كما يقول [دليل الترقية](https://docs.tutor.edly.io/upgrading.html?ref=arabroot.io) لا رجوع عنه إلا من نسخة احتياطية، لأن الرجوع إلى إصدار أقدم غير مدعوم. والخطوات بالترتيب:

1. اقرأ ملف `CHANGELOG.md` في Tutor، وابحث عن التغييرات التي عليها العلامة 💥، فهي التي تغير السلوك الذي يعتمد عليه الآخرون Breaking Change، مثل ترقية Meilisearch في Tutor 22.0.0 التي تتطلب حذف الفهرس وإعادة بنائه.
2. أوقف المنصة وخذ نسخة كاملة من المجلد بأمر `rsync`.
3. تأكد أن كل إضافة Plugin لها إصدار متوافق مع الإصدار الجديد.
4. جرب الترقية على نسخة من المنصة أولاً، وتذكر أن التهيئة قد تأخذ وقتاً طويلاً كما رأينا.
5. حدث الحزم، ثم شغل `tutor local launch`، وإذا كنت تبني Docker Images خاصة بك فاستخدم `tutor local upgrade --from=<الإصدار السابق>` قبله كما في الدليل.

```bash
tutor local stop
sudo rsync -avr "$(tutor config printroot)"/ /backup/tutor-before-upgrade/
pip install --upgrade "tutor<24" "tutor-mfe<24" "tutor-indigo<24"
tutor local launch
```

## التوسع Scaling: من سيرفر واحد إلى Kubernetes

[دليل التوسع في Tutor](https://docs.tutor.edly.io/sysadmin/scale.html?ref=arabroot.io) يفرق بين ثلاثة أشياء: التوسع العمودي Vertical Scaling بزيادة موارد السيرفر نفسه، والتوسع الأفقي Horizontal Scaling بإضافة سيرفرات، والتوافرية العالية High Availability، ويقول بوضوح إن السيرفر الواحد نقطة فشل وحيدة Single Point of Failure، فلا توافرية عالية معه. وفيما يلي المراحل كما يصفها الدليل:

| المرحلة         | ماذا تفعل                                                                                      | الأمر أو الإعداد                                               |
| --------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| سيرفر واحد أكبر | زد عمليات uWSGI لمنصة التعلم والاستوديو، والافتراضي 2 لكل منهما، وكل عملية تحتاج أكثر من 500MB | OPENEDX\_LMS\_UWSGI\_WORKERS=8 وOPENEDX\_CMS\_UWSGI\_WORKERS=4 |
| فصل البيانات    | انقل قواعد البيانات خارج السيرفر بالترتيب: MySQL ثم MongoDB ثم Redis ثم تخزين الملفات          | RUN\_MYSQL=false وMYSQL\_HOST=…                                |
| عدة سيرفرات     | Kubernetes بدلاً من Docker Compose، وزيادة النسخ Replicas لكل خدمة                             | tutor k8s scale lms 8                                          |

والدليل يذكر مثالاً منقولاً عن منصة كبيرة تخدم 500 ألف مستخدم مختلف في الأسبوع على سيرفر واحد فيه 8 معالجات و16GB من الذاكرة، وهو رقم مفيد لتعرف أن السيرفر الواحد يذهب بعيداً، ولكنه ليس وعداً، فالحمل الحقيقي يحدده عدد المتصلين في اللحظة نفسها، وليس عدد المستخدمين في الأسبوع، وقسه كما شرحنا في [اختبار الأحمال والضغط](https://arabroot.io/articles/%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D8%A7%D8%AD%D9%85%D8%A7%D9%84-%D9%88%D8%A7%D9%84%D8%B6%D8%BA%D8%B7-load-%D9%88-stress-testing-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/). ونقطة أخرى من الدليل: إذا كنت تتوقع أن تنتقل إلى عدة سيرفرات يوماً ما، فخزن الملفات المرفوعة في تخزين متوافق مع S3 من البداية عبر إضافة `tutor-minio`، لأن تخزينها في مجلد على السيرفر يصعب التوسع بعد ذلك.

## متى تختار Open edX؟

- **نقاط القوة:** صمم لمقررات مفتوحة بأعداد كبيرة، وتجربة المتعلم حديثة ومنظمة في وحدات قصيرة، والمقرر ملفات OLX يمكن مراجعتها في Git، وTutor يوحد التثبيت والترقية، وطريق واضح إلى Kubernetes.
- **نقاط الضعف:** يحتاج 5GB من الذاكرة وهو خامل، والتهيئة والترقية ثقيلتان على المعالج، والعربية أقل اكتمالاً من Moodle، وأدوات الفصل الدراسي التقليدي مثل الشعب والحضور ليست من طبيعته، والإضافات الأساسية مثل المنتديات تثبت منفصلة.

فإذا كانت مؤسستك تطلق مقررات مفتوحة للجمهور أو برامج تدريب ذاتي لآلاف المتدربين فهو مناسب جداً، وأما مدرسة بفصول وشعب ومعلمين يرفعون واجبات أسبوعية فالأقرب لها [Moodle](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-moodle-%D9%85%D9%86%D8%B5%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%B9%D9%84%D9%89-%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D9%83/).

## مشكلات شائعة وحلولها Troubleshooting

- **`MySQL initialisation error` في أول تشغيل:** MySQL لم يكمل إقلاعه الأول، فانتظر حتى ترى `ready for connections` في `tutor local logs mysql`، ثم شغل `tutor local do init`.
- **المتصفح يذهب إلى عنوان بلا منفذ:** المنصة تبني عناوين الواجهات الأمامية من النطاق وحده، فشغلها على 80 و443 أو خلف Reverse Proxy عليهما.
- **الصفحة تبقى في حالة تحميل:** صفحات الواجهات الأمامية تتصل بمنصة التعلم بعد التحميل، وفي تجربتنا احتاجت صفحة المقرر أكثر من 20 ثانية في أول فتح بعد التشغيل، لأن العمليات تبدأ بارد Cold Start، فانتظر قبل أن تبحث عن خطأ.
- **العاملون يصلون إلى حد الذاكرة:** كل عامل Celery يشغل عملية لكل معالج، فارفع الحد أو خفف عدد العمليات قبل أن يقتل النظام العامل بسبب نقص الذاكرة.
- **النقاشات لا تظهر:** المنتديات إضافة منفصلة `tutor-forum`، وليست جزءاً من Tutor الأساسي.

## تنظيف المختبر

```bash
tutor local dc down --remove-orphans
```

```text
 Container edu1-openedx-mongodb-1 Removed
 Container edu1-openedx-permissions-1 Removed
 Container edu1-openedx-mysql-1 Removed
 Network edu1-openedx_default Removing
 Network edu1-openedx_default Removed
```

هذا الأمر يحذف ال Containers والشبكة فقط، والبيانات تبقى في مجلد Tutor، فإذا أردت حذف كل شيء فاحذف المجلد بعد أن تتأكد أنه لا يحمل شيئاً تحتاجه، ثم احذف ال Docker Images بأسمائها الكاملة بأمر `docker image rm`، فهي وحدها أكثر من 8GB.

## تدريب عملي

- صدر المقرر من الاستوديو، وقارن المجلد الناتج بملفات OLX التي كتبناها، ثم أضف وحدة جديدة فيها فيديو واستوردها مرة أخرى على نسخة من المنصة.
- غير `max_attempts` في السؤال إلى 1، وأجب إجابة خاطئة بحساب `student2`، ثم راقب صفحة التقدم ورسالة النجاح.

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- Open edX منصتان: منصة التعلم LMS والاستوديو Studio، ومعهما واجهات أمامية MFE وعاملان وأربع قواعد بيانات، وTutor هو الطريقة المعتمدة لتشغيلها.
- الإصدار الحالي Verawood مع Tutor 22، والإصدار الأحدث هو الوحيد المدعوم، والإصدار التالي Willow في ديسمبر 2026.
- ال Docker Images وحدها نحو 8.1GB، والمنصة الخاملة تستهلك نحو 5.4GB من الذاكرة، والعاملان أكبر المستهلكين.
- التهيئة الأولى طبقت 1378 خطوة ترحيل، وهي ثقيلة على المعالج، والمنصة مصممة لتعمل على 80 و443.
- المقرر يمكن أن يكون ملفات OLX في Git، والدرجة تصل إلى صفحة التقدم بحسب سياسة التقييم.
- النسخة الكاملة هي MySQL وMongoDB والملفات و`config.yml` معاً، والترقية بين الإصدارات الرئيسية لا رجوع عنها إلا من هذه النسخة.

## سجل التحديثات

- أكتوبر 2026: كتابة الدليل وتجربته على Open edX Verawood مع Tutor 22.0.2 وMySQL 8.4.11 وMongoDB 7.0.39.