استضافة Planka ذاتياً باستخدام Docker Compose
انشر Planka على VPS عبر Docker Compose مع Postgres وTraefik، واضبط متغيرات إنشاء المسؤول وBASE_URL لتجنب خطأ تسجيل الدخول الناتج عن العنوان الخاطئ.
ما الذي تحصل عليه عند استضافة Planka ذاتياً
تمنحك استضافة Planka ذاتياً لوحة Kanban لفريقك، مع نموذج البطاقات والقوائم والتسميات الذي يعرفه المستخدمون من Trello، وتعمل على VPS تتحكم فيه. لا توجد حدود لعدد المستخدمين ولا فوترة لكل مستخدم، لأن التكلفة الوحيدة هي تكلفة الخادم. ينشر هذا الدليل التطبيق باستخدام Docker Compose خلف Traefik، مع استخدام Postgres لتخزين البيانات ووحدة تخزين مسماة لكل ملف يحمّله المستخدمون.
أفترض أن القارئ يدير فريقاً من شخصين إلى خمسة أشخاص ينتقلون من الخطة المجانية في Trello. إذا كنت لا تزال تقرر أي لوحة ستستخدم، فاقرأ أولاً مقارنة بدائل Trello المستضافة ذاتياً. يفترض هذا الدليل أن القرار اتُّخذ بالفعل، ويغطي النشر فقط.
تحتاج إلى VPS يشغّل Docker Engine مع Compose plugin، وإلى سجل DNS من نوع A يشير إليه. تحتاج أيضاً إلى مثيل Traefik مُعد مسبقاً لإنهاء TLS (أمان طبقة النقل) على ذلك الخادم. إذا لم يكن Traefik مُعداً بعد، فأعد أولاً إعداد reverse proxy باستخدام Traefik أمام عدة تطبيقات Compose، واقرأ أساسيات Docker Compose على VPS إذا بدا الملف أدناه غير مألوف.
ما مقدار موارد VPS التي يحتاجها Planka؟
لا ينشر المشروع حداً أدنى لمواصفات العتاد، لذلك تعامل مع أي رقم تقرؤه على أنه نقطة بداية، لا قياساً فعلياً. الرقم الذي يتكرر في صفحات الاستضافة، وهو 2 vCPU و4 GB، يمثل إعداداً افتراضياً مريحاً لدى مزود الخدمة، وليس متطلباً قاسه المشروع. وهو سخي بالنسبة إلى لوحة يستخدمها خمسة أشخاص.
ما يعمل فعلياً صغير الحجم: عملية Node.js واحدة لتقديم API والواجهة الأمامية المبنية، وعملية Postgres واحدة لحفظ البيانات. كما تعمل عملية proxy صغيرة ثالثة داخل حاوية Planka لتصفية طلباتها الصادرة. تكفي خطة تضم 1 vCPU و2 GB للوحة يستخدمها شخصان إلى خمسة أشخاص، وينتهي معظم الذاكرة الاحتياطية في ذاكرة التخزين المؤقت لدى Postgres. لا تستهلك اللوحة موارد كبيرة، لذلك إذا كان VPS نفسه سيستضيف أيضاً مستندات فريقك، فحدد الموارد وفقاً لذلك التطبيق أولاً: تشغيل AFFiNE كمساحة عمل على نمط Notion يحتاج إلى بضعة GB بمفرده قبل أن يطلب Planka أي موارد.
حدّد سعة القرص قبل تحديد سعة الذاكرة، لأن المرفقات هي الجزء الذي ينمو. قِس مثيلك بنفسك بدلاً من الاعتماد على هذه الفقرة:
docker stats --no-stream
docker system df -vيعرض الأمر الأول الذاكرة ووحدة المعالجة المركزية المستخدمة حالياً لكل حاوية. ويعرض الأمر الثاني مقدار المساحة التي يشغلها كل volume. أجرِ القياسين بعد أسبوع عمل عادي، لا في يوم التثبيت، لأن لوحة خاملة لا تخبرك بشيء عن فريقك.
إنشاء ملف Compose
أنشئ الدليل وتولَّ ملكيته، حتى لا تضطر إلى تحرير هذه الملفات عبر sudo.
sudo mkdir -p /opt/planka
sudo chown "$USER":"$USER" /opt/planka
cd /opt/plankaأنشئ الأسرار في ملف .env بجانب ملف Compose. يقرأ Compose هذا الملف تلقائياً ويستبدل القيم.
umask 077
{
printf 'SECRET_KEY=%s\n' "$(openssl rand -hex 64)"
printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)"
printf 'ADMIN_PASSWORD=%s\n' "$(openssl rand -hex 12)"
} > .env
chmod 600 .envاستخدام openssl rand -hex مقصود. تحتوي السلسلة السداسية العشرية على أرقام فقط والحروف من a إلى f، لذلك لا يمكنها إفساد سلسلة اتصال DATABASE_URL التي تُلصق فيها. أمّا كلمة مرور base64 التي تحتوي على شرطة مائلة أو علامة at فتؤدي إلى خطأ اتصال يبدو كأنه اسم مضيف غير صحيح، وقد يكلّفك ذلك ساعة كاملة. يشرح إبقاء الأسرار خارج ملف Compose النمط الأوسع لذلك.
الآن docker-compose.yml. استبدل kanban.example.com باسم المضيف الخاص بك في الموضعين اللذين يظهر فيهما.
services:
planka:
image: ghcr.io/plankanban/planka:2.1.1
restart: unless-stopped
volumes:
- planka-data:/app/data
environment:
- BASE_URL=https://kanban.example.com
- DATABASE_URL=postgresql://planka:${POSTGRES_PASSWORD}@postgres/planka
- SECRET_KEY=${SECRET_KEY}
- TRUST_PROXY=true
- DEFAULT_ADMIN_EMAIL=you@example.com
- DEFAULT_ADMIN_PASSWORD=${ADMIN_PASSWORD}
- DEFAULT_ADMIN_NAME=Your Name
- DEFAULT_ADMIN_USERNAME=admin
networks:
- proxy
- internal
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.planka.rule=Host(`kanban.example.com`)"
- "traefik.http.routers.planka.entrypoints=websecure"
- "traefik.http.routers.planka.tls.certresolver=default"
- "traefik.http.services.planka.loadbalancer.server.port=1337"
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=planka
- POSTGRES_USER=planka
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
networks:
- internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U planka -d planka"]
interval: 10s
timeout: 5s
retries: 5
volumes:
planka-data:
db-data:
networks:
proxy:
external: true
internal:تستحق أربعة قرارات في هذا الملف التوضيح، لأنها القرارات التي يغيّرها المستخدمون ثم يندمون على ذلك.
- لا توجد كتلة
ports:في خدمة Planka. يصل Traefik إلى الحاوية عبر شبكةproxy، لذلك لا يُنشر المنفذ 1337 على المضيف. نشره يمنح أي شخص وسيلة لتجاوز الـproxy والشهادة. - يحدد
loadbalancer.server.port=1337اسم المنفذ داخل الحاوية. تستمع Planka على 1337، ولا يصل إليها المثال الأصلي إلا عبر 3000 لأنه يربط المنفذ بالمضيف. لا يوجد ربط بمنفذ المضيف هنا، لذلك يجب إبلاغ Traefik بمنفذ الحاوية. - يرتبط
condition: service_healthyبفحص سلامة Postgres. من دونه تبدأ Planka قبل أن تقبل قاعدة البيانات الاتصالات، وتفشل في أول استعلام لها ثم تخرج، فيبدو الأمر كأنه حلقة تعطل. ترد التفاصيل في فحوصات سلامة Compose وترتيب بدء التشغيل. - سُمّيت خدمة قاعدة البيانات
postgresعمداً. توجّه Planka 2 طلباتها الصادرة عبر مرشح داخلي، وقائمة الحظر الافتراضية لهذا المرشح هيlocalhost,postgres. إذا أعدت تسمية الخدمة، فستزيل قاعدة البيانات من تلك القائمة دون تنبيه واضح.
تحقق من أن Compose يستطيع قراءة أسرارك قبل بدء أي شيء:
docker compose config | grep -E 'image:|BASE_URL|POSTGRES_USER'يعرض ذلك الملف بعد استبدال قيم .env مسبقاً. تعني القيمة الفارغة أن Compose لا يقرأ ملف .env، ويحدث ذلك عادةً لأنك تنفّذ الأمر من دليل مختلف.
ما الذي تفعله متغيرات التمهيد الإداري فعلياً
منذ Planka 1.13، لا يُنشأ أي حساب إداري تلقائياً، لذلك لا يوجد في قاعدة البيانات الجديدة أي مستخدم يمكنه تسجيل الدخول. وتُعد مجموعة DEFAULT_ADMIN_* إحدى طريقتين لمعالجة ذلك.
عند بدء التشغيل، يبحث Planka عن مستخدم يطابق DEFAULT_ADMIN_EMAIL. إذا لم يعثر عليه، ينشئ مستخدماً باستخدام كلمة المرور واسم العرض واسم المستخدم المحددة إلى جانبه. يحدث ذلك عند أول تشغيل باستخدام قاعدة بيانات فارغة، لذلك تعمل هذه المتغيرات على تمهيد حساب، ولا تديره بعد ذلك.
تؤدي DEFAULT_ADMIN_EMAIL مهمة ثانية قد تفوت على بعض المستخدمين. ما دام المتغير مضبوطاً، لا يمكن لأي شخص تعديل الحساب الذي يشير إليه أو حذفه من الواجهة. وهذا إجراء لمنع فقدان الوصول، وهو سبب عدم إمكانية إعادة تسمية ذلك الحساب أو تغيير عنوان بريده الإلكتروني من الواجهة. أزل المتغير وأعد التشغيل، وسيصبح الحساب مسؤولاً عادياً يمكنك تعديله مثل أي حساب آخر.
يجب توخي الحذر مع سطر كلمة المرور. يمكن لأي شخص يستطيع تشغيل docker inspect على الحاوية قراءة أي قيمة ضمن environment:، لذلك لا ينبغي أن تبقى DEFAULT_ADMIN_PASSWORD هناك بشكل دائم. سجّل الدخول، وغيّر كلمة المرور من الواجهة، واحذف ذلك السطر، ثم شغّل docker compose up -d مرة أخرى.
المسار الأنظف يتجاوز المتغيرات بالكامل. علّق مجموعة DEFAULT_ADMIN_* بأكملها، ثم أنشئ الحساب بشكل تفاعلي:
docker compose run --rm planka npm run db:create-admin-userسيطلب منك إدخال البريد الإلكتروني وكلمة المرور واسم العرض واسم مستخدم اختياري، ثم يكتب المستخدم مباشرةً إلى قاعدة البيانات. لا تلامس كلمة المرور ملف Compose أو بيئة الحاوية. استخدم هذا المسار إذا كان أكثر من شخص يملك وصول shell إلى VPS. يبدأ الأمر بتشغيل Postgres أولاً بسبب depends_on، لذلك يعمل على مكدس لم يُشغّل من قبل.
يتركك كلا المسارين مسؤولاً عن إدارة كلمات مرور Planka يدوياً. وإذا كانت هذه رابع مجموعة من بيانات الاعتماد التي جمعها فريقك، فيمكن لـPlanka بدلاً من ذلك تفويض تسجيل الدخول إلى موفّر OIDC مثل Authentik الذي يعمل كخادم تسجيل دخول موحّد خاص بك، مع الاحتفاظ بالمسؤول الذي أُنشئ أثناء التمهيد كحساب للطوارئ لاستخدامه في اليوم الذي يتوقف فيه الموفّر عن العمل.
لماذا يؤدي عدم تطابق BASE_URL مع اسم المضيف إلى تعطّل تسجيل الدخول
BASE_URL هو العنوان الدقيق الذي يكتبه المستخدمون في المتصفح، مع المخطط ومن دون شرطة مائلة في النهاية. في هذه الحزمة، يكون العنوان هو https://kanban.example.com. ينشئ Planka روابطه واتصال WebSocket اعتماداً على هذه القيمة، لذلك لا يعرض BASE_URL غير الصحيح خطأً واضحاً. بل يعرض صفحة تُحمّل ثم لا يكتمل تحميلها أبداً.
السيناريو الشائع هو أن تنسخ المثال المقدم من المشروع upstream، وتترك BASE_URL=http://localhost:3000 كما هو، ثم تصل إلى الموقع عبر HTTPS باستخدام نطاقك الفعلي. يرسل نموذج تسجيل الدخول الطلب، وتُقبل بيانات اعتمادك. لكن اللوحة لا تظهر. افتح وحدة تحكم المطوّر في المتصفح، وسترى أن الطلبات إلى /socket.io/ تفشل، لأن العميل تلقى تعليمات بفتح اتصاله المباشر إلى localhost:3000، وهذا العنوان غير موجود أصلاً على حاسوبك المحمول.
TRUST_PROXY=true هو الجزء الآخر من المشكلة نفسها. يعمل Planka خلف Traefik، لذلك يصل كل طلب إليه من عنوان الـproxy عبر HTTP غير المشفّر داخل شبكة Docker. من دون TRUST_PROXY، يتجاهل التطبيق رأسي X-Forwarded-Proto وX-Forwarded-For اللذين يضبطهما Traefik، لذلك يعتقد أن الاتصال غير آمن، ويتعامل مع كل عميل على أنه يستخدم عنوان IP مشتركاً واحداً. عند ضبطه، يقرأ التطبيق هذه الرؤوس ويتفق مع المتصفح على المخطط المستخدم في الاتصال.
يوجّه Traefik اتصالات WebSocket من دون إعداد إضافي، وهذا أحد أسباب تفضيله في هذه الحالة. أما في nginx، فيحتاج socket.io إلى كتلة location خاصة تتضمن proxy_set_header Upgrade $http_upgrade وproxy_set_header Connection "upgrade"، وإلا فستحصل على مؤشر التحميل العالق نفسه، ولكن بسبب مختلف.
يعني نقل اللوحة إلى اسم مضيف جديد لاحقاً تغيير أمرين معاً: قيمة BASE_URL وقاعدة Host() في Traefik. إذا غيّرت أحدهما ونسيت الآخر، فستعود إلى ظهور مؤشر التحميل. يعمل تقديم Planka من مسار فرعي مثل https://example.com/planka بدءاً من الإصدار 2.1.0، الذي صدر في March 2026. أما في الوسوم الأقدم، فاستخدم نطاقاً فرعياً مخصصاً له.
مكان تخزين Planka للمرفقات والصور الرمزية
يخزّن Planka 2 كل ما يحمّله المستخدم ضمن مسار واحد داخل الحاوية: /app/data. توجد المرفقات والصور الرمزية للمستخدمين وصور خلفية اللوحات كلها ضمن هذا المسار. كان الإصدار 1 يستخدم ثلاثة مجلدات منفصلة، لذلك يربط ملف Compose المنسوخ من شرح أقدم مسارات لم تعد موجودة، ويظل دليل البيانات الفعلي من دون mount.
هذا الـmount هو ما يحدد ما إذا كانت اللوحة ستبقى سليمة بعد الترقية أو ستسبب مشكلة كبيرة. إذا لم يكن /app/data موجوداً على volume، فستُخزَّن التحميلات في طبقة الكتابة الخاصة بالحاوية. تُحذف هذه الطبقة عند إعادة إنشاء الحاوية، وتُعاد الحاوية إنشاؤها في كل مرة تغيّر فيها وسم image. ستظهر اللوحة مجدداً بحالة سليمة، وستبقى جميع البطاقات موجودة، لكن كل رابط مرفق سيكون معطلاً، لأن صفوف قاعدة البيانات ستظل تشير إلى ملفات لم تعد موجودة.
يمنع named volume الموجود في ملف Compose أعلاه حدوث ذلك. ويعمل bind mount أيضاً، كما يجعل نسخ الملفات احتياطياً باستخدام الأدوات المعتادة أسهل، لكنه يتطلب خطوة إضافية. تعمل عملية Node داخل الحاوية باستخدام UID 1000، لذلك يؤدي وجود دليل على المضيف مملوك للحساب root إلى ظهور خطأ صلاحيات عند أول تحميل:
sudo chown -R 1000:1000 /opt/planka/dataيشرح bind mounts مقارنةً بـnamed volumes المفاضلة بين الخيارين.
إذا تجاوزت المرفقات سعة القرص المتاحة في خطتك، يستطيع Planka كتابتها إلى مساحة تخزين متوافقة مع S3 بدلاً من ذلك، عبر S3_ENDPOINT وS3_BUCKET ومتغيرات المفاتيح المطابقة. ويمكن أن يشير ذلك إلى bucket مستضاف أو إلى مخزن كائنات MinIO مستضاف ذاتياً على خادم آخر. اتخذ هذا القرار قبل أن يملأ الفريق اللوحة، لأن الإعداد ينطبق على التحميلات الجديدة.
شغّل الحزمة وتحقق من نجاحها
docker compose pull
docker compose up -d
docker compose psيجب أن يعرض docker compose ps قيمة postgres على أنها healthy وقيمة planka على أنها running. إذا كان Planka يُعاد تشغيله في حلقة، فتحقق أولاً من اتصال قاعدة البيانات، وليس من التطبيق.
docker compose logs -f plankaتُجري عملية الإقلاع الأولى السليمة عمليات ترحيل قاعدة البيانات، ثم تعرض أن الخادم يستمع على المنفذ 1337. تحقّق من إنشاء المخطط فعلياً عبر الاستعلام المباشر من Postgres بدلاً من الاعتماد على السجل:
docker compose exec postgres psql -U planka -d planka -c '\dt'تعني قائمة الجداول التي تتضمن board وcard أن عمليات الترحيل نُفذت. وتعني الرسالة "Did not find any relations" أن Planka لم يتصل بقاعدة البيانات، لذا قارن DATABASE_URL بقيمتي POSTGRES_USER وPOSTGRES_PASSWORD في .env.
ثم تحقّق من المسار من جهازك أنت، وليس من VPS:
curl -I https://kanban.example.comتعني HTTP/2 200 أن Traefik يملك شهادة ويصل إلى الحاوية. وتشير استجابة 404 التي يقدّمها Traefik إلى أن تسميات الموجّه لم تتطابق، وغالباً ما يكون السبب أن الحاوية غير متصلة بشبكة proxy. افتح الموقع الآن وسجّل الدخول باستخدام حساب المسؤول.
نفّذ pg_dump قبل كل ترقية للإصدار
يحتفظ مخزنان منفصلان ببيانات لوحتك، لذلك يجب أن تشمل النسخة الاحتياطية كليهما: قاعدة بيانات Postgres ووحدة التخزين planka-data. نفّذ تفريغ قاعدة البيانات بينما تكون الحزمة قيد التشغيل.
docker compose exec -T postgres pg_dump -U planka -d planka > "planka-db-$(date +%F).sql"الخيار -T إلزامي. بدونه، يخصّص Compose طرفية زائفة، وتعيد طبقة الطرفية كتابة نهايات الأسطر في الدفق، فتحصل على ملف تفريغ يفشل في منتصف عملية الاستعادة. يظهر الفشل بعد أسابيع، وهذا أسوأ وقت ممكن لاكتشافه.
ثم انسخ الملفات المرفوعة. اعثر أولاً على اسم وحدة التخزين الفعلي، لأن Compose يضيف إليه اسم مجلد المشروع كبادئة.
docker volume ls | grep planka
docker run --rm -v planka_planka-data:/data -v "$PWD":/backup alpine \
tar czf /backup/planka-files-$(date +%F).tgz -C /data .يتضمن المشروع أيضاً docker-backup.sh وdocker-restore.sh في مستودعه، وتضعهما الوثائق الرسمية في مهمة cron ليلية. كلا الأسلوبين مناسب. لكن النسخة الاحتياطية التي لم تستعدها من قبل ليست مناسبة. لذلك استعد نسخة واحدة على VPS مؤقت مرة واحدة، وتأكد من إمكانية تسجيل الدخول وفتح مرفق. يظهر المخزنان نفسهما في كل تطبيق Compose يقبل الملفات المرفوعة. لذلك، إذا شغّلت لاحقاً Chatwoot على الخادم نفسه الذي يوجد عليه مكتب الدعم، فستنتقل الآلية التي تبنيها هنا مع تغييرات بسيطة تقتصر غالباً على أسماء وحدات التخزين.
نفّذ التفريغ مباشرة قبل كل تغيير في الإصدار. النسخة الاحتياطية من الليلة الماضية ليست النسخة الاحتياطية التي أُخذت قبل الترحيل الذي توشك على تشغيله.
ثبّت الوسوم واقرأ ملاحظات الإصدار
وسما الصورة في ذلك الملف مثبتان عن قصد.
ghcr.io/plankanban/planka:2.1.1 إصدار محدد، وهو الإصدار الحالي حتى August 2026. أما latest فيتغير كلما نشر المشروع المصدر إصداراً جديداً، لذلك قد تجلب عملية docker compose pull دورية ترحيل مخطط قاعدة البيانات في وقت لم تختره. اقرأ ملاحظات الإصدار قبل تغيير ذلك الرقم، لأن التغييرات غير المتوافقة وإصلاحات الأمان موضحة هناك. نُشر الإصدار 2.0.3 كإصدار أمني، وهذا تحديداً ما تريد قراءته بدلاً من تثبيته عرضاً. يسهل التثبيت هنا لأن المشروع المصدر ينشر الصور أصلاً، وعندما لا ينشر المشروع صوراً، يجب أن تلتزم بالانضباط نفسه مع خطوة إضافية، كما في openGym الذي بُني على الخادم من وسم git مسحوب.
ثُبّت postgres:16-alpine على إصدار رئيسي لسبب أكثر أهمية. يكتب Postgres دليل البيانات بتنسيق مرتبط بالإصدار الرئيسي، ويرفض الخادم فتح دليل كتبته نسخة رئيسية مختلفة. اكتب postgres:latest، ودع الوسم ينتقل إلى 17، ولن تبدأ الحاوية:
FATAL: database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.لن تضيع أي بيانات، ولن يحل إعادة التشغيل المشكلة. الانتقال إلى إصدار رئيسي جديد من Postgres يعني إنشاء dump من الإصدار القديم ثم استعادته إلى دليل بيانات جديد على الإصدار الجديد. هذه مهمة مخططة تُنفَّذ مع إيقاف المكدس، وليست أثراً جانبياً لسحب صورة.
إذا كنت تنقل تثبيتاً موجوداً من Planka 1.x بدلاً من البدء من الصفر، فللترقية إجراء موثق مستقل في وثائق المشروع، ولا توجد طريقة للعودة إلى الإصدار 1 من دون نسخة احتياطية أُخذت مسبقاً.
أوضاع الفشل والنصوص التي ستراها
يعيد Planka التشغيل في حلقة، ويذكر السجل قاعدة البيانات. بيانات الاعتماد في DATABASE_URL لا تطابق بيئة Postgres. لاحظ أن POSTGRES_PASSWORD يُطبَّق فقط عند تهيئة دليل البيانات للمرة الأولى، لذلك لا يغيّر إصلاح المتغير بعد إقلاع أول فاشل شيئاً. يجب حذف وحدة التخزين db-data والبدء من جديد.
ينجح تسجيل الدخول، لكن اللوحة لا تُحمَّل أبداً. لا يتطابق BASE_URL مع العنوان الظاهر في شريط المتصفح، أو أن TRUST_PROXY مفقود. تعرض وحدة تحكم المتصفح طلبات فاشلة إلى /socket.io/.
تفشل عمليات الرفع بينما يعمل كل شيء آخر. نقطة ربط مملوكة للمستخدم root. نفّذ sudo chown -R 1000:1000 على الدليل الموجود على المضيف، ثم أعد تشغيل الحاوية.
اختفت المرفقات بعد الترقية. لم يكن /app/data موجوداً على وحدة تخزين، لذلك بقيت الملفات في طبقة الحاوية التي استبدلتها الترقية. استعد الملفات من نسخة احتياطية، ثم أضف وحدة التخزين قبل تغيير وسم الصورة مرة أخرى.
يعرض Traefik الخطأ 404. الحاوية ليست على شبكة proxy، أو أن قاعدة Host() لا تطابق سجل DNS لديك. يعرض docker compose config التسميات بعد الاستبدال، وهنا تظهر الأخطاء المطبعية.
لا تصل الإشعارات أو webhooks أبداً. يرسل Planka 2 طلبات HTTP الصادرة عبر مرشح داخلي، وتشمل قائمة الحظر الافتراضية localhost وpostgres. قد يُحظر webhook موجّه إلى حاوية أخرى على المضيف نفسه عن قصد. عدّل OUTGOING_ALLOWED_HOSTS بدلاً من إزالة المرشح.
بعد تشغيله، يكون العبء التشغيلي صغيراً. راقب ملاحظات الإصدار، وأنشئ تفريغاً لقاعدة البيانات قبل كل ترقية. تعيد إعادة التشغيل تشغيل الحزمة تلقائياً بفضل restart: unless-stopped، ما دام Docker مفعّلاً عند الإقلاع، ويغطي حزم Compose التي تعود بعد إعادة التشغيل الحالات التي لا يحدث فيها ذلك.
FAQ
لماذا يستمر Planka في التحميل بعد تسجيل الدخول؟
قُبلت بيانات الاعتماد، لكن اتصال الوقت الفعلي لم يُنشأ. ينشئ Planka عنوان WebSocket من BASE_URL، لذلك إذا كان هذا المتغير لا يزال يساوي http://localhost:3000 بينما تصل إلى الموقع عبر https://kanban.example.com، يحاول المتصفح فتح مقبس إلى عنوان غير موجود على جهازك. تعرض وحدة تحكم المطور طلبات فاشلة إلى /socket.io/. اضبط BASE_URL على العنوان العام الدقيق من دون شرطة مائلة في النهاية، وأضف TRUST_PROXY=true لكي يراعي التطبيق ترويسة X-Forwarded-Proto التي يرسلها الـreverse proxy، ثم شغّل docker compose up -d.
كيف أنشئ مستخدم Planka الإداري الأول؟
منذ الإصدار 1.13، لا يُنشأ أي مسؤول تلقائياً. إمّا أن تضبط DEFAULT_ADMIN_EMAIL مع متغيرات كلمة المرور والاسم واسم المستخدم المطابقة له ثم تبدأ الـstack، أو تشغّل docker compose run --rm planka npm run db:create-admin-user وتجيب عن المطالبات. يُعد الأمر التفاعلي أكثر أماناً على خادم مشترك، لأن كلمة المرور لا تدخل إلى بيئة الحاوية حيث يمكن لـdocker inspect قراءتها. ويؤدي إبقاء DEFAULT_ADMIN_EMAIL مضبوطاً بعد ذلك إلى منع تعديل ذلك الحساب وحذفه من الواجهة.
أين يخزّن Planka المرفقات والصور الرمزية؟
توجد جميع الملفات المرفوعة ضمن /app/data داخل الحاوية في Planka 2، بما في ذلك المرفقات والصور الرمزية للمستخدمين وخلفيات اللوحات. اربط هذا المسار بوحدة تخزين مسماة. إذا لم يكن المسار مربوطاً، فتبقى الملفات في طبقة الكتابة الخاصة بالحاوية وتُحذف في المرة التالية التي يُعاد فيها إنشاء الحاوية، ويحدث ذلك مع كل ترقية للصورة. يعمل bind mount أيضاً، لكن عملية Node تعمل بالمعرّف UID 1000، لذلك شغّل sudo chown -R 1000:1000 على دليل المضيف، وإلا تفشل عمليات الرفع بسبب خطأ في الصلاحيات.
ما مقدار RAM الذي يحتاج إليه Planka المستضاف ذاتياً؟
لا ينشر المشروع حداً أدنى لمواصفات العتاد. إن رقم 2 vCPU و4 GB المتكرر في صفحات الاستضافة هو قيمة افتراضية لدى موفر الخدمة، وليس نتيجة قياس، وهو سخي بالنسبة إلى لوحة صغيرة. تتكون أعباء العمل كاملةً من عملية Node واحدة وعملية Postgres واحدة، لذلك تكفي خطة بمواصفات 1 vCPU و2 GB لفريق يتكون من شخصين إلى خمسة أشخاص. شغّل docker stats --no-stream بعد أسبوع عادي، وحدد الحجم استناداً إلى أرقامك الفعلية. راقب القرص باهتمام أكبر من الذاكرة، لأن المرفقات هي التي تنمو.
كيف أرقي Planka من دون فقدان البيانات؟
أنشئ نسخة تفريغ من قاعدة البيانات وأرشف وحدة تخزين الرفع مباشرةً قبل الترقية، وليس وفق جدولة الليلة السابقة. استخدم docker compose exec -T postgres pg_dump -U planka -d planka > planka-db.sql، مع الإبقاء على -T حتى لا تؤدي المحطة الطرفية الوهمية إلى إفساد المخرجات المعاد توجيهها. اقرأ ملاحظات الإصدار لكل إصدار تتجاوزه، وغيّر وسم الصورة إلى إصدار محدد بدلاً من latest، ثم شغّل docker compose pull وdocker compose up -d وراقب السجل بحثاً عن عملية الترحيل. أبقِ وسم Postgres مثبتاً على إصداره الرئيسي، لأن الخادم يرفض فتح دليل بيانات كُتب بواسطة إصدار رئيسي مختلف.