الأدلة التقنية

تثبيت خادم البريد mailcow باستخدام Docker

أن تدير خادم بريدك بنفسك يعني أن تضمن وصول رسائلك إلى صندوق الوارد لا إلى الرسائل المزعجة. يشرح هذا الدليل تثبيت mailcow، وضبط سجلات DNS المطلوبة، وحل مشكلات التسليم الشائعة.

تثبيت خادم البريد mailcow باستخدام Docker

في هذا الدليل سوف نثبت mailcow على سيرفر واحد، وهو حزمة جاهزة من عدة مكونات Components تعمل كلها في Docker Containers، حيث يرسل Postfix البريد ويستقبله، ويدير Dovecot صناديق البريد Mailboxes عبر IMAP وPOP3، ويكافح Rspamd الرسائل المزعجة Spam ويوقع Signs الرسائل بـ DKIM، ويفحص ClamAV المرفقات Attachments، ويقدم SOGo البريد عبر الويب Webmail مع التقويم Calendar وجهات الاتصال Contacts، وتتحكم في ذلك كله لوحة إدارة Admin Panel واحدة، ومعها سكربتات Scripts رسمية للتثبيت Installation والتحديث Update والنسخ الاحتياطي Backup. ويناسب mailcow الشركات الصغيرة والمتوسطة، والجهات التي تريد أن يبقى بريدها على سيرفراتها، ومن يدير عدة نطاقات Domains من لوحة واحدة، أما إذا كان كل ما تحتاجه إرسال رسائل آلية Transactional Emails من تطبيقاتك، فخدمة إرسال مثل Amazon SES أو خادم SMTP وسيط SMTP Relay أبسط بكثير.

وإذا لم تقرر بعد هل تستضيف بريد مؤسستك بنفسك، وما الذي تتحمله في المقابل من سمعة Reputation ومتابعة، فابدأ بـ دليل استضافة البريد الإلكتروني للمؤسسات، فهو يشرح الصورة الكاملة من القرار إلى خطة النقل، ثم عد إلى هذا الدليل للتثبيت.

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

  • متطلبات السيرفر والمنافذ واسم السيرفر، ولماذا يحدد مزود الاستضافة نجاح خادم البريد قبل أن تبدأ.
  • سجلات DNS المطلوبة: A وMX وSPF وDKIM وDMARC وPTR، والسجلات الاختيارية مثل MTA-STS وTLS-RPT.
  • تثبيت mailcow بالسكربت generate_config.sh، ثم إضافة النطاق وصناديق البريد ومفتاح DKIM.
  • تشغيل mailcow خلف Reverse Proxy، والتحقق من النجاح، والنسخ الاحتياطي، والتحديث.
  • أشهر مشكلات وصول الرسائل Deliverability وحلولها.

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

السيرفر

  • الذاكرة RAM: يحتاج الإعداد الافتراضي Default Configuration إلى 6 GiB من الذاكرة على الأقل مع 1 GiB من swap، وإلى 8 GiB لفريق من 5 إلى 10 مستخدمين، وأكثر المكونات استهلاكاً للذاكرة ClamAV ومحرك البحث النصي FTS، ويمكنك إيقافهما في السيرفرات الصغيرة.
  • المعالج CPU والقرص Disk: معالج x86_64 أو ARM64، و20 GiB للنظام وال Containers دون حساب الرسائل نفسها، ثم احسب مساحة البريد من عدد الصناديق وحصة Quota كل صندوق.
  • نوع الأجهزة الافتراضية Virtualization: يعمل mailcow على المنصات التي تقدم جهازاً افتراضياً كاملاً مثل KVM وESX وHyper-V، أما OpenVZ وVirtuozzo وLXC وأجهزة NAS مثل Synology وQNAP فلا يدعمها، لذلك اسأل المزود عن نوع الأجهزة الافتراضية إذا كان سعر الخطة رخيصاً بشكل لافت.
  • النظام: توزيعة Linux Distribution حديثة مثل Debian أو Ubuntu LTS، مع Docker Engine 24 أو أحدث وإضافة Plugin Docker Compose، وإذا لم يكن Docker مثبتاً فاتبع دليل تثبيت Docker على Ubuntu. وتحتاج أيضاً إلى git وopenssl وcurl وjq (صار مطلوباً منذ إصدار 2025-09)، وإلى مزامنة الوقت NTP مفعلة، فتأكد بالأمر timedatectl أن السطرين NTP service وSystem clock synchronized قيمتهما active وyes.
  • عنوان IP ثابت Static IP ونظيف: سيرفر افتراضي VPS بعنوان IPv4 ثابت غير مدرج في قوائم الحظر Blocklists، ويجب أن يسمح المزود بالاتصال الصادر Outbound Connection على المنفذ 25 وأن يتيح لك ضبط سجل PTR. وكثير من المزودين يحجبون المنفذ 25 افتراضياً، فمثلاً تحجب Hetzner المنفذين 25 و465 على كل سيرفرات Cloud ولا تفتحهما إلا بطلب بعد شهر من التسجيل ودفع أول فاتورة، وتحجب DigitalOcean منافذ SMTP على كل Droplets، وتقيد AWS المنفذ 25 على EC2 حتى تقدم طلباً لرفع القيد. لذلك تحقق من ذلك قبل الشراء، وراجع دليل اختيار خادم VPS. أما خادم بريد على اتصال الإنترنت المنزلي Residential Connection فهو غير عملي في الغالب، والسبب أن عناوين IP المنزلية مدرجة عادة في قوائم الحظر، وسجل PTR بيد مزود خدمة الإنترنت ISP وليس بيدك.
  • سيرفر مخصص Dedicated Server للبريد إن أمكن: يستخدم mailcow المنفذين 80 و443 وعدة منافذ للبريد، ويعمل أفضل عندما ينفرد بها، ويمكن تشغيله مع تطبيقات ويب أخرى خلف Reverse Proxy كما سيأتي في قسم مستقل.

المنافذ

يسرد دليل المتطلبات الرسمي المنافذ التالية:

المنفذالخدمةالاستخدام
25/tcpSMTPاستقبال البريد من السيرفرات الأخرى وإرساله إليها
465/tcpSMTPSإرسال البريد من برامج المستخدمين Mail Clients عبر TLS مباشر
587/tcpSubmissionإرسال البريد من برامج المستخدمين عبر STARTTLS
143/tcp و993/tcpIMAP وIMAPSقراءة البريد من البرامج والهواتف
110/tcp و995/tcpPOP3 وPOP3Sقراءة البريد بطريقة POP3 (اختياري)
4190/tcpManageSieveإدارة قواعد الفرز Filtering Rules من برامج البريد
80/tcp و443/tcpHTTP وHTTPSلوحة الإدارة وSOGo وActiveSync وautodiscover والتحقق عبر HTTP (HTTP Challenge) لشهادة Let's Encrypt

افتح هذه المنافذ في جدار الحماية Firewall، وفي لوحة المزود أيضاً إذا كان فيها جدار حماية خارجي، والأمر التالي يفتحها مع ufw:

sudo ufw allow 22,25,80,443,110,143,465,587,993,995,4190/tcp

ثم تأكد أنه لا توجد خدمة أخرى على السيرفر تستخدم هذه المنافذ، مثل Postfix أو Exim اللذين يأتيان أحياناً مع النظام:

sudo ss -tlpn | grep -E ':(25|80|110|143|443|465|587|993|995|4190)\s'

اسم السيرفر Hostname والنطاق

هنا اسمان مختلفان يخلط بينهما كثيرون، فالأول هو اسم خادم البريد (FQDN) مثل mail.example.com، وبه يعرف السيرفر نفسه أمام السيرفرات الأخرى وله تصدر الشهادة Certificate، والثاني هو نطاق البريد مثل example.com، وهو ما يظهر بعد @ في العناوين، ولاحظ أن سيرفراً واحداً باسم mail.example.com يستطيع أن يخدم عدة نطاقات. ابدأ بضبط اسم السيرفر في النظام:

sudo hostnamectl set-hostname mail.example.com
hostname -f

سجلات DNS

سجلات DNS هي التي تحدد هل تصل رسائلك أم تضيع، فمنها يقرأ السيرفر المستقبل SPF وDKIM وDMARC والاستعلام العكسي PTR، وقد شرحنا ما يفعله كل واحد منها ولماذا يوجد في شرح SPF وDKIM وDMARC للمبتدئين، وأنواع السجلات نفسها في شرح DNS وسجلاته للمبتدئين. والآن سوف نضيف السجلات التالية في لوحة DNS الخاصة بنطاقك، وضع عنوان سيرفرك مكان 203.0.113.10:

الاسمالنوعالقيمةالغرض
mail.example.comA203.0.113.10عنوان خادم البريد (أضف سجل AAAA إذا كان IPv6 مضبوطاً لديك)
example.comMX10 mail.example.comيخبر السيرفرات الأخرى أين تسلم بريد النطاق، والقيمة اسم وليست عنوان IP
example.comTXTv=spf1 mx a -allSPF: السيرفر المذكور في سجل MX هو وحده المصرح له بالإرسال
dkim._domainkey.example.comTXTv=DKIM1;k=rsa;t=s;s=email;p=MIIB…المفتاح العام Public Key لتوقيع DKIM، وتنسخه من لوحة mailcow بعد إضافة النطاق
_dmarc.example.comTXTv=DMARC1; p=none; rua=mailto:[email protected]سياسة DMARC وعنوان استقبال التقارير
autodiscover.example.comCNAMEmail.example.comالإعداد التلقائي Autoconfiguration في Outlook والهواتف
autoconfig.example.comCNAMEmail.example.comالإعداد التلقائي في Thunderbird
_autodiscover._tcp.example.comSRV0 1 443 mail.example.comبديل autodiscover لبعض البرامج
203.0.113.10 (عكسي)PTRmail.example.comالاستعلام العكسي، ويضبط من لوحة مزود السيرفر وليس من لوحة DNS

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

  • PTR أو rDNS: يجب أن يطابق اسم السيرفر تماماً، وأن يشير السجل A لهذا الاسم إلى العنوان نفسه، وستجده في لوحة مزود ال VPS باسم Reverse DNS أو rDNS، وإذا أضفت سجل AAAA فاضبط PTR لعنوان IPv6 أيضاً. وبدون هذا التطابق ترفض Gmail وغيرها كثيراً من الرسائل أو تصنفها رسائل مزعجة.
  • SPF: سجل واحد فقط لكل نطاق، فإذا كنت ترسل أيضاً عبر خدمة أخرى مثل نشرة بريدية Newsletter أو نظام تذاكر Ticketing System فأضفها إلى السجل نفسه، مثل v=spf1 mx a include:amazonses.com -all، والسبب أن وجود سجلي SPF يجعل الفحص يفشل في الحالتين.
  • DMARC: المثال في التوثيق الرسمي يبدأ مباشرة بالقيمة p=reject، ولكن الأسلم أن تبدأ بالقيمة p=none ثم تنتقل إلى p=quarantine ثم إلى p=reject بعد أن تقرأ التقارير، كما شرحنا في قسم المراحل من شرح SPF وDKIM وDMARC للمبتدئين.
  • قواعد Gmail وYahoo: منذ فبراير 2024 تشترط Gmail على كل من يرسل إلى حساباتها SPF أو DKIM وسجل PTR مطابقاً والاتصال عبر TLS، وقواعد Yahoo مشابهة، وقد جمعنا الشروط كاملة ولمن تنطبق في شرح SPF وDKIM وDMARC للمبتدئين. والإعداد في هذا الدليل يحقق شروط المرسل العادي كلها.
  • MTA-STS وTLS-RPT (اختياريان): يخبر MTA-STS السيرفرات الأخرى أن بريد نطاقك يجب أن يصل عبر TLS فقط، ويدعمه mailcow من لوحة الإدارة منذ إصدار 2025-09 مع سجل TXT باسم _mta-sts وسجل CNAME باسم mta-sts، ويضيف إليه سجل TLS-RPT باسم _smtp._tls عنواناً تصلك عليه تقارير فشل TLS. أضفهما بعد أن يستقر كل شيء، وابدأ بالوضع testing.
  • إذا كنت تستخدم Cloudflare أو خدمة مشابهة، فاجعل سجلات mail وautodiscover وautoconfig على وضع DNS only دون ال Proxy، والسبب أن ال Proxy يمرر HTTP فقط ولا يمرر منافذ البريد.
  • كل نطاق تضيفه لاحقاً إلى mailcow يحتاج إلى سجلاته الخاصة: MX وSPF وDKIM وDMARC وautodiscover وautoconfig، أما سجلا A وPTR لاسم السيرفر فيبقيان كما هما.

بعد نشر السجلات تحقق منها من أي جهاز:

dig +short A mail.example.com
dig +short MX example.com
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short -x 203.0.113.10

التثبيت

تنزيل mailcow

نثبت mailcow من مستودعه على GitHub Repository، ولاحظ أن المستودع نفسه يحفظ ملف الإعداد Configuration File والبيانات الدائمة Persistent Data، لذلك ضعه في مسار دائم مثل /opt/mailcow-dockerized. وتتطلب السكربتات أن تكون قيمة umask هي 0022 حتى تنشئ الملفات بالصلاحيات Permissions الصحيحة، فتأكد منها أولاً:

umask

ثم نزل المستودع بصلاحيات root:

sudo -i
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized

الفرع Branch الافتراضي master هو الفرع المستقر، ويحمل آخر إصدار منشور (2026-09 وقت كتابة الدليل). ولا تستخدم الوسم Tag latest ولا تغير وسوم ال Images يدوياً، والسبب أن كل إصدار من mailcow يثبت وسوم ال Images الخاصة به في docker-compose.yml، وسكربت التحديث وحده هو الذي ينقلك بين الإصدارات.

إنشاء ملف الإعداد

السكربت generate_config.sh يولد الملف mailcow.conf بكلمات مرور عشوائية Random Passwords لقاعدة البيانات Database وRedis وغيرهما، وينشئ أيضاً شهادة مؤقتة Self-signed Certificate تعمل حتى تصدر شهادة Let's Encrypt:

./generate_config.sh

وعند تشغيل الأمر سوف يسألك السكربت عن القيم التالية:

  • Mail server hostname (FQDN): اسم السيرفر مثل mail.example.com، وليس نطاق البريد.
  • Timezone: المنطقة الزمنية مثل UTC أو منطقتك المحلية بالصيغة Region/City.
  • الفرع: اختر 1 للفرع المستقر master.
  • إذا كانت الذاكرة 2.5 GiB أو أقل فسوف يقترح السكربت إيقاف ClamAV، فوافق على ذلك في السيرفرات الصغيرة.

ويتحقق السكربت أيضاً من دعم IPv6 على السيرفر ويضبط ENABLE_IPV6 تلقائياً، ويضيف إلى الملف الخيار SPAMHAUS_DQS_KEY، والسبب أن Spamhaus تمنع الاستعلام المجاني عن قوائمها من شبكات بعض المزودين مثل OVH وAWS وCloudflare، فإذا كان سيرفرك في إحداها عطل mailcow قوائم Spamhaus عند التشغيل، إلا إذا أنشأت حساباً مجانياً لخدمة DQS ووضعت مفتاحها في هذا الخيار.

أهم خيارات mailcow.conf

افتح الملف وراجع القيم التالية قبل التشغيل الأول، ولاحظ أن الملف .env في المجلد هو رابط Symlink إلى mailcow.conf، لذلك يقرأ Docker Compose القيم منه مباشرة:

nano mailcow.conf
# اسم الخادم كما أدخلته
MAILCOW_HOSTNAME=mail.example.com

# منافذ الواجهة؛ اتركها 80 و443 إن كان mailcow يملك الخادم وحده
HTTP_PORT=80
HTTP_BIND=
HTTPS_PORT=443
HTTPS_BIND=

# تحويل HTTP إلى HTTPS تلقائيًا
HTTP_REDIRECT=y

# أسماء إضافية في الشهادة، مثل imap.* وsmtp.* لكل نطاق
ADDITIONAL_SAN=

# شهادات Let's Encrypt عبر حاوية acme-mailcow
SKIP_LETS_ENCRYPT=n

# الخدمات الثقيلة: أوقفها في الخوادم الصغيرة
SKIP_CLAMD=n
SKIP_FTS=n

# إشعارات watchdog عند تعطل خدمة
USE_WATCHDOG=y
[email protected]

# شبكة Docker الداخلية؛ غيّرها فقط إن تعارضت مع شبكة موجودة
IPV4_NETWORK=172.22.1

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

  • لا تغير DBPASS وDBROOT وREDISPASS بعد التشغيل الأول، والسبب أن هذه القيم تسجل في قاعدة البيانات عند إنشائها.
  • يستخدم IPV4_NETWORK الشبكة 172.22.1.0/24، فإذا كانت لديك شبكة Docker أو VPN في هذا النطاق فاختر قيمة أخرى مثل 172.29.1.
  • في الملف كلمات مرور، وصلاحياته 600 ويجب أن تبقى كذلك، وهو جزء من النسخ الاحتياطي.

التشغيل الأول

docker compose pull
docker compose up -d

التنزيل الأول يجلب قرابة 18 Image حجمها عدة غيغابايتات، والإقلاع الأول يستغرق بضع دقائق لأن MariaDB تنشئ الجداول Tables وClamAV يحمل قواعد التواقيع Signature Databases، وتستطيع متابعة الحالة بهذين الأمرين:

docker compose ps
docker compose logs -f --tail=50 nginx-mailcow acme-mailcow

وفي سجلات Logs ال Container acme-mailcow سوف ترى التحقق من السجل A لاسم السيرفر ثم إصدار الشهادة، وإذا فشل الإصدار لأن سجلات DNS لم تنتشر Propagation بعد فسوف يعيد ال Container المحاولة تلقائياً، ويمكنك إعادة تشغيله بنفسك بعد ضبط السجلات:

docker compose restart acme-mailcow

الدخول الأول وتغيير كلمة مرور المدير Administrator

افتح https://mail.example.com/admin، ولاحظ أن في لوحة mailcow ثلاثة أنواع من الدخول: المدير في /admin، ومدير النطاق Domain Administrator في /domainadmin، والمستخدم العادي Regular User في الصفحة الرئيسية. وبيانات المدير الافتراضية Default Credentials هي اسم المستخدم admin وكلمة المرور moohoo، وهي معروفة للجميع، لذلك غيرها قبل أي خطوة أخرى.

صفحة دخول المدير في mailcow
صفحة دخول المدير في /admin، وأسفلها روابط دخول المستخدم ومدير النطاق

بعد الدخول افتح System ← Configuration ← Access ← Administrators، ثم اختر Edit بجوار المستخدم admin وأدخل كلمة مرور قوية مرتين واحفظ، وتستطيع توليد كلمة مرور من الطرفية Terminal بالأمر التالي:

openssl rand -base64 24
نموذج تعديل حساب المدير وتغيير كلمة المرور
تغيير كلمة مرور المدير الافتراضية من صفحة Edit administrator

ومن الصفحة نفسها فعل التحقق الثنائي Two-Factor Authentication (TOTP أو مفتاح FIDO2) لحساب المدير، والسبب أن هذه اللوحة تتحكم في كل صناديق البريد. وإذا نسيت كلمة المرور لاحقاً فالسكربت helper-scripts/mailcow-reset-admin.sh يعيد ضبط Reset الحساب بكلمة مرور عشوائية.

وصفحة System ← Information تعرض حالة كل ال Containers وإصدار كل Image، فراجعها بعد التشغيل الأول لتتأكد أن كل الخدمات في حالة Running.

قائمة Containers الخاصة بـ mailcow وحالتها في لوحة الإدارة
قسم Container information: تعمل كل خدمة في Container مستقل بوسم Image مثبت

إضافة نطاق وصناديق بريد

إضافة النطاق

افتح E-Mail ← Configuration ← Domains ثم اختر Add domain، والحقول الأساسية هي:

  • Domain: نطاق البريد فقط مثل example.com، دون mail..
  • Max. possible mailboxes / aliases والحصص: حدود النطاق، والحصة الافتراضية لكل صندوق 3 GiB وحدها الأقصى 10 GiB في الإعداد الافتراضي، فعدلها بحسب خطتك.
  • Rate limit: أقصى عدد من الرسائل يرسله النطاق، مثل 100 رسالة في الساعة، وهذا الحد يحمي سمعة سيرفرك إذا سرق أحدهم كلمة مرور حساب واستغله في إرسال الرسائل المزعجة.
  • Selector وDKIM key length: ينشئ mailcow مفتاح DKIM للنطاق تلقائياً بالمحدد Selector dkim وبطول 2048 بت، فاترك القيم الافتراضية.
نافذة إضافة نطاق بريد جديد في mailcow
نافذة Add domain مع حد إرسال قدره 100 رسالة في الساعة ومفتاح DKIM بطول 2048 بت

اختر Add domain and restart SOGo حتى يتعرف البريد عبر الويب على النطاق الجديد، وبعد ضبط سجلات DNS للنطاق أعد تشغيل acme-mailcow ليضيف autodiscover.example.com وautoconfig.example.com إلى الشهادة.

إنشاء صندوق بريد

من التبويب Mailboxes اختر Add mailbox، ثم أدخل الجزء الأيسر من العنوان Local Part مثل info والاسم الكامل، واختر النطاق وحدد كلمة المرور والحصة. والخيار Force password update at next login يلزم المستخدم بتغيير كلمة المرور المؤقتة Temporary Password التي أعطيته إياها.

نافذة إنشاء صندوق بريد جديد
إنشاء الصندوق [email protected] مع البروتوكولات المسموح بها وحد الإرسال الخاص به
قائمة صناديق البريد في mailcow
الصندوق الجديد في القائمة، ويفتحه زر Login مباشرة في SOGo

ومن التبويب نفسه تنشئ Aliases مثل [email protected] توجه الرسائل إلى صندوق أو أكثر، وDomain aliases تجعل نطاقاً ثانياً مرادفاً للأول، ويمكنك تعيين مدير لكل نطاق من Access ← Domain administrators فيدير صناديقه دون أن يصل إلى إعدادات السيرفر.

مفتاح DKIM وفحص DNS

زر DNS بجوار النطاق في قائمة النطاقات يعرض كل السجلات المطلوبة بقيمها الصحيحة وحالتها الحالية في DNS، وهذه الشاشة هي أسرع طريقة لنسخ القيم ولمعرفة السجل الناقص.

نافذة فحص سجلات DNS للنطاق في mailcow
فحص DNS المدمج: القيم المطلوبة لكل سجل، ومنها سجل DKIM الكامل. ويبقى عمود الحالة فارغاً ما دامت السجلات غير منشورة في DNS عام

وتجد المفتاح العام أيضاً في System ← Configuration ← Options ← ARC/DKIM keys، فانسخ القيمة كاملة وأضفها سجل TXT باسم dkim._domainkey.example.com. ولاحظ أن بعض لوحات DNS تقسم القيم الطويلة إلى عدة سلاسل Strings بين علامات تنصيص، ولا مشكلة في ذلك ما دامت السلاسل متتالية دون فواصل.

صفحة مفاتيح ARC وDKIM في mailcow
مفتاح DKIM للنطاق بحالة Key valid والمحدد dkim

البريد عبر الويب والبرامج

يدخل المستخدم من https://mail.example.com بعنوانه وكلمة مروره، فينقله mailcow إلى SOGo حيث البريد والتقويم وجهات الاتصال، أما برامج البريد مثل Thunderbird وOutlook وتطبيقات الهواتف فيكفيها غالباً العنوان وكلمة المرور، والسبب أن بقية الإعداد تتولاها سجلات autodiscover وautoconfig.

وللإعداد اليدوي Manual Setup استخدم هذه القيم: IMAP على mail.example.com بالمنفذ 993 مع SSL/TLS، وSMTP على المنفذ 465 مع SSL/TLS أو المنفذ 587 مع STARTTLS، واسم المستخدم هو العنوان الكامل.

واجهة البريد عبر الويب SOGo بعد دخول المستخدم
صندوق [email protected] في SOGo بعد الدخول من الصفحة الرئيسية
💡
للتطبيقات التي ترسل عبر SMTP مثل listmonk أو Chatwoot، أنشئ صندوقاً مخصصاً مثل [email protected]، واستخدم كلمة مرور تطبيق App password من إعدادات الصندوق بدلاً من كلمة المرور الأساسية، وحدد له Rate limit مناسباً، والسبب أن تسريب كلمة مرور التطبيق لا يكشف الحساب كله وتستطيع إلغاءها وحدها.

كيف تشغل mailcow خلف Reverse Proxy؟

أبسط إعداد وأكثره استقراراً أن ينفرد mailcow بالمنفذين 80 و443 على سيرفر مخصص، فيصدر ال Container acme-mailcow الشهادة ويجددها Renewal ويستخدمها Postfix وDovecot مباشرة. أما إذا كان لديك Reverse Proxy على السيرفر نفسه مثل Nginx Proxy Manager، فانقل واجهة mailcow إلى منافذ داخلية Internal Ports:

HTTP_PORT=8080
HTTP_BIND=127.0.0.1
HTTPS_PORT=8443
HTTPS_BIND=127.0.0.1

ثم أعد إنشاء ال Containers:

docker compose up -d

داخل شبكة mailcow يستمع ال Container nginx-mailcow على المنفذ نفسه (8080)، لذلك يصل إليه باسمه أي Reverse Proxy يعمل في Docker إذا وصلته بشبكة mailcow، واسم الشبكة <COMPOSE_PROJECT_NAME>_mailcow-network وقيمته الافتراضية mailcowdockerized_mailcow-network:

# في docker-compose.yml الخاص بـ Nginx Proxy Manager
services:
  app:
    networks:
      - default
      - mailcow

networks:
  mailcow:
    name: mailcowdockerized_mailcow-network
    external: true

وفي NPM أنشئ Proxy Host للأسماء mail.example.com وautodiscover.example.com وautoconfig.example.com يوجه الطلبات إلى http://nginx-mailcow:8080، ثم فعل Websockets Support وForce SSL وشهادة Let's Encrypt من NPM.

وتبقى مسألة الشهادة على منافذ البريد، حيث يحتاج Postfix وDovecot إلى شهادة صالحة للاسم mail.example.com، ولكن NPM يستقبل طلبات /.well-known/acme-challenge/ لنفسه، فيفشل التحقق عبر HTTP (HTTP Challenge) الذي تعتمد عليه acme-mailcow. والحل الأنسب أن يصدر mailcow شهادته عبر التحقق من ملكية النطاق عبر ال DNS (DNS Challenge) بعيداً عن ال Reverse Proxy، والمثال هنا Cloudflare، والطريقة نفسها تعمل مع أي مزود يدعمه acme.sh:

ACME_DNS_CHALLENGE=y
ACME_DNS_PROVIDER=dns_cf
[email protected]

ثم مرر متغيرات البيئة Environment Variables الخاصة بالمزود إلى ال Container من ملف docker-compose.override.yml في مجلد mailcow، ولاحظ أن سكربت التحديث لا يمس هذا الملف:

services:
  acme-mailcow:
    environment:
      - CF_Token=REPLACE_WITH_CLOUDFLARE_API_TOKEN
      - CF_Zone_ID=REPLACE_WITH_ZONE_ID
docker compose up -d
docker compose logs --tail=50 acme-mailcow
⚠️
لا تمرر منافذ البريد (25 و465 و587 و993 وغيرها) عبر ال Reverse Proxy إطلاقاً، بل اتركها منشورة مباشرة من ال Containers الخاصة بـ mailcow، فال Reverse Proxy يخدم الواجهة وActiveSync وautodiscover فقط.

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

  • أرسل رسالة من SOGo إلى حساب Gmail ثم افتح Show original، وتأكد أن نتيجة SPF وDKIM وDMARC هي PASS، وللتقييم الكامل أرسل رسالة إلى أداة مثل mail-tester.com.

أرسل رسالة من حساب خارجي إلى [email protected] وتأكد أنها وصلت، وعند أي مشكلة راجع سجل Postfix:

docker compose logs --tail=100 postfix-mailcow

المنفذ 25 الصادر مفتوح لدى المزود، فنفذ الأمر التالي من السيرفر نفسه، وإذا انتهت المهلة دون اتصال فالمزود يحجبه:

nc -vz -w 5 gmail-smtp-in.l.google.com 25

المنفذ 25 يستجيب من خارج السيرفر ويعلن الاسم الصحيح، فنفذ الأمر التالي من جهاز آخر:

nc -v mail.example.com 25

والمخرج سوف يكون سطراً يبدأ بـ 220 mail.example.com ESMTP.

الشهادة من Let's Encrypt وليست الشهادة المؤقتة، على HTTPS وعلى منفذ SMTP:

echo | openssl s_client -connect mail.example.com:443 -servername mail.example.com 2>/dev/null | openssl x509 -noout -issuer -dates
echo | openssl s_client -starttls smtp -connect mail.example.com:587 2>/dev/null | openssl x509 -noout -issuer

جميع ال Containers في حالة running أو healthy:

docker compose ps --format 'table {{.Service}}\t{{.Status}}'

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

لـ mailcow سكربت رسمي للنسخ الاحتياطي ينسخ كل ما يلزم: الرسائل (vmail) وقاعدة البيانات، ومفاتيح التشفير (crypt) التي لا تقرأ الرسائل المستعادة بدونها، وRedis وفيه مفاتيح DKIM، وبيانات Rspamd، وطوابير Queues ال Postfix، ونسخة من mailcow.conf. ويعمل السكربت والخدمات قيد التشغيل، ويضع كل نسخة في مجلد باسم mailcow-YYYY-MM-DD-HH-MM-SS:

mkdir -p /opt/backup/mailcow
cd /opt/mailcow-dockerized
MAILCOW_BACKUP_LOCATION=/opt/backup/mailcow ./helper-scripts/backup_and_restore.sh backup all --delete-days 7

الخيار --delete-days 7 يحذف النسخ التي مضى عليها أكثر من سبعة أيام، وفي أول تشغيل يسحب الأمر Image مساعدة باسم ghcr.io/mailcow/backup. وللجدولة Scheduling اليومية أضف مهمة cron:

sudo crontab -e
30 2 * * * cd /opt/mailcow-dockerized && MAILCOW_BACKUP_LOCATION=/opt/backup/mailcow THREADS=2 ./helper-scripts/backup_and_restore.sh backup all --delete-days 7 >/var/log/mailcow-backup.log 2>&1

لكن تذكر: النسخة المحفوظة على قرص السيرفر نفسه لا تحميك إذا تعطل السيرفر، لذلك انقل المجلد إلى تخزين خارجي Offsite Storage بأداة مثل restic أو rsync أو rclone، وانسخ معه docker-compose.override.yml وأي ملفات عدلتها في data/conf.

وللاستعادة على سيرفر جديد ثبت mailcow بالإصدار نفسه واسم السيرفر نفسه، وانتظر حتى يعمل بالكامل، وتأكد أن قيمة MAILDIR_SUB في mailcow.conf مطابقة للسيرفر القديم لأن اختلافها يخفي الرسائل بعد الاستعادة، ثم شغل السكربت في وضع restore، فيعرض النسخ المتاحة وتختار نقطة الاستعادة Restore Point وما تريد استعادته، سواءً كل شيء أو جزءاً محدداً:

cd /opt/mailcow-dockerized
MAILCOW_BACKUP_LOCATION=/opt/backup/mailcow ./helper-scripts/backup_and_restore.sh restore
🛑
تكتب الاستعادة فوق البيانات الحالية، لذلك لا تجربها على سيرفر الإنتاج Production Server، بل اختبرها دورياً على سيرفر مؤقت لتتأكد أن النسخ صالحة فعلاً. ولا تفصل نسخة vmail عن نسخة crypt، والسبب أن الرسائل مخزنة على القرص مشفرة Encrypted بمفاتيح crypt.

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

يصدر mailcow تحديثاً كل شهر تقريباً باسم مثل 2026-09، وبينها تحديثات تصحيحية Patch Releases بحروف مثل 2026-07a و2026-07b. ولا تحدث ال Images يدوياً بتعديل الوسوم، وإنما استخدم السكربت update.sh الذي يسحب الكود Code الجديد ويدمجه مع تعديلاتك، ثم يحدث وسوم ال Images ويسحبها ويعيد التشغيل. وقبل التحديث خذ نسخة احتياطية واقرأ ملاحظات الإصدار Release Notes على GitHub:

cd /opt/mailcow-dockerized
./update.sh --check

رمز الخروج Exit Code 0 يعني أن هناك تحديثاً، والرمز 3 يعني أنك على آخر إصدار. ولتقصير مدة التوقف Downtime اسحب ال Images أولاً ثم نفذ التحديث:

./update.sh --prefetch
./update.sh

وقد يحدث السكربت ملفاته المساعدة في المجلد _modules ثم يطلب منك تشغيله مرة ثانية، فنفذه مجدداً، وبعد التحديث احذف ال Images القديمة لتوفير المساحة:

./update.sh --gc

وضع تعديلاتك في docker-compose.override.yml وفي ملفات الإعداد المخصصة التي يوثقها mailcow مثل data/conf/postfix/extra.cf، ولا تضعها في docker-compose.yml، والسبب أنها سوف تتعارض مع التحديث. وتنبهك لوحة الإدارة إلى صدور إصدار جديد في صفحة Information.

📌
في 2 مارس 2021 أصدرت Microsoft تحديثاً طارئاً لأربع ثغرات في Exchange Server المثبت على سيرفرات المؤسسات نفسها On-premises (الإصدارات 2013 و2016 و2019)، وكانت مجموعة HAFNIUM تستغلها فعلاً لزرع Web Shells على السيرفرات وسرقة محتوى صناديق البريد، بينما لم تتأثر خدمة Exchange Online التي تديرها Microsoft. وفي اليوم التالي أصدرت CISA التوجيه الطارئ ED 21-02 الذي ألزم الجهات الفيدرالية الأمريكية بتثبيت التحديث فوراً أو فصل السيرفرات عن الشبكة. والدرس واضح: من يستضيف بريده بنفسه يتحمل مسؤولية التحديث التي كان يتحملها المزود، لذلك تابع إصدارات mailcow الأمنية ولا تؤجلها.

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

لماذا تصل الرسائل إلى مجلد الرسائل المزعجة أو ترفض؟

  • PTR غير مطابق: تأكد أن dig +short -x 203.0.113.10 يعيد mail.example.com، وأن السجل A لهذا الاسم يعيد العنوان نفسه.
  • فشل SPF أو DKIM: راجع الترويسة Header المسماة Authentication-Results في الرسالة المستلمة، فإذا كانت نتيجة DKIM fail أو none فالسبب غالباً مفتاح نسخته ناقصاً أو بمسافات زائدة، أو سجل DNS قديم ما زال في الذاكرة المؤقتة Cache.
  • عنوان IP في قوائم الحظر: افحصه لدى Spamhaus وMXToolbox، فبعض المزودين يعطونك عنواناً جديداً يحمل سمعة سيئة من مستخدمين سابقين، فاطلب رفعه من القائمة أو اطلب عنواناً آخر.
  • سمعة جديدة: السيرفرات الأخرى تتعامل بحذر مع سيرفر جديد ليس له تاريخ إرسال Sending History، لذلك ابدأ بحجم إرسال Sending Volume صغير، ولا ترسل الحملات التسويقية Marketing Campaigns من خادم البريد الأساسي، بل خصص لها أداة مستقلة ونطاقاً فرعياً Subdomain، والسبب أن شكاوى حملة واحدة قد تضر بريد الموظفين اليومي.
  • Microsoft وOutlook: سجل عنوانك في برنامج Microsoft SNDS، وإذا رفضت Microsoft رسائلك برمز يذكر عنوان IP فاطلب رفع الحظر من صفحة الدعم الخاصة بها.

لماذا يتعذر الإرسال إلى الخارج؟

إذا بقيت الرسائل في الطابور (E-Mail ← Queue Manager) مع الخطأ Connection timed out على المنفذ 25، فالمزود يحجب المنفذ الصادر، فاطلب فتحه من الدعم الفني Support، أو أرسل عبر خادم وسيط Relay مثل Amazon SES. أضف بيانات الوسيط في System ← Configuration ← Routing ← Sender-dependent transports ثم اختره في إعدادات النطاق، وإذا استخدمت وسيطاً فأضفه إلى سجل SPF وأضف سجلات DKIM التي يطلبها.

ال Container unbound-mailcow بحالة unhealthy

يستخدم mailcow خادم DNS داخلياً هو Unbound يستعلم مباشرة من الخوادم الجذرية Root Servers، والسبب أن فحوص الرسائل المزعجة تحتاج إلى استعلامات DNS دقيقة. فإذا كان جدار حماية الشبكة يمنع استعلامات DNS الصادرة على المنفذ 53، يفشل unbound-mailcow في فحص الصحة Health Check وتبقى بقية ال Containers متوقفة في انتظاره. والحل الصحيح أن تسمح بالاتصال الصادر على UDP/TCP 53، ومؤقتاً يمكنك تجاوز الفحص:

SKIP_UNBOUND_HEALTHCHECK=y

ولا توجه استعلامات Unbound إلى خوادم DNS عامة مثل 8.8.8.8، والسبب أن قوائم الحظر مثل Spamhaus ترفض الاستعلامات القادمة منها.

فشل التشغيل لأن أحد المنافذ مستخدم

إذا ظهر خطأ مثل bind: address already in use على المنفذ 25، فهناك Postfix أو Exim تابع للنظام يعمل على السيرفر، فأوقفه وعطله (systemctl disable --now postfix)، وإذا ظهر على المنفذين 80 و443 فهناك خادم ويب Web Server أو Reverse Proxy آخر، فاتبع قسم ال Reverse Proxy.

الذاكرة لا تكفي

إذا ظل Docker يعيد تشغيل clamd-mailcow أو غيره وظهرت رسائل OOM في dmesg، فاضبط SKIP_CLAMD=y وSKIP_FTS=y في mailcow.conf، ثم أضف ملف swap ونفذ docker compose up -d.

المتصفح Browser وبرامج البريد تحذر من الشهادة

التحذير يعني أن mailcow ما زال يستخدم الشهادة المؤقتة، فراجع docker compose logs acme-mailcow، والأسباب المعتادة هي: السجل A لا يشير إلى السيرفر، أو المنفذ 80 مغلق، أو Reverse Proxy يعترض طلبات التحقق، أو أنك أضفت أسماء في ADDITIONAL_SAN دون سجلات DNS لها.

الخلاصة

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

  • رسالة من سيرفر جديد بلا SPF وDKIM وPTR سوف تصل إلى الرسائل المزعجة أو ترفض، لذلك اضبط السجلات كلها قبل أول رسالة.
  • اختر مزوداً يسمح بالمنفذ 25 الصادر وبتعديل PTR، ويقدم جهازاً افتراضياً كاملاً مثل KVM، مع 6 GiB من الذاكرة على الأقل.
  • ابدأ DMARC بالقيمة p=none وانتقل إلى p=reject بعد أن تراجع التقارير.
  • غير كلمة مرور المدير الافتراضية فوراً وفعل التحقق الثنائي، وحدد Rate limit لكل نطاق.
  • انسخ vmail وcrypt معاً إلى تخزين خارجي يومياً، واختبر الاستعادة على سيرفر مؤقت، وحدث بالسكربت update.sh دون تأجيل.

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

  • سبتمبر 2026: كتابة الدليل واختباره على mailcow-dockerized 2026-09.
  • أكتوبر 2026: مراجعة الدليل على mailcow-dockerized 2026-09: صححنا وصف فحص Spamhaus (يحدث عند تشغيل ال Containers وليس في generate_config.sh، ويحله الخيار SPAMHAUS_DQS_KEY)، وأضفنا jq ومزامنة الوقت NTP وأنواع الأجهزة الافتراضية غير المدعومة إلى المتطلبات، وأضفنا أمثلة حجب المنفذ 25 لدى Hetzner وDigitalOcean وAWS، وقواعد Gmail وYahoo للمرسلين، وسجلات MTA-STS وTLS-RPT الاختيارية، وشرط تطابق MAILDIR_SUB عند الاستعادة، وأن update.sh قد يطلب إعادة تشغيله بعد تحديث _modules.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.