في 15 فبراير 2024 أوقفت Atlassian دعم نسخ Server من Jira، وبعدها أعلنت أن نسخ Data Center ستصل إلى نهاية عمرها (End of Life) في 28 مارس 2029، حيث تتحول بعد هذا التاريخ إلى وضع القراءة فقط، وبالتالي فكل مؤسسة كانت تشغل Jira على سيرفراتها أصبح أمامها خياران: أن تنقل بيانات مشاريعها إلى سحابة Atlassian وتدفع عن كل مستخدم، أو أن تبحث عن أداة أخرى تعمل داخل شبكتها. ومن أكثر الأدوات التي تظهر في هذا البحث اليوم Plane، وهي أداة إدارة مشاريع Project Management مفتوحة المصدر Open Source تشبه Jira وLinear في طريقة العمل: مهام Work Items، وسبرنتات تسميها Cycles، ووحدات Modules، وصفحات توثيق Pages، ولوحات Kanban ومخطط Gantt.
وقد يتساءل البعض: إذا كنا شرحنا تثبيت Taiga من قبل، فلماذا Plane؟ والإجابة أن Taiga تدخل اليوم مرحلة صيانة أكثر من مرحلة تطوير، وأما Plane فتصدر نسخة جديدة كل أسابيع قليلة وواجهتها أقرب لما اعتاد عليه فريق قادم من Jira، ولكن عليك أن تعرف قبل التثبيت أن Plane تأتي بنسختين، وأن جزءاً مهماً من ميزاتها لا يوجد في النسخة المجانية، وأن العربية فيها تعمل في العناوين ولكنها لا تعمل بشكل صحيح في محرر النصوص، وكل هذا سوف نراه بالاختبار الفعلي في هذا الدليل. وإذا كنت ما زلت في مرحلة اختيار الأداة نفسها، فابدأ بالمقالين التاليين ثم ارجع إلى هنا:
دليلكيف تختار أداة إدارة المشاريع Project Management لفريقك؟قبل أن تشتري Jira أو تثبت أداة مفتوحة المصدر، حدد طريقة عمل فريقك ومن سيستخدم الأداة وأين تبقى بياناتك، ثم جرب على مشروع حقيقي.
دليلأدوات إدارة المشاريع مفتوحة المصدر بديلاً عن Jira وAsanaمقارنة بين أدوات إدارة المشاريع مفتوحة المصدر والأدوات التجارية بالرخصة والسعر ونشاط التطوير، مع اختبار حقيقي للعربية في خمس منها.وفي هذا المقال سوف نتناول:
- الفرق بين Community Edition والنسخة التجارية Commercial Edition، وما الذي يعمل مجاناً بالفعل.
- الخدمات الثلاث عشرة التي تتكون منها Plane، ثم التثبيت بملفات الإصدار الرسمية مع تثبيت الإصدار Version Pinning وتوليد الأسرار Secrets.
- إعداد المدير Instance Admin، ثم مساحة العمل Workspace والمشروع والمهام والسبرنتات والوحدات والعروض Views والصفحات وصندوق الطلبات Intake.
- الربط مع GitHub وGitLab، والاستيراد من Jira، واختبار العربية واتجاه النص RTL.
- النسخ الاحتياطي والاستعادة بالتجربة، ثم التحديث والمشكلات الشائعة.
أي نسخة من Plane تثبت؟ Community أم Commercial
عندما تفتح صفحة التثبيت الرسمية سوف تجد أن الشرح الأساسي فيها للنسخة التجارية، وأن النسخة المجتمعية Community Edition موجودة في قسم مطوي، وهذا ليس صدفة، والسبب أن Plane تبيع اشتراكاتها عبر النسخة التجارية. ولذلك من المهم أن تفهم الفرق بين النسختين قبل أن تختار:
| Community Edition | Commercial Edition | |
|---|---|---|
| الترخيص License | مفتوحة المصدر برخصة AGPL-3.0 | مغلقة المصدر |
| الميزات | تعادل الخطة المجانية Free في Plane Cloud | كل ميزات Cloud، وتفتح الخطط المدفوعة بمفتاح ترخيص |
| عدد المستخدمين | لا يوجد حد في الترخيص | 12 مقعداً مجانياً لكل Workspace، وما زاد عليها مدفوع |
| الترقية إلى خطة مدفوعة | تحتاج أولاً إلى الانتقال إلى Commercial Edition | من داخل التطبيق مباشرة |
وفي التطبيق نفسه بعد التثبيت سوف تجد أن قائمة إعدادات مساحة العمل في Community Edition فيها General وMembers وBilling & Plans وExports وWebhooks فقط، ولا توجد فيها صفحة Imports ولا Integrations، وعند فتح الرابط /settings/imports مباشرة تظهر صفحة غير موجودة (404). وبمقارنة صفحة الأسعار (راجعناها في أكتوبر 2026) مع ما وجدناه في التثبيت، فهذه أهم الميزات التي لا تحصل عليها في Community Edition:
- المستوردات Importers، ومنها Jira، فالتوثيق يقول صراحة إنها متاحة في Plane Cloud والنسخة التجارية فقط.
- تكامل GitHub وGitLab الذي يربط ال Pull Requests بالمهام ويزامن ال Issues، وهو في خطة Pro.
- الدخول الموحد عبر LDAP أو OIDC أو SAML.
- تتبع الوقت Time Tracking، وسير العمل والموافقات Workflows and Approvals، وأنواع المهام والحقول المخصصة Custom Properties، والقوالب Templates.
- نماذج Intake الخارجية وإنشاء الطلبات من البريد، أما Intake داخل التطبيق فموجود.
- Wiki على مستوى مساحة العمل، والتحرير المشترك الفوري، والصفحات المتداخلة Nested Pages، أما صفحات المشروع Project Pages فموجودة.
وأما السعر فصفحة الأسعار تذكر خطة Pro بسعر 6 دولارات للمستخدم شهرياً عند الدفع السنوي و8 دولارات عند الدفع الشهري، وخطة Business بسعر 13 و15 دولاراً، بينما شاشة Billing & Plans داخل الإصدار v1.4.2 الذي ثبتناه تعرض Pro بسعر 10 دولارات شهرياً و8 دولارات عند الدفع السنوي، لذلك اعتمد على عرض السعر الذي يصلك من Plane نفسها قبل أي قرار.
وفي هذا الدليل سوف نثبت Community Edition، والسبب أنها النسخة المفتوحة التي تملك بياناتها وكودها بالكامل، وهي تكفي فريقاً يريد المهام والسبرنتات واللوحات والصفحات، أما إذا كان الاستيراد من Jira أو الربط مع GitHub شرطاً عندك، فاعرف من الآن أنك تحتاج النسخة التجارية.
ما تحتاجه قبل أن تبدأ Requirements
- سيرفر Linux بمعالجين CPU وذاكرة RAM بحجم 4 GB كحد أدنى و8 GB للإنتاج، وهذه أرقام التوثيق الرسمي. وفي اختبارنا استهلكت الحزمة كلها قرابة 1.6 GB من الذاكرة وهي خاملة، أكبرها خدمة
workerبحوالي 715 MB. - مساحة قرص للـ Images وحدها بحوالي 5 GB، فخدمتا
liveوspaceوحدهما تقتربان من 1.7 GB و1.5 GB، ثم مساحة البيانات والمرفقات. - Docker Engine مع Docker Compose كما في دليل تثبيت Docker على Ubuntu.
- نطاق فرعي Subdomain مثل
plane.example.comيشير إلى السيرفر (203.0.113.10)، وحساب SMTP إذا أردت الدعوات وإشعارات البريد.
مكونات Plane وما يفعله كل جزء منها Architecture
قد تبدو Plane تطبيقاً واحداً في المتصفح، لكن في الواقع فهي ثلاث عشرة خدمة Service في ملف Compose واحد، والصورة التالية تبين كيف يمر الطلب بينها:

| الخدمة | الدور |
|---|---|
proxy | سيرفر Caddy هو الوحيد الذي يفتح منفذاً Port للخارج، ويوزع المسارات على بقية الخدمات، ويستطيع أيضاً إصدار شهادة TLS بنفسه |
web وspace وadmin | الواجهات Frontends: التطبيق نفسه، والصفحات العامة المنشورة، ولوحة إدارة السيرفر على المسار /god-mode/ |
live | سيرفر WebSocket لمحرر الصفحات Pages |
api | الخلفية Backend المبنية على Django، وفيها ال API الداخلي والعام |
worker وbeat-worker | نفس Image الخلفية، ولكنها تنفذ مهام Celery في الخلفية والمهام المجدولة، مثل التصدير Export والإشعارات |
migrator | يطبق تعديلات قاعدة البيانات Migrations عند كل تشغيل ثم يخرج |
plane-db | قاعدة البيانات Database، وهي PostgreSQL |
plane-redis | Valkey للتخزين المؤقت Cache والجلسات |
plane-mq | RabbitMQ، وهو طابور Queue المهام بين ال api وال worker |
plane-minio | MinIO لتخزين الملفات المرفوعة Uploads والتصديرات، وهو تخزين متوافق مع S3 |
لاحظ أن الملفات المرفوعة لا تحفظ في قاعدة البيانات وإنما في MinIO، وهذا يعني أن نسخة احتياطية من PostgreSQL وحدها ليست نسخة كاملة، وسوف نرجع لهذه النقطة في قسم النسخ الاحتياطي.
تثبيت Plane خطوة بخطوة Installation
تنزيل ملفات الإصدار الرسمية
الطريقة الرسمية التي يشرحها التوثيق هي سكربت setup.sh، وهو قائمة نصية فيها Install وStart وStop وUpgrade وBackup، وعند اختيار Install يقوم بتنزيل ملفين من صفحة الإصدار على GitHub هما docker-compose.yml وvariables.env، ثم يحفظهما في مجلد plane-app باسمي docker-compose.yaml وplane.env. ولكن هناك مشكلة رئيسية في هذه الطريقة، فالسكربت يأخذ آخر إصدار مستقر Stable في لحظة التثبيت، فلا تعرف بالضبط ما الذي ثبته، لذلك سوف نأخذ نفس الملفين مباشرة من صفحة الإصدار v1.4.2، وبهذا الشكل يكون الإصدار مثبتاً في الملف وتعرف ما الذي يعمل على سيرفرك:
sudo mkdir -p /opt/plane/plane-app
cd /opt/plane/plane-app
REL=https://github.com/makeplane/plane/releases/download/v1.4.2
sudo curl -fsSL -o docker-compose.yaml $REL/docker-compose.yml
sudo curl -fsSL -o plane.env $REL/variables.env
sudo curl -fsSL -o setup.sh $REL/setup.sh
sudo curl -fsSL -o restore.sh $REL/restore.sh
sudo chmod +x setup.sh restore.shوفي ملف docker-compose.yaml سوف تجد أن كل Images الخاصة بـ Plane مكتوبة بالشكل makeplane/plane-backend:${APP_RELEASE:-v1.4.2}، أي أن الإصدار يأتي من المتغير APP_RELEASE في ملف plane.env، وقيمته الافتراضية في الملف stable، لذلك أول تعديل هو تثبيته على رقم الإصدار، وأما قاعدة البيانات وبقية الخدمات فمثبتة في الملف نفسه: postgres:15.7-alpine وvalkey/valkey:7.2.11-alpine وrabbitmq:3.13.6-management-alpine.
ملف plane.env بأسرار مولدة Secrets
القيم الافتراضية في plane.env منشورة للجميع، فكلمة مرور قاعدة البيانات plane وكلمة مرور RabbitMQ plane وSECRET_KEY قيمته change-this-key-on-deployment، لذلك قم بتوليد قيم عشوائية لكل سر:
cd /opt/plane/plane-app
PG=$(openssl rand -hex 16); MQ=$(openssl rand -hex 16)
sudo sed -i \
-e "s|^APP_RELEASE=.*|APP_RELEASE=v1.4.2|" \
-e "s|^APP_DOMAIN=.*|APP_DOMAIN=plane.example.com|" \
-e "s|^WEB_URL=.*|WEB_URL=https://plane.example.com|" \
-e "s|^CORS_ALLOWED_ORIGINS=.*|CORS_ALLOWED_ORIGINS=https://plane.example.com|" \
-e "s|^LISTEN_HTTP_PORT=.*|LISTEN_HTTP_PORT=8080|" \
-e "s|^LISTEN_HTTPS_PORT=.*|LISTEN_HTTPS_PORT=8443|" \
-e "s|^SECRET_KEY=.*|SECRET_KEY=$(openssl rand -hex 32)|" \
-e "s|^LIVE_SERVER_SECRET_KEY=.*|LIVE_SERVER_SECRET_KEY=$(openssl rand -hex 32)|" \
-e "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$PG|" \
-e "s|^RABBITMQ_PASSWORD=.*|RABBITMQ_PASSWORD=$MQ|" \
-e "s|^AWS_SECRET_ACCESS_KEY=.*|AWS_SECRET_ACCESS_KEY=$(openssl rand -hex 16)|" \
-e "s|^DATABASE_URL=.*|DATABASE_URL=postgresql://plane:$PG@plane-db:5432/plane|" \
-e "s|^AMQP_URL=.*|AMQP_URL=amqp://plane:$MQ@plane-mq:5672/plane|" \
plane.env
sudo chmod 600 plane.envفي الإعداد أعلاه لاحظ التالي:
WEB_URLوCORS_ALLOWED_ORIGINSيجب أن يطابقا العنوان الذي يكتبه المستخدم في المتصفح بالضبط، مع البروتوكول والمنفذ إن وجد، فإذا كنت تجرب على السيرفر بلا نطاق فاكتبhttp://203.0.113.10:8080.- غيرنا
LISTEN_HTTP_PORTإلى 8080 لأننا سوف نضع Reverse Proxy أمام Plane يستقبل المنفذين 80 و443، وإذا كانت Plane وحدها على السيرفر فيمكنك ترك 80 و443. - السطران الأخيران أهم ما في الإعداد، والسبب في الخطوة التالية.
لماذا يجب تعديل DATABASE_URL أيضاً؟
لنفرض أنك غيرت POSTGRES_PASSWORD فقط وتركت DATABASE_URL فارغاً كما في الملف الأصلي، فالمتوقع أن تأخذ Plane كلمة المرور الجديدة، ولكن ما يحدث فعلياً أن ملف Compose يعرف المتغير بهذا الشكل:
DATABASE_URL: ${DATABASE_URL:-postgresql://plane:plane@plane-db/plane}
AMQP_URL: ${AMQP_URL:-amqp://plane:plane@plane-mq:5672/plane}والقيمة الفارغة في Compose تعامل مثل القيمة غير الموجودة، فتستخدم Plane الرابط الافتراضي بكلمة المرور plane، بينما أنشأت قاعدة البيانات المستخدم بكلمة المرور الجديدة، وعند التشغيل سوف ترى في سجلات migrator وapi الخطأ التالي يتكرر:
django.db.utils.OperationalError: connection failed: connection to server at "192.168.112.3", port 5432 failed: FATAL: password authentication failed for user "plane"لذلك عليك بكتابة الرابطين كاملين بكلمتي المرور الجديدتين كما فعلنا في الخطوة السابقة، وإذا وقعت في هذا الخطأ بعد التشغيل فيكفي تصحيح plane.env ثم تشغيل docker compose up -d مرة أخرى، فلا تحتاج إلى حذف ال Volumes.
التشغيل الأول ومتابعة migrator
cd /opt/plane/plane-app
sudo docker compose -f docker-compose.yaml --env-file plane.env pull
sudo docker compose -f docker-compose.yaml --env-file plane.env up -d
sudo docker compose -f docker-compose.yaml --env-file plane.env logs -f migratorوهذا بالضبط ما يفعله ./setup.sh start، أي docker compose up -d بنفس الملفين. ولاحظ أن خدمة migrator تطبق في التثبيت الأول 164 تعديلاً على قاعدة البيانات، وهذا قد يأخذ عدة دقائق على قرص بطيء، وفي هذه الفترة يعطي المسار /api/ الخطأ 502 لأن خدمة api تنتظر قاعدة البيانات، فلا تقلق منه. وعندما ينتهي سوف تجد آخر السجلات كما يلي:
migrator-1 | Applying license.0006_instance_is_current_version_deprecated... OK
migrator-1 | Applying sessions.0001_initial... OKثم تتحول حالة migrator إلى Exited (0) وتبقى بقية الخدمات تعمل، وتستطيع التأكد من جاهزية ال API بطلب بسيط:
curl -s http://localhost:8080/api/instances/ | head -c 300والمخرج سوف يبدأ بإعدادات السيرفر، ومنها "instance_name":"Plane Community Edition" و"current_version":"1.4.2" و"edition":"PLANE_COMMUNITY"، وهذه الثلاثة تؤكد لك النسخة والإصدار الذي يعمل.
الإعداد الأول: مدير السيرفر ومساحة العمل
حساب مدير السيرفر Instance Admin
افتح https://plane.example.com/god-mode/، وأول من يفتح هذه الصفحة هو من ينشئ حساب مدير السيرفر، لذلك لا تترك السيرفر مكشوفاً للإنترنت قبل هذه الخطوة. وفي النموذج سوف تجد خانة Allow Plane to anonymously collect usage events مفعلة افتراضياً، وهي ترسل بيانات استخدام مجهولة Telemetry إلى Plane، فإذا كانت سياسة مؤسستك لا تسمح بذلك فألغها هنا:

بعد ذلك ادخل إلى صفحة Authentication في نفس اللوحة، وهنا خطوتان مهمتان:
- الخيار Allow anyone to sign up even without an invite مفعل افتراضياً، أي أن أي شخص يصل إلى الرابط يستطيع إنشاء حساب، فأوقفه إذا كان السيرفر مفتوحاً على الإنترنت، فلا يدخل إلا من تدعوه.
- طرق الدخول المتاحة في Community Edition هي كلمة المرور، والرموز عبر البريد Unique Codes إذا ضبطت SMTP، والدخول بحساب Google أو GitHub أو GitLab أو Gitea عبر OAuth. ولاحظ أن LDAP وOIDC وSAML غير موجودة هنا.

مساحة العمل Workspace
بعد إنشاء المدير ادخل إلى التطبيق من العنوان الرئيسي، وسوف يطلب منك اسمك ثم إنشاء أول مساحة عمل، ومساحة العمل هي المؤسسة أو الفريق، وفيها المشاريع والأعضاء، ورابطها Slug يظهر في كل عنوان مثل plane.example.com/example/، لذلك اختره قصيراً وثابتاً لأنك لن ترغب بتغييره لاحقاً:

العمل اليومي في Plane
إذا كنت قرأت مقال Agile وScrum وKanban بلا شعارات فسوف تجد أن Plane تعطيك أدوات الأسلوبين معاً، وفيما يلي كيف تقابل كل فكرة شاشة في التطبيق، ولاحظ أن ما يلي جربناه على مشروع باسم عربي، وأن الصور كلها من نفس التثبيت.
المشروع والمهام Work Items
المشروع Project له معرف قصير Identifier، مثل PORTAL، وكل مهمة تأخذ رقماً بعده مثل PORTAL-8، وهذا الرقم هو ما يذكره الفريق في المحادثات وفي رسائل ال Commits. ولكل مهمة حالة State من خمس مجموعات ثابتة: Backlog وUnstarted وStarted وCompleted وCancelled، وتستطيع إضافة حالات داخل كل مجموعة، ولها أولوية Priority وتواريخ بداية ونهاية وتصنيفات Labels ومسؤول Assignee. والصورة التالية تبين المهام في عرض القائمة List:

ومن نفس الشاشة تنتقل بين خمسة أشكال للعرض Layouts: القائمة، ولوحة Kanban، والتقويم Calendar، والجدول Spreadsheet، ومخطط Gantt. وفي لوحة Kanban تسحب المهمة من عمود إلى آخر فتتغير حالتها:

وأما مخطط Gantt فيرسم المهام التي لها تاريخ بداية ونهاية على خط زمني، وهو كاف لمتابعة الجدول، ولكن الاعتماديات Dependencies بين المهام على الخط الزمني من ميزات الخطط المدفوعة حسب صفحة الأسعار، فإذا كان التخطيط بالاعتماديات والمسار الحرج أساس عملك فقد تناسبك أداة مثل OpenProject أكثر:

السبرنتات Cycles
ما يسميه Scrum سبرنت Sprint تسميه Plane دورة Cycle، وهي فترة بتاريخ بداية ونهاية تضع فيها مجموعة مهام، وعندما تكون الدورة نشطة تعرض Plane نسبة الإنجاز ومخطط Burndown الذي يقارن المهام المتبقية بالخط المثالي. وفي المثال التالي وضعنا أربع مهام في الدورة وأنهينا واحدة، فظهرت النسبة 25%:

ولاحظ أن نقل المهام غير المنتهية تلقائياً إلى الدورة التالية Auto-transfer وبدء الدورات وإيقافها يدوياً من ميزات الخطط المدفوعة، ففي Community Edition تنقلها بنفسك في نهاية كل دورة.
الوحدات Modules والعروض Views
الدورة تقسم العمل حسب الزمن، والوحدة Module تقسمه حسب الجزء من المنتج، مثل «وحدة الدفع الإلكتروني» أو «تطبيق الجوال»، والمهمة الواحدة يمكن أن تكون في دورة وفي وحدة في نفس الوقت، وللوحدة حالتها وتواريخها ومسؤولها:

وأما العرض Views فهو مرشح Filter محفوظ باسم، مثل «العاجل والمهم» الذي يعرض المهام ذات الأولوية Urgent أو High فقط، فيفتحه مدير المشروع كل صباح بدل أن يعيد بناء المرشح كل مرة. ولاحظ أن الدورات والوحدات والعروض وIntake ميزات تفعل لكل مشروع من إعداداته في Features، فإذا لم تجدها في القائمة الجانبية فابحث عنها هناك.
صندوق الطلبات Intake
هناك مشكلة رئيسية في أي أداة مهام، وهي أن الطلبات تأتي من خارج الفريق: من الإدارة المالية أو من الدعم الفني أو من عميل، فإذا أضافها كل شخص مباشرة إلى قائمة المهام امتلأت القائمة بما لم يقرره أحد. ولذلك وضعت Plane صندوق Intake، حيث تدخل الطلبات بحالة Pending، ثم يراجعها مسؤول المشروع فيقبلها Accept فتنتقل إلى المشروع، أو يرفضها Decline، أو يؤجلها Snooze إلى تاريخ، أو يربطها بمهمة موجودة Duplicate:

وفي Community Edition تدخل الطلبات من داخل التطبيق فقط، من عضو أو ضيف Guest أو عبر ال API، أما النموذج العام Intake Form والطلبات عبر البريد فمن الخطط المدفوعة.
صفحات التوثيق Pages
لكل مشروع صفحات Pages لمحاضر الاجتماعات والمواصفات، ومحررها يدعم القوائم والجداول والصور، وتستطيع تصديرها PDF أو نسخها بصيغة Markdown. وسوف نرجع للصفحات في قسم العربية، لأنها المكان الذي ظهرت فيه أهم مشكلة في اختبارنا.
الربط مع GitHub وGitLab والاستيراد من Jira
هذا هو القسم الذي يجب أن تقرأه بتمعن إذا كان فريقك قادماً من Jira، فالربط الحقيقي مع GitHub في Plane، أي أن يذكر المطور [PORTAL-8] في عنوان ال Pull Request فتنتقل المهمة تلقائياً إلى In Progress ثم إلى Done عند الدمج Merge، هو تكامل في خطة Pro، وكذلك تكامل GitLab وSlack. وأما ما تجده في Community Edition فهو أمران:
- الدخول بحساب GitHub أو GitLab أو Gitea، وهو تسجيل دخول OAuth فقط ولا يربط المستودعات بالمشاريع.
- Webhooks في إعدادات مساحة العمل، وREST API عام بمفتاح API Key ينشئه كل مستخدم من إعدادات حسابه، وبهما تستطيع أن تبني ربطاً بسيطاً بنفسك، مثل خطوة في ال Pipeline تغير حالة المهمة عند النشر.

المثال التالي يبين ال API العام، حيث نقرأ حالات المشروع ثم ننشئ مهمة:
API=https://plane.example.com/api/v1/workspaces/example
KEY=plane_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
PROJECT=f737e66d-73f0-4b89-b718-f851db568df2
curl -s -H "X-API-Key: $KEY" $API/projects/$PROJECT/states/ \
| jq -r '.results[] | "\(.name) \(.group)"'والمخرج سوف يكون كما يلي:
Backlog backlog
Todo unstarted
In Progress started
Done completed
Cancelled cancelledcurl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
$API/projects/$PROJECT/work-items/ \
-d '{"name":"نموذج طلب الخدمة الجديد","priority":"medium"}' \
| jq '{sequence_id, name, priority}'ويرجع الطلب الرمز 201 ومعه المهمة الجديدة برقمها في المشروع. ولاحظ أن ال API محدود افتراضياً بستين طلباً في الدقيقة لكل مفتاح، وهذا تحدده القيمة API_KEY_RATE_LIMIT=60/minute في plane.env، فإذا كانت لديك أداة ترحيل Migration ترسل آلاف الطلبات فارفعها مؤقتاً.
وأما الاستيراد من Jira فالمستوردات متاحة في Plane Cloud والنسخة التجارية فقط، وفي تثبيتنا لا توجد صفحة Imports أصلاً، وحسب صفحة الأسعار فمستوردات Jira وLinear وAsana وClickUp وCSV داخلة في الخطة المجانية للنسخة التجارية. لذلك إذا كان الترحيل من Jira شرطاً عندك فأمامك طريقان: أن تثبت Commercial Edition بخطتها المجانية لتستخدم المستورد، أو أن تكتب سكربت ترحيل يقرأ من Jira ويكتب في ال API العام كما في المثال أعلاه. ولم نختبر المستورد نفسه لأنه غير موجود في النسخة التي ثبتناها.
هل تعمل العربية في Plane؟ اختبار RTL
لا توجد واجهة عربية في Plane، فاللغات المتاحة في الإصدار v1.4.2 هي الإنجليزية ومعها لغات منها الفرنسية والألمانية والإسبانية والروسية والتركية واليابانية والصينية، والتخطيط Layout يبقى من اليسار إلى اليمين، وهناك طلب مفتوح لدعم RTL على GitHub. ولذلك اختبرنا البيانات العربية نفسها، وكانت النتيجة كما يلي:
| ما اختبرناه | النتيجة |
|---|---|
| اسم المشروع وعناوين المهام والتصنيفات والدورات والوحدات | تحفظ وتظهر صحيحة في القائمة واللوحة وGantt، ولكنها محاذاة لليسار |
| وصف المهمة ومحرر الصفحات Pages | الفقرة اتجاهها LTR، فالجملة المختلطة بالعربية والإنجليزية تلتف بترتيب خاطئ، والنقطة في نهاية الجملة تظهر في جهة اليسار، والنقاط في القوائم على اليسار. وزر المحاذاة لليمين ينقل النص فقط ولا يصحح الترتيب |
| تصدير الصفحة PDF | الحروف العربية غير مقروءة، وخرج العنوان فقط بدون محتوى الصفحة |
| تصدير المهام CSV من صفحة Exports | الملف UTF-8 والعربية فيه صحيحة، ولكنه بدون BOM، لذلك افتحه في Excel من Data ثم From Text/CSV حتى تظهر الحروف صحيحة |
والصورة التالية من محرر الصفحات بعد كتابة محضر اجتماع قصير، ولاحظ السطر الأول: الجملة الأصلية هي «اتفق الفريق على تسليم نموذج طلب الخدمة قبل نهاية الأسبوع، وتأجيل الربط مع SSO إلى السبرنت الثاني.» ولكنها ظهرت مقسومة عند كلمة SSO بترتيب معكوس:

وأما تصدير نفس الصفحة PDF فكانت نتيجته الصورة التالية، وهي مشكلة مسجلة في المستودع ولم تغلق بعد:

والخلاصة العملية: Plane تصلح لفريق يكتب عناوين المهام بالعربية ويعيش مع واجهة إنجليزية، ولكنها لا تصلح اليوم مكاناً لتوثيق طويل بالعربية، فإذا كانت محاضرك ومواصفاتك عربية فاحفظها في أداة توثيق تدعم RTL واربطها من المهمة.
ربط النطاق مع شهادة TLS
خدمة proxy في Plane مبنية على Caddy وتستطيع أن تصدر شهادة Let's Encrypt بنفسها إذا كانت على المنفذين 80 و443، حيث تضع اسم النطاق في SITE_ADDRESS وبريدك في CERT_EMAIL. ولكن إذا كان على السيرفر خدمات أخرى فالأفضل أن تترك Plane على المنفذ 8080 كما فعلنا، وتضع أمامها Reverse Proxy مثل Nginx Proxy Manager يوجه plane.example.com إلى http://203.0.113.10:8080 مع تفعيل دعم WebSocket، والسبب أن محرر الصفحات يعتمد على اتصال WebSocket مع خدمة live. وبعد تفعيل الشهادة تأكد أن WEB_URL وCORS_ALLOWED_ORIGINS يبدآن بـ https://، ثم أعد التشغيل. ولم نختبر إصدار شهادة حقيقية لأنه يحتاج نطاقاً عاماً، وإنما اختبرنا الوصول عبر HTTP على منفذ محلي.
كيف تتأكد أن كل شيء يعمل
docker compose -f docker-compose.yaml --env-file plane.env ps -a: كل الخدمات بحالة running، وmigratorوحده بحالةExited (0).curl -s https://plane.example.com/api/instances/يرجع JSON فيه"current_version":"1.4.2".- أنشئ مهمة وارفع لها مرفقاً، ثم افتحه من جهاز آخر، فهذا يختبر MinIO والمسار
/uploads/معاً. - افتح صفحة من جهازين في نفس الوقت واكتب في أحدهما، فإذا ظهرت الكتابة في الآخر فخدمة
liveوال WebSocket يعملان. - من صفحة Exports صدر المشروع CSV، فإذا وصل الملف فخدمة
workerوRabbitMQ يعملان.
النسخ الاحتياطي Backup والاستعادة Restore
الخيار 7 في setup.sh واسمه Backup Data ينسخ مجلدات البيانات من أربع خدمات هي plane-db وplane-minio وplane-mq وplane-redis إلى مجلد backup/ بتاريخ اليوم، ويستعيدها السكربت restore.sh. ولكن لاحظ أن السكربت ينسخ مجلد PostgreSQL بالأمر docker cp وقاعدة البيانات تعمل، ونسخ ملفات قاعدة بيانات تعمل قد ينتج نسخة غير متسقة إذا تزامن مع كتابة، لذلك الأسلم أن تعتمد على pg_dump لقاعدة البيانات، ومعه أرشيف لل Volume الخاص بـ MinIO، فهذان هما البيانات التي لا تعوض، وأما Valkey وRabbitMQ فيعاد بناؤهما.
cd /opt/plane/plane-app
mkdir -p backup
C="docker compose -f docker-compose.yaml --env-file plane.env"
$C exec -T plane-db pg_dump -h /var/run/postgresql -U plane -d plane -Fc > backup/plane-db.dump
docker run --rm -v plane-app_uploads:/data:ro -v "$PWD/backup":/backup alpine:3.22 \
tar czf /backup/plane-uploads.tar.gz -C /data .
ls -la backupفي الأوامر أعلاه لاحظ التالي:
- كتبنا
-h /var/run/postgresqlلأن داخل Container قاعدة البيانات متغيرPGHOST=plane-db، فبدونه يتصلpg_dumpعبر الشبكة ويطلب كلمة مرور، فيفشل بالخطأfe_sendauth: no password supplied. - اسم ال Volume يبدأ باسم المجلد، فمع المجلد
plane-appيكونplane-app_uploads، وتستطيع التأكد منه بالأمرdocker volume ls. - أضف
plane.envإلى النسخة، فبدونه لا تعرف كلمات المرور ولاSECRET_KEY، واحفظ الكل خارج السيرفر.
ونسخة لم تجرب استعادتها لا يعتمد عليها، لذلك جربنا أسوأ حالة: حذفنا الخدمات وكل ال Volumes بالأمر down -v، ثم شغلنا قاعدة البيانات وMinIO وحدهما، واستعدنا البيانات قبل تشغيل بقية الخدمات، والسبب أن migrator لو عمل على قاعدة فارغة لأنشأ جداول جديدة تتعارض مع الاستعادة:
C="docker compose -f docker-compose.yaml --env-file plane.env"
$C down -v
$C up -d plane-db plane-minio
until $C exec -T plane-db pg_isready -h /var/run/postgresql -U plane; do sleep 2; done
docker run --rm -v plane-app_uploads:/data -v "$PWD/backup":/backup alpine:3.22 \
tar xzf /backup/plane-uploads.tar.gz -C /data
$C exec -T plane-db pg_restore -h /var/run/postgresql -U plane -d plane --clean --if-exists --no-owner < backup/plane-db.dump
$C up -dوبعد الاستعادة أعاد ال API نفس المهام الست بأرقامها وعناوينها العربية، ورجعت الصفحات الثلاث ومنها محضر الاجتماع، واشتغل مفتاح ال API القديم بدون تغيير لأنه محفوظ في قاعدة البيانات، وأخذ migrator هذه المرة 31 ثانية فقط لأنه لم يجد تعديلات جديدة يطبقها.
التحديث Upgrade إلى إصدار أحدث
- اقرأ ملاحظات الإصدار في صفحة الإصدارات، وتجنب الإصدارات التي تنتهي بـ
-rcلأنها مرشحة وليست مستقرة. - خذ نسخة احتياطية كما في القسم السابق.
- نزل ملفي
docker-compose.ymlوvariables.envللإصدار الجديد، وقارنvariables.envبملفك لترى المتغيرات الجديدة، ثم غيرAPP_RELEASEإلى رقم الإصدار الجديد. - شغل
pullثمup -d، وتابع سجلاتmigratorحتى يخرج بالرمز 0.
والخيار 5 في setup.sh واسمه Upgrade يفعل نفس الخطوات تقريباً، حيث ينزل الملفين ويحفظ القديم في مجلد archive، ولكنه يأخذ آخر إصدار مستقر وليس إصداراً تختاره أنت. ولاحظ أن التحديث لا رجوع عنه إلا من النسخة الاحتياطية، والسبب أن migrator يعدل جداول قاعدة البيانات.
مشكلات شائعة وحلولها
password authentication failed for user "plane"
غيرت POSTGRES_PASSWORD وتركت DATABASE_URL فارغاً، فاستخدمت Plane الرابط الافتراضي بكلمة المرور القديمة. اكتب DATABASE_URL وAMQP_URL كاملين كما في قسم ملف plane.env ثم شغل up -d.
الخطأ 502 على /api بعد التشغيل
خدمة api تنتظر انتهاء migrator، وفي التثبيت الأول قد يأخذ هذا عدة دقائق. تابع logs -f migrator، فإذا خرج بالرمز 0 واستمر الخطأ فانظر في سجلات api.
لا أجد Imports ولا Integrations
هذا متوقع في Community Edition، فالمستوردات والتكاملات في النسخة التجارية، كما شرحنا في قسم الربط مع GitHub.
النص العربي في PDF غير مقروء
هذه مشكلة في تصدير الصفحات في Plane نفسها وليست في إعدادك، فاستخدم Copy markdown من قائمة الصفحة وانقل النص إلى أداة تدعم العربية حتى يصلح Plane التصدير.
الخلاصة
- Plane Community Edition مفتوحة المصدر برخصة AGPL-3.0، وتعطيك المهام واللوحات وGantt والدورات والوحدات والعروض والصفحات وIntake داخل التطبيق، بلا حد لعدد المستخدمين.
- المستوردات ومنها Jira، وتكامل GitHub وGitLab، وLDAP وOIDC وSAML، وتتبع الوقت وسير العمل، كلها في النسخة التجارية، فاحسم هذه النقاط قبل التثبيت.
- ثبت الإصدار في
APP_RELEASE، وولد كل الأسرار، واكتبDATABASE_URLوAMQP_URLبكلمات المرور الجديدة. - العناوين العربية تعمل، أما محرر الصفحات وتصدير PDF فلا يدعمان العربية بشكل صحيح في الإصدار v1.4.2.
- انسخ قاعدة البيانات بـ
pg_dumpوال Volume الخاص بـ MinIO معاً، وجرب الاستعادة قبل أن تحتاجها.
وفي الدليل التالي بإذن الله سوف نثبت OpenProject، وهي أداة مبنية حول مكتب المشاريع PMO ومخططات Gantt والميزانيات، لترى الفرق بين أداة صممت للفريق وأداة صممت للمؤسسة.
سجل التحديثات (Changelog)
- أكتوبر 2026: كتابة الدليل واختباره على Plane Community Edition v1.4.2.