> ## 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.

# تثبيت Mattermost Team Edition مع PostgreSQL وترقيته بأمان
- URL: https://arabroot.io/articles/تثبيت-mattermost-وترقيته/
- Published: 2026-09-18T15:15:00.000Z
- Updated: 2026-10-05T06:20:43.000Z
- Description: مساحة محادثة لفريقك تبقى رسائلها وملفاتها كاملة على سيرفرك، فلا تحذفها خطة مجانية ولا يخفيها حد للرسائل. نثبت Mattermost Team Edition مع PostgreSQL، ونجهز الفريق الأول والبريد، ثم نشرح النسخ الاحتياطي والتحديث دون أن تفقد بياناتك.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, تطبيقات لفريقك, الاستضافة الذاتية, Mattermost

لنفرض أن نقاشات فريقك وقراراته والملفات التي يتبادلها موجودة اليوم على Slack أو Microsoft Teams، فسوف تجد أن هذا مريح جداً إلى أن تتغير الأسعار أو شروط الخطة المجانية Free Plan، أو تطلب منك سياسة مؤسستك أن تبقى المحادثات داخلها، وعندها تكتشف أن تاريخ فريقك كله محفوظ على سيرفر Server لا تملكه ولا تتحكم في مدة الاحتفاظ بما عليه.

📌

في 26 أغسطس 2024 بدأت Slack [بحذف الرسائل والملفات التي مضى عليها أكثر من سنة](https://slack.com/help/articles/115002422943-Usage-limits-for-free-workspaces?ref=arabroot.io) من مساحات العمل Workspaces على الخطة المجانية، بعد أن كانت هذه الخطة تحصر البحث والعرض في آخر 90 يوماً فقط، فالفريق الذي اعتمد على الخطة المجانية لسنوات وجد أن نقاشاته القديمة وقراراته لم تعد مخفية فقط، وإنما أصبحت تحذف تباعاً. والدرس أن من يملك السيرفر هو الذي يقرر كم تبقى رسائلك، وليس أنت.

والحل الأول الذي يخطر على البال هو أن تبقى على الخدمة السحابية Cloud وتدفع الاشتراك، وهذا يعيد إليك التاريخ القديم ولكنه لا يغير الأصل، فالبيانات تبقى عند جهة أخرى والسعر يحدده غيرك. والحل الثاني هو أن تأخذ [المستودع الرسمي mattermost/docker](https://github.com/mattermost/docker?ref=arabroot.io) وتشغله كما هو، والمشكلة هنا أن هذا المستودع يستخدم افتراضياً الـ Docker Image الخاصة بـ Enterprise Edition، وهذه الـ Image عندما تعمل دون ترخيص License تتحول إلى خطة مجانية اسمها [Mattermost Entry](https://docs.mattermost.com/product-overview/editions-and-offerings?ref=arabroot.io)، وفيها ميزات أكثر ولكن مع حد قدره 10,000 رسالة على مستوى السيرفر كله، وما زاد عن ذلك يبقى في قاعدة البيانات Database ولكنه لا يظهر في القنوات ولا في البحث، والتوثيق نفسه يذكر أنها تناسب الفرق التي يقل عددها عن 50 مستخدماً.

لذلك فالحل الأنسب لفريق صغير أو متوسط يريد أن يبقى تاريخه كاملاً هو [**Mattermost**](https://mattermost.com/?ref=arabroot.io) بنسخة [**Team Edition**](https://docs.mattermost.com/product-overview/editions-and-offerings?ref=arabroot.io)، وهو منصة محادثة Chat مفتوحة المصدر Open Source تعمل بطريقة قريبة من Slack، ففيها الفرق Teams والقنوات Channels العامة Public والخاصة Private، والرسائل المباشرة Direct Messages وسلاسل الردود Threads والبحث Search في الرسائل، ولها تطبيقات لسطح المكتب Desktop والجوال Mobile، وتكاملات Integrations عبر الـ Webhooks والـ Slash Commands والـ Bots. ونسخة Team Edition مجانية ومرخصة بترخيص MIT، ولا يوجد فيها حد لعدد الرسائل، والرسائل والملفات كلها تبقى على سيرفرك.

وقد يتساءل البعض: لماذا لا أختار Entry ما دامت مجانية وفيها ميزات أكثر؟ والإجابة أن الأمر يتوقف على ما يحتاجه فريقك، فإذا كنت تحتاج تسجيل الدخول الموحد SSO عبر LDAP أو SAML أو حتى GitLab، أو حسابات الضيوف Guest Accounts، فهذه غير موجودة في Team Edition، حيث [أزالت Mattermost تسجيل الدخول عبر GitLab منها في الإصدار 11.0](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes?ref=arabroot.io)، وتوقفت فيها Playbooks أيضاً، والتوثيق يحددها لفرق يقل عدد مستخدميها المفعلين Activated Users عن 250 ولا تحتاج SSO. وأما إذا كان المهم عندك أن يبقى تاريخ المحادثات كاملاً ويمكن البحث فيه، فـ Team Edition هي الخيار الصحيح، وهي التي سوف نستخدمها في هذا الدليل. ومتطلبات الامتثال Compliance المتقدمة، مثل eDiscovery وسياسات الاحتفاظ بالرسائل Message Retention، موجودة في الخطط المدفوعة Paid Plans فقط.

وسوف نناقش في هذا المقال ما يلي:

- تثبيت Mattermost Team Edition باستخدام Docker Compose مع PostgreSQL، وشرح الأسطر المهمة في الملف.
- ربط النطاق Domain مع شهادة TLS عبر الـ Reverse Proxy، وإنشاء أول مدير وأول فريق.
- أهم إعدادات System Console: العنوان Site URL والبريد SMTP وتخزين الملفات File Storage والتسجيل Signup.
- إرسال تنبيهات من أنظمتك عبر Incoming Webhook، ثم النسخ الاحتياطي Backup والاستعادة Restore.
- الفرق بين إصدارات الدعم الممتد ESR والإصدارات الشهرية، والتحديث Upgrade بأمان، وأشهر المشكلات وحلولها.

## ما تحتاجه قبل أن تبدأ Requirements

- سيرفر Linux، و[متطلبات العتاد Hardware الرسمية](https://docs.mattermost.com/deployment-guide/software-hardware-requirements?ref=arabroot.io) تذكر أن سيرفراً واحداً بمعالج 1 vCPU وذاكرة RAM بحجم 2 GB يكفي حتى 1,000 مستخدم مسجل، ومعالجين 2 vCPU و4 GB من 1,000 إلى 2,000 مستخدم، ولأن PostgreSQL سوف تعمل على نفس السيرفر فاجعل الذاكرة 4 GB إذا استطعت. وأما المساحة Storage فتكفي 10 GB للبداية، وتزيد الحاجة مع الملفات المرفقة Attachments.
- Docker Engine مع Compose v2، وإذا لم يكن مثبتاً فاتبع [دليل تثبيت Docker](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-docker-%D8%B9%D9%84%D9%89-ubuntu/).
- نطاق فرعي Subdomain مثل `chat.example.com` يشير إلى السيرفر، وReverse Proxy يصدر شهادة TLS Certificate ويدعم WebSocket، مثل [Nginx Proxy Manager](https://arabroot.io/articles/nginx-proxy-manager-%D9%86%D8%B7%D8%A7%D9%82%D8%A7%D8%AA-%D9%88%D8%B4%D9%87%D8%A7%D8%AF%D8%A7%D8%AA-tls/).
- حساب SMTP للإشعارات Notifications ودعوات Invitations المستخدمين واستعادة كلمات المرور Password Reset.
- المنفذ Port رقم `8443` (UDP وTCP)، وتحتاجه فقط للمكالمات الصوتية والمرئية Voice and Video Calls عبر إضافة Plugin اسمها [Calls](https://docs.mattermost.com/deployment-guide/calls/calls-deployment-guide?ref=arabroot.io)، ولاحظ أن Team Edition تسمح بمكالمات ثنائية 1:1 ومشاركة الشاشة Screen Sharing لمدة أقصاها 40 دقيقة، وأما المكالمات الجماعية Group Calls فهي في الخطط المدفوعة.

## تثبيت Mattermost خطوة بخطوة Installation

### مجلد التثبيت وملف .env

أول خطوة هي أن ننشئ مجلداً للتثبيت:

```bash
sudo mkdir -p /opt/mattermost
cd /opt/mattermost
```

ثم نضع فيه ملف `.env` يحمل رقم الإصدار Version وكلمة مرور قاعدة البيانات، والسبب أننا لا نريد أن نكتب كلمة المرور داخل ملف Compose نفسه فتظهر في كل نسخة منه، ولذلك نولدها عشوائياً ونجعل الملف مقروءاً للمالك فقط:

```bash
cat > .env <<EOF
MM_TAG=11.11.1
POSTGRES_PASSWORD=$(openssl rand -hex 24)
EOF
chmod 600 .env
```

والإصدار [11.11.1](https://github.com/mattermost/mattermost/releases/tag/v11.11.1?ref=arabroot.io) هو أحدث إصدار مستقر Stable Release حتى كتابة هذا الدليل، وهو من الإصدارات الشهرية Feature Releases، وأما إذا كنت تفضل أن تحدث السيرفر مرات أقل فاختر إصدار الدعم الممتد ESR، والتفصيل في قسم التحديث أدناه.

### ملف docker-compose.yml وشرح ما فيه

هذا الملف مبني على [المستودع الرسمي mattermost/docker](https://github.com/mattermost/docker?ref=arabroot.io) مع بعض التعديلات التي سوف نشرحها بعد الملف، وتجد طريقة التثبيت الرسمية في [دليل التثبيت عبر Containers](https://docs.mattermost.com/deployment-guide/server/deploy-containers?ref=arabroot.io). والملف سوف يكون كما يلي:

```yaml
services:
  postgres:
    image: postgres:18.6-alpine
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    environment:
      POSTGRES_USER: mmuser
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?}
      POSTGRES_DB: mattermost
      TZ: UTC
    volumes:
      # PostgreSQL 18 يحفظ بياناته تحت /var/lib/postgresql/18/docker
      - db:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mmuser -d mattermost"]
      interval: 10s
      timeout: 5s
      retries: 10

  mattermost:
    image: mattermost/mattermost-team-edition:${MM_TAG}
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      TZ: UTC
      MM_SQLSETTINGS_DRIVERNAME: postgres
      MM_SQLSETTINGS_DATASOURCE: postgres://mmuser:${POSTGRES_PASSWORD}@postgres:5432/mattermost?sslmode=disable&connect_timeout=10
      MM_SERVICESETTINGS_SITEURL: https://chat.example.com
      # يسمح بـ mmctl --local من داخل الـ Container (ويستخدمه الـ Healthcheck المدمج في الـ Image)
      MM_SERVICESETTINGS_ENABLELOCALMODE: "true"
    ports:
      - "127.0.0.1:8065:8065"
      # للمكالمات فقط (إضافة Calls)
      # - "8443:8443/udp"
      # - "8443:8443/tcp"
    volumes:
      - config:/mattermost/config
      - data:/mattermost/data
      - logs:/mattermost/logs
      - plugins:/mattermost/plugins
      - client-plugins:/mattermost/client/plugins
    networks:
      - default
      - proxy

volumes:
  db:
  config:
  data:
  logs:
  plugins:
  client-plugins:

networks:
  proxy:
    external: true
```

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

- الـ Image هي `mattermost/mattermost-team-edition` وليست `mattermost-enterprise-edition` التي يستخدمها المستودع الرسمي افتراضياً، والسبب هو حد الرسائل في Entry الذي شرحناه في البداية.
- استخدمنا Volumes مسماة Named Volumes بدل المجلدات المربوطة Bind Mounts، والسبب أن Mattermost يعمل داخل الـ Container بالمستخدم UID 2000، والمستودع الرسمي يطلب منك لذلك أن تنفذ `chown -R 2000:2000` على المجلدات قبل التشغيل، أما الـ Volume الجديد فيأخذ ملكية المجلد الموجود داخل الـ Image تلقائياً، فلا تحتاج إلى هذه الخطوة.
- حذفنا الـ Volume الخاص بـ `bleve-indexes` والمتغير `MM_BLEVESETTINGS_INDEXDIR` الموجودين في المستودع الرسمي، والسبب أن Mattermost [أزال البحث عبر Bleve في الإصدار 11.0](https://docs.mattermost.com/administration-guide/upgrade/upgrading-mattermost-server?ref=arabroot.io)، وأصبح البحث يعمل من قاعدة البيانات مباشرة.
- منفذ الويب مربوط بالعنوان `127.0.0.1` فقط، والسبب أن الـ Reverse Proxy وحده هو الذي يصل إليه عبر الشبكة `proxy`، فلا يستطيع أحد أن يتجاوز شهادة TLS ويفتح Mattermost مباشرة على المنفذ 8065.
- الصيغة `${POSTGRES_PASSWORD:?}` تجعل Compose يتوقف برسالة خطأ إذا لم يجد المتغير في ملف `.env`، بدل أن يشغل قاعدة البيانات بكلمة مرور فارغة، والشرط `service_healthy` يجعل Mattermost ينتظر حتى تصبح PostgreSQL جاهزة فعلاً.
- الـ Image الخاصة بـ PostgreSQL 18 تحفظ بياناتها تحت `/var/lib/postgresql` وليس `/var/lib/postgresql/data` كما في الإصدارات السابقة، ولذلك ربطنا الـ Volume بهذا المسار، والإصدار 18 مدعوم لأن [الحد الأدنى في Mattermost](https://docs.mattermost.com/deployment-guide/software-hardware-requirements?ref=arabroot.io) هو PostgreSQL 14، ويصبح 15 بدءاً من الإصدار 12.0.

وكل إعداد في System Console تستطيع تثبيته بمتغير بيئة Environment Variable بحروف كبيرة على الصيغة `MM_<SECTION>_<SETTING>`، مثل `MM_SERVICESETTINGS_SITEURL`، كما في [صفحة إعدادات التهيئة Configuration Settings](https://docs.mattermost.com/administration-guide/configure/configuration-settings?ref=arabroot.io)، وعندها يظهر الإعداد في الواجهة Web UI مقفلاً Locked، وبجانبه العبارة «This setting has been set through an environment variable»، لذلك استخدم هذه الطريقة للقيم التي لا تريد أن يغيرها أحد من الواجهة.

ويجدر الإشارة هنا إلى أن التوثيق الرسمي يصنف التثبيت عبر Docker للتجربة والتطوير، والسبب أنه لا يدعم التشغيل على عدة سيرفرات Cluster ولا التوافرية العالية High Availability، ويوصي بـ Kubernetes لمن يحتاجها. وهذا لا يمنعك من تشغيله لفريقك على سيرفر واحد، ولكن تذكر أن أي تحديث أو عطل في السيرفر يعني توقف المحادثات لدقائق.

### تشغيل الخدمات Services

الآن سوف نقوم بإنشاء الشبكة المشتركة مع الـ Reverse Proxy، ثم تشغيل الخدمتين ومتابعة السجلات Logs:

```bash
docker network create proxy
docker compose up -d
docker compose logs -f mattermost
```

وإذا كانت الشبكة موجودة من قبل فسوف يفشل الأمر الأول برسالة أنها موجودة، وهذا لا يضر بشيء. وفي الـ Image فحص صحة Healthcheck مدمج يعتمد على الأمر `mmctl system status --local`، لذلك انتظر حتى يظهر الـ Container بالحالة `healthy` في مخرجات Output الأمر `docker compose ps`، ثم تحقق بهذا الأمر:

```bash
curl -s http://127.0.0.1:8065/api/v4/system/ping
```

والمخرج سوف يكون رداً Response فيه `"status":"OK"`.

## ربط النطاق Domain وشهادة TLS عبر الـ Reverse Proxy

في Nginx Proxy Manager أضف مضيفاً Proxy Host للنطاق `chat.example.com` يوجه الطلبات Requests إلى الـ Container الخاص بـ mattermost على المنفذ `8065`، وفعل **Websockets Support**، والسبب أن الرسائل الفورية Real-time Messages تمر عبر WebSocket، فإذا لم تفعله فلن تظهر الرسائل إلا بعد تحديث الصفحة. ثم اطلب شهادة Let's Encrypt مع Force SSL، وقم بزيادة حد الرفع Upload Limit في الإعدادات المتقدمة Advanced ليطابق حد الملفات في Mattermost، وهو 100 MB افتراضياً (راجع [توثيق client\_max\_body\_size](https://nginx.org/en/docs/http/ngx%5Fhttp%5Fcore%5Fmodule.html?ref=arabroot.io#client%5Fmax%5Fbody%5Fsize) و[دليل إعداد NGINX لـ Mattermost](https://docs.mattermost.com/deployment-guide/server/setup-nginx-proxy?ref=arabroot.io)):

```nginx
client_max_body_size 100m;
proxy_read_timeout 600s;
```

وإذا كنت تستخدم Caddy فيكفي هذا:

```nginx
chat.example.com {
    reverse_proxy mattermost-mattermost-1:8065
}
```

والسبب أن التوجيه Directive [reverse\_proxy](https://caddyserver.com/docs/caddyfile/directives/reverse%5Fproxy?ref=arabroot.io) في Caddy يمرر اتصالات WebSocket تلقائياً. وفي الحالتين تأكد أن قيمة `MM_SERVICESETTINGS_SITEURL` تطابق العنوان العام Public URL تماماً، وإلا فسوف تتعطل الروابط في الإشعارات ويفشل تسجيل الدخول Login من التطبيقات.

## إنشاء أول مدير Admin وأول فريق

افتح `https://chat.example.com/` واختر **View in Browser**، وتذكر أن **أول حساب تنشئه يصبح مدير النظام System Admin**، لذلك أنشئه فور التشغيل وقبل أن تنشر الرابط لأي أحد.

![صفحة Create your account في Mattermost Team Edition مع البريد واسم المستخدم mmadmin](https://arabroot.io/content/images/2026/09/mattermost-01-create-first-admin.webp)

إنشاء الحساب الأول، وهو مدير النظام تلقائياً

بعد ذلك يطلب منك المعالج Wizard اسم المؤسسة، وينشئ به أول فريق Team مع قناتيه الافتراضيتين Town Square وOff-Topic، ثم يعرض عليك تكاملات اختيارية مثل GitHub وGitLab وJira وتستطيع تخطيها.

![شاشة What's the name of your organization في معالج Mattermost مع اسم Example Engineering](https://arabroot.io/content/images/2026/09/mattermost-02-organization-name.webp)

يصبح اسم المؤسسة اسماً لأول فريق

## أهم الإعدادات في System Console

افتح **System Console** من قائمة المنتجات Product Menu، وهي أيقونة المربعات في أعلى اليسار، وفيما يلي أهم الإعدادات بعد التثبيت.

### العنوان العام Site URL

هذا الإعداد في [**Environment ← Web Server**](https://docs.mattermost.com/administration-guide/configure/environment-configuration-settings?ref=arabroot.io)، وسوف تجده مقفلاً لأننا ضبطناه بمتغير بيئة، فاضغط **Test Live URL** لتتأكد أن العنوان يعمل.

![صفحة Web Server في System Console مع Site URL مقفلاً لأنه مضبوط بمتغير بيئة](https://arabroot.io/content/images/2026/09/mattermost-03-system-console-site-url.webp)

Site URL مضبوط بمتغير البيئة (العنوان في الصورة محلي)

### إعداد البريد SMTP

في **Environment ← SMTP** أدخل عنوان سيرفر البريد والمنفذ، وفعل **Enable SMTP Authentication** مع اسم المستخدم Username وكلمة المرور، ثم اختر **Connection Security**: إما `STARTTLS` على المنفذ 587 أو `TLS` على المنفذ 465\. واحفظ الإعدادات قبل أن تضغط على **Test Connection**، والسبب أن الاختبار يستخدم الإعدادات المحفوظة وليس ما كتبته في الحقول.

![صفحة SMTP في System Console مع الخادم والمنفذ ورسالة نجاح اختبار الاتصال](https://arabroot.io/content/images/2026/09/mattermost-04-smtp-test-connection.webp)

نجاح اختبار SMTP

بعد ذلك فعل الإشعارات من [**Site Configuration ← Notifications**](https://docs.mattermost.com/administration-guide/configure/site-configuration-settings?ref=arabroot.io)، حيث تجعل **Enable Email Notifications** \= true، وتضبط **Notification From Address** (مثل `chat@example.com`) واسم المرسل. وتستطيع أيضاً تثبيت إعدادات البريد بمتغيرات البيئة كما يلي:

```yaml
      MM_EMAILSETTINGS_SMTPSERVER: smtp.example.com
      MM_EMAILSETTINGS_SMTPPORT: "587"
      MM_EMAILSETTINGS_ENABLESMTPAUTH: "true"
      MM_EMAILSETTINGS_SMTPUSERNAME: chat@example.com
      MM_EMAILSETTINGS_SMTPPASSWORD: ${SMTP_PASSWORD}
      MM_EMAILSETTINGS_CONNECTIONSECURITY: STARTTLS
      MM_EMAILSETTINGS_SENDEMAILNOTIFICATIONS: "true"
      MM_EMAILSETTINGS_FEEDBACKEMAIL: chat@example.com
```

ونجاح الاختبار يعني أن Mattermost وصل إلى سيرفر البريد، وأما وصول الرسائل إلى صناديق البريد الحقيقية دون أن تذهب إلى الرسائل المزعجة Spam فيتوقف على مزود البريد Email Provider وعلى سجلات Records من نوع SPF وDKIM في النطاق كما شرحنا في [شرح SPF وDKIM وDMARC للمبتدئين](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-spf-%D9%88-dkim-%D9%88-dmarc-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)، لذلك أرسل دعوة إلى بريد تجريبي وتأكد أنها وصلت.

### تخزين الملفات File Storage

الخيار الافتراضي في **Environment ← File Storage** هو **Local File System** في المسار `./data/`، أي في الـ Volume المسمى `data`، وهو مناسب لسيرفر واحد. وإذا قمت بتعديل **Maximum File Size** فعدل حد الـ Reverse Proxy معه، وإلا فسوف يرفض الـ Reverse Proxy الملف قبل أن يصل إلى Mattermost.

وإذا كان لديك تخزين متوافق مع S3 (S3-compatible)، مثل MinIO أو خدمة سحابية، فاختر **Amazon S3** وأدخل الـ bucket والمفاتيح Access Keys والـ endpoint، وعندها يصبح الـ bucket هو ما تنسخه احتياطياً بدل الـ Volume المسمى `data`.

![صفحة File Storage في System Console مع Local File System ومجلد ./data/ والحد الأقصى 100 ميغابايت](https://arabroot.io/content/images/2026/09/mattermost-05-file-storage.webp)

التخزين المحلي للملفات والحد الأقصى لحجم المرفق

### التسجيل Signup ودعوة الزملاء

في [**Authentication ← Signup**](https://docs.mattermost.com/administration-guide/configure/authentication-configuration-settings?ref=arabroot.io) اترك **Enable Open Server** معطلاً كما هو افتراضياً، والسبب أن تفعيله يسمح لأي شخص يصل إلى الرابط بإنشاء حساب، وقيد **Restrict new system and team members to specified email domains** بنطاق مؤسستك، ثم ادع زملاءك من قائمة الفريق ← **Invite People**.

## إرسال رسائل من أنظمتك عبر Incoming Webhooks

[الـ Incoming Webhook](https://developers.mattermost.com/integrate/webhooks/incoming/?ref=arabroot.io) هو أبسط أنواع التكامل، وهو عنوان سري Secret URL يستقبل بيانات JSON وينشرها رسالة في قناة، وبالتالي فهو مناسب لتنبيهات Alerts الـ CI/CD والمراقبة Monitoring والنسخ الاحتياطي. تأكد أولاً أن [**Integrations ← Integration Management ← Enable Incoming Webhooks**](https://docs.mattermost.com/administration-guide/configure/integrations-configuration-settings?ref=arabroot.io) مفعل، وهو مفعل افتراضياً، ثم افتح من قائمة الفريق **Integrations ← Incoming Webhooks ← Add Incoming Webhook**:

![نموذج إضافة Incoming Webhook بعنوان CI notifications وقناة Town Square](https://arabroot.io/content/images/2026/09/mattermost-06-incoming-webhook.webp)

إنشاء webhook وارد وربطه بقناة

فعل **Lock to this channel**، والسبب أن الـ Webhook دون هذا الخيار يستطيع النشر في أي قناة يكون منشئه عضواً فيها إذا أرسل الحقل `channel`. وبعد الحفظ تحصل على عنوان مثل `https://chat.example.com/hooks/xxxxxxxxxxxxxxxxxxxxxxxxxx`، فاحمه كما تحمي كلمة المرور، لأن كل من يعرفه يستطيع النشر في قناتك. الآن سوف نرسل رسالة، والنص يدعم Markdown والجداول Tables:

```bash
curl -s -X POST -H 'Content-Type: application/json' \
  -d '{"text":"#### :white_check_mark: Build succeeded\n| Repository | Branch | Commit |\n|:--|:--|:--|\n| gitadmin/demo-app | main | 59d070b9 |\n[Open the run](https://git.example.com/gitadmin/demo-app/actions/runs/2)"}' \
  https://chat.example.com/hooks/xxxxxxxxxxxxxxxxxxxxxxxxxx
```

والمخرج سوف يكون كلمة `ok` مع رمز الحالة Status Code رقم 200، والرسالة تظهر في القناة كما يلي:

![رسالة Build succeeded مع جدول المستودع والفرع والـ commit في قناة Town Square](https://arabroot.io/content/images/2026/09/mattermost-07-webhook-message.webp)

الرسالة كما وصلت عبر الـ webhook

ولاحظ أن Mattermost يتجاهل الحقلين `username` و`icon_url` في الـ JSON إلا إذا فعلت **Enable integrations to override usernames** و**profile picture icons** في Integration Management، ولذلك تظهر الرسالة باسم منشئ الـ Webhook مع شارة Badge مكتوب فيها BOT.

وفي [Gitea Actions](https://docs.gitea.com/usage/actions/overview?ref=arabroot.io) (راجع [دليل Gitea Actions](https://arabroot.io/articles/gitea-actions-%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-ci-cd-%D8%B9%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%85%D9%83/)) احفظ الرابط في سر Secret، واستدعه في الخطوة Step الأخيرة مع `if: always()` حتى يصلك التنبيه سواءً نجح البناء أو فشل.

## كيف تتأكد أن كل شيء يعمل Verification

- الأمر `docker compose ps` يعرض الـ Containers الاثنين بالحالة `healthy`.
- الأمر `curl -s https://chat.example.com/api/v4/system/ping` يعيد `"status":"OK"`.
- الرسائل تصل فوراً بين متصفحين Browsers دون تحديث الصفحة، وهذا يعني أن اتصال WebSocket يمر عبر الـ Reverse Proxy.
- رفع ملف بحجم 20 MB في قناة ينجح.
- Test Connection في إعدادات SMTP ينجح، ورسالة الدعوة تصل إلى بريد تجريبي.
- الإصدار المتوقع يظهر في قائمة المنتجات ← **About Mattermost**.

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

النسخة الكاملة تتكون من قاعدة البيانات، ففيها الرسائل والمستخدمون والقنوات، ومن الـ Volume المسمى `data` وفيه الملفات المرفقة، و`config` وفيه الملف `config.json` بكل ما ضبطته من الواجهة، و`plugins` وفيه الإضافات التي ثبتها من الـ Marketplace، ومعها الملفان `.env` و`docker-compose.yml`. ولاحظ أن أسماء الـ Volumes على القرص Disk تبدأ باسم المشروع Project Name، مثل `mattermost_data`، والأوامر كما يلي:

```bash
cd /opt/mattermost
mkdir -p backups
docker compose exec -T postgres pg_dump -U mmuser -d mattermost -Fc > backups/mattermost-db-$(date +%F).dump
docker run --rm \
  -v mattermost_config:/v/config:ro \
  -v mattermost_data:/v/data:ro \
  -v mattermost_plugins:/v/plugins:ro \
  -v "$PWD/backups:/backup" \
  alpine:3 tar czf /backup/mattermost-files-$(date +%F).tar.gz -C /v config data plugins
```

ولا تحتاج إلى إيقاف Mattermost أثناء النسخ، ولكن الملفات التي ترفع في تلك اللحظة قد لا تدخل النسخة، لذلك اجعل النسخ في الليل. وفي تثبيت جديد يكون ملف [pg\_dump](https://www.postgresql.org/docs/18/app-pgdump.html?ref=arabroot.io) بحجم 200 KB تقريباً، وأرشيف Archive الملفات بحجم 86 MB تقريباً، ومعظمها للإضافات المدمجة، ثم انقل النسختين خارج السيرفر، لأن النسخة التي تبقى على نفس القرص تضيع معه.

**الاستعادة** تكون كما يلي:

```bash
cd /opt/mattermost
docker compose up -d postgres
docker compose exec -T postgres pg_restore -U mmuser -d mattermost --clean --if-exists --no-owner < backups/mattermost-db-2026-09-26.dump
docker run --rm \
  -v mattermost_config:/v/config \
  -v mattermost_data:/v/data \
  -v mattermost_plugins:/v/plugins \
  -v "$PWD/backups:/backup" \
  alpine:3 sh -c 'tar xzf /backup/mattermost-files-2026-09-26.tar.gz -C /v && chown -R 2000:2000 /v'
docker compose up -d
```

في الأوامر أعلاه لاحظ التالي:

- نستعيد قاعدة البيانات بالأداة [pg\_restore](https://www.postgresql.org/docs/18/app-pgrestore.html?ref=arabroot.io) قبل تشغيل Mattermost، والخياران `--clean --if-exists` يحذفان الجداول الموجودة قبل إنشائها من النسخة.
- نعيد ضبط المالك إلى `2000:2000` بعد فك الأرشيف، والسبب أن Mattermost يعمل داخل الـ Container بالمستخدم UID 2000، فإذا بقيت الملفات باسم root فسوف يتوقف بخطأ صلاحيات Permissions.
- الاستعادة تكون على نفس إصدار Mattermost الذي أخذت منه النسخة، ثم تحدث بعدها إذا أردت.

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

### تحديث Mattermost

تصدر Mattermost [نوعين من الإصدارات](https://docs.mattermost.com/product-overview/mattermost-server-releases?ref=arabroot.io): إصدار شهري Feature Release يدعم لمدة ثلاثة أشهر تقريباً، فالإصدار 11.11 مثلاً صدر في سبتمبر 2026 وينتهي دعمه في 15 ديسمبر 2026، وإصدار الدعم الممتد Extended Support Release واختصاراً ESR يدعم لمدة سنة تقريباً، مثل الإصدار 11.7 الذي ينتهي دعمه في 15 مايو 2027\. فإذا اخترت الإصدارات الشهرية فعليك أن تحدث كل شهر أو شهرين، وأما إذا اخترت ESR فتحدث مرة في السنة من ESR إلى الذي يليه، والتوثيق يذكر أن هذا المسار مدعوم ومختبر بالكامل.

وعندما تشغل الإصدار الجديد يقوم Mattermost بترحيل Migrate قاعدة البيانات تلقائياً إلى الشكل الجديد، وبين الإصدارات الثانوية Minor Versions، مثل 11.10 إلى 11.11، يكون التحديث مباشراً، وأما إذا كنت تقفز عبر عدة إصدارات أو إلى إصدار رئيسي Major Version، مثل 11 إلى 12، فاقرأ قبله [**Important Upgrade Notes**](https://docs.mattermost.com/administration-guide/upgrade/important-upgrade-notes?ref=arabroot.io)، والسبب أن بعض الترحيلات يأخذ وقتاً طويلاً على القواعد الكبيرة، وبعضها يحتاج خطوات يدوية، وفي الإصدار 11.0 مثلاً توقف دعم MySQL وأصبح الحد الأدنى PostgreSQL 14\. والإجراء الرسمي تجده في [صفحة تحديث السيرفر](https://docs.mattermost.com/administration-guide/upgrade/upgrading-mattermost-server?ref=arabroot.io)، وأما في Docker فالخطوات كما يلي:

1. أنشئ نسخة احتياطية كاملة كما في القسم السابق.

تحقق من الإصدار الجديد:

```bash
curl -s "https://chat.example.com/api/v4/config/client?format=old" | grep -o '"Version":"[^"]*"'
```

اسحب Pull الـ Image، وأعد إنشاء الـ Container الخاص بالتطبيق وحده، وراقب السجل:

```bash
docker compose pull mattermost
docker compose up -d mattermost
docker compose logs -f mattermost
```

اختر [الوسم Tag الجديد](https://hub.docker.com/r/mattermost/mattermost-team-edition/tags?ref=arabroot.io)، وغيره في `.env`:

```bash
sed -i 's/^MM_TAG=.*/MM_TAG=11.11.1/' .env
```

وبهذه الخطوات، من [11.10.2](https://github.com/mattermost/mattermost/releases/tag/v11.10.2?ref=arabroot.io) إلى [11.11.1](https://github.com/mattermost/mattermost/releases/tag/v11.11.1?ref=arabroot.io)، يعود الـ Container إلى الحالة `healthy` خلال دقيقة تقريباً، وتبقى الرسائل والـ Webhooks كما هي، وتتحدث الإضافات المدمجة تلقائياً.

![نافذة About Mattermost تعرض Server Version 11.11.1 وDatabase Schema Version 213](https://arabroot.io/content/images/2026/09/mattermost-08-about-after-upgrade.webp)

بعد الترقية: الإصدار 11.11.1

وبعد أن تتأكد من سلامة التحديث احذف الـ Image القديمة بالأمر `docker image prune`. وإذا فشل التحديث فأوقف التطبيق، واستعد نسخة قاعدة البيانات، ثم ارجع إلى الوسم القديم، ولا تقم بتشغيل الإصدار القديم على قاعدة بيانات رحلها الإصدار الجديد، والسبب أن الإصدار القديم لا يعرف شكل الجداول الجديد، وفي الإصدار 11 مثلاً تغيرت طريقة تخزين كلمات المرور إلى PBKDF2، فالمستخدم الذي سجل دخوله بعد التحديث لا يستطيع الدخول إذا رجعت إلى إصدار أقدم من 11.

ويجدر بك أن تعرف أن الإصدار 12.0 مجدول في 14 أكتوبر 2026، وسوف يرفع الحد الأدنى إلى PostgreSQL 15، وهذا لا يؤثر على الملف أعلاه لأنه يستخدم PostgreSQL 18، ولكن انتظر الإصدار التصحيحي الأول منه واقرأ ملاحظاته قبل أن تنتقل إليه.

### تحديث PostgreSQL إلى إصدار رئيسي جديد

تغيير وسم PostgreSQL من إصدار رئيسي إلى آخر، مثل 17 إلى 18، لا يكفي وحده، والسبب أن ملفات البيانات غير متوافقة بين الإصدارين، فسوف يتوقف الـ Container بالرسالة «database files are incompatible with server». والطريقة الآمنة كما في [توثيق التحديث في PostgreSQL](https://www.postgresql.org/docs/18/upgrading.html?ref=arabroot.io) هي أن تفرغ Dump قاعدة البيانات كاملة، ثم تستعيدها في Volume جديد:

```bash
cd /opt/mattermost
docker compose stop mattermost
docker compose exec -T postgres pg_dumpall -U mmuser > backups/all-before-pg-upgrade.sql
docker compose rm -sf postgres
docker volume rm mattermost_db
```

بعد ذلك غير وسم `postgres` في `docker-compose.yml` إلى الإصدار الجديد، وانتبه إلى أن [الـ Image الخاصة بـ PostgreSQL 18](https://hub.docker.com/%5F/postgres?ref=arabroot.io) تستخدم المسار `/var/lib/postgresql`، وليس المسار `/var/lib/postgresql/data` الذي استخدمته الإصدارات السابقة، ثم نفذ:

```bash
docker compose up -d postgres
docker compose exec -T postgres psql -U mmuser -d postgres < backups/all-before-pg-upgrade.sql
docker compose up -d mattermost
```

والرسالة «role mmuser already exists» أثناء الاستعادة طبيعية، لأن الـ Image أنشأت المستخدم عند أول تشغيل، و[pg\_dumpall](https://www.postgresql.org/docs/18/app-pg-dumpall.html?ref=arabroot.io) يحفظ كلمة مرور المستخدم فتبقى مطابقة لما في `.env`. ولا تقم بحذف الـ Volume القديم قبل أن تتأكد أن ملف التفريغ موجود وأن حجمه منطقي.

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

### يتوقف الـ Container بالخطأ «permission denied» على /mattermost/config أو data

وهذا يحدث مع المجلدات المربوطة Bind Mounts، والسبب أن Mattermost يعمل بالمستخدم UID 2000 والمجلد على السيرفر ملك لمستخدم آخر، والحل أن تنفذ `sudo chown -R 2000:2000 ./volumes/app/mattermost`، أو أن تستخدم Volumes مسماة كما في هذا الدليل.

### لا تظهر الرسائل إلا بعد تحديث الصفحة، أو تظهر الرسالة «Cannot connect to the server»

والسبب أن اتصال WebSocket لا يمر عبر الـ Reverse Proxy، والحل أن تفعل Websockets Support في NPM، أو تتحقق من الترويستين Headers `Upgrade` و`Connection` في Nginx.

### روابط الإشعارات تشير إلى localhost، أو يظهر التحذير «Site URL is not set»

والسبب أن المتغير `MM_SERVICESETTINGS_SITEURL` غير مضبوط أو خاطئ، فاضبطه على العنوان العام مع `https`، ثم نفذ `docker compose up -d`.

### Test Connection يظهر الرسالة «Please save unsaved changes first»

والسبب أن الاختبار يستخدم الإعدادات المحفوظة، فاضغط Save أولاً ثم أعد الاختبار.

### يبقى الـ Container بالحالة unhealthy مع أن الموقع يعمل

والسبب أن الـ Healthcheck في الـ Image يعتمد على [mmctl --local](https://docs.mattermost.com/administration-guide/manage/mmctl-command-line-tool?ref=arabroot.io)، وهذا يحتاج `MM_SERVICESETTINGS_ENABLELOCALMODE=true`. ولا تقلق من تفعيله، لأن الوضع المحلي Local Mode يعمل عبر مقبس Socket من نوع Unix داخل الـ Container فقط، ولا يفتح أي منفذ خارجي.

### الخطأ «413 Request Entity Too Large» عند رفع ملف

والسبب هو حد حجم الطلب في الـ Reverse Proxy، والحل أن ترفع قيمة `client_max_body_size` لتطابق Maximum File Size في Mattermost.

## الخلاصة

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

- الخدمة السحابية تقرر نيابة عنك كم تبقى رسائلك، والـ Image الخاصة بـ Enterprise Edition دون ترخيص تخفي ما زاد عن 10,000 رسالة، ولذلك فـ Team Edition هي الخيار المناسب لفريق يقل عن 250 مستخدماً ولا يحتاج SSO.
- اربط منفذ الويب بالعنوان `127.0.0.1` خلف الـ Reverse Proxy مع تفعيل WebSocket، واضبط `MM_SERVICESETTINGS_SITEURL` بدقة لأن منه تبنى كل الروابط.
- أنشئ حساب المدير فور التشغيل، واترك Open Server معطلاً، وفعل Lock to this channel لكل Webhook واحفظ رابطه كما تحفظ كلمة المرور.
- خذ نسخة `pg_dump` ونسخة الـ Volumes وانقلهما خارج السيرفر، ولا تشغل إصداراً أقدم على قاعدة بيانات رحلها إصدار أحدث.
- اختر بين الإصدارات الشهرية وESR حسب عدد المرات التي تستطيع أن تحدث فيها، واقرأ Important Upgrade Notes قبل كل تحديث رئيسي.

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

- سبتمبر 2026: كتابة الدليل واختباره على Mattermost 11.11.1 (مع ترقية مجربة من 11.10.2).
- أكتوبر 2026: مراجعة الدليل، وحذف إعدادات Bleve التي أزيلت في الإصدار 11.0، وتصحيح متطلبات العتاد، وإضافة الفرق بين Team Edition وEntry وحدود المكالمات، وشرح الإصدارات الشهرية وESR والإصدار 12.0.