إعداد البريد الإلكتروني الوارد بالتسليم المباشر للمواقع المستضافة ذاتيًا باستخدام Mail-Receiver

حالة استخدام CloudFlare

هذه التعليمات مخصصة لمنتديات Discourse المستضافة ذاتيًا والتي تستخدم وكيل Cloudflare.

عند استخدام وكيل Cloudflare، يمنع هذا وصول أي حركة مرور SMTP (المنفذ 25) إلى الخادم الخاص بك على الإطلاق. يتطلب هذا منك إعداد اسم نطاق فرعي مختلف لكي يعمل مُستقبِل البريد.

على سبيل المثال، إذا كان اسم النطاق الخاص بك هو forums.domain.tld، فستحتاج إلى إنشاء اسم نطاق فرعي جديد، مثل mail.domain.tld.

مع Cloudflare، لديك خطوات إضافية أدناه.

  1. إنشاء سجل A لاسم النطاق الفرعي الجديد. سيستخدم نفس عنوان IP الخاص بـ forums.domain.tld الخاص بك.
  2. إنشاء سجل MX لاسم النطاق الفرعي الجديد كما هو موضح في التعليمات الرئيسية.

اتبع مجموعات التعليمات الرئيسية مع هذا التغيير الطفيف. سيعمل بشكل جيد تمامًا مع إيقاف تشغيل أمان TLS.

إذا كنت ترغب في تشغيل أمان TLS، فسيتطلب هذا عملًا إضافيًا.

نظرة عامة على إعداد TLS

ستقوم هذه التعليمات بتثبيت Certbot وإضافة مكون إضافي لـ Certbot الخاص بـ CloudFlare. ستحصل الأوامر على شهادات LetsEncrypt في وضعية الاستقلال عبر عملية شهادة DNS. بمجرد توفر الشهادات، يتم نسخها إلى منطقة البريد المُستقبِل المشتركة ليستخدمها الحاوية. يجب علينا استخدام نموذج DNS، نظرًا لأن Discourse لديه بالفعل المنفذ 80 مستخدماً.

تحدي DNS

بدلاً من إثبات ملكية النطاق عبر HTTP، يثبت Certbot ذلك عن طريق إنشاء سجل TXT في نظام أسماء النطاقات (DNS) الخاص بك. نظرًا لأن نظام أسماء النطاقات الخاص بك هو Cloudflare، يمكن أتمتة هذا بالكامل باستخدام رمز وصول API الخاص بـ Cloudflare — لا حاجة للمنفذ 80، ولا حاجة لإيقاف تشغيل خادم الويب.

كيف يعمل

Certbot → ينشئ سجل TXT باسم _acme-challenge.mail.lotuselan.net في Cloudflare
Let's Encrypt → يبحث عن سجل TXT هذا → يتحقق → يصدر الشهادة
Certbot → يحذف سجل TXT

يتم كل هذا على الخادم الأساسي الخاص بك، وليس داخل حاوية Discourse.

الإعداد

1 — تثبيت cerbot والمكوّن الإضافي لـ Cloudflare Certbot:

apt install certbot python3-certbot-dns-cloudflare -y

2 — إنشاء رمز وصول API لـ Cloudflare:

  1. انتقل إلى Cloudflare ← ملفي الشخصي ← رموز وصول API ← إنشاء رمز
  2. استخدم قالب “تحرير DNS للمنطقة”
  3. الأذونات: المنطقة ← DNS ← تحرير
  4. موارد المنطقة: تضمين ← منطقة محددة ← lotuselan.net
  5. قيود IP: قم بالإعداد للسماح فقط من عنوان IP الخاص بالخادم الخاص بك
  6. انسخ الرمز

3 — حفظ الرمز في ملف بيانات الاعتماد:

mkdir -p /etc/letsencrypt/cloudflare
nano /etc/letsencrypt/cloudflare/credentials.ini

ألصق:

dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN

قم بتأمين الملف:

chmod 600 /etc/letsencrypt/cloudflare/credentials.ini

4 — طلب الشهادة:

قم بتحديث الأمر التالي بعنوان البريد الإلكتروني للمسؤول واسم النطاق الخاص بك.

certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
  --non-interactive \
  --agree-tos \
  --email youremailadress@domain.tld \
  -d mail.domain.tld

في النتائج، يجب أن يكون هناك بيان يقول:

Certbot has set up a scheduled task to automatically renew this certificate in the background.

سيقوم Certbot بإعداد مهمة cron للتحقق من انتهاء صلاحية الشهادة مرتين في اليوم. سيقوم بتجديد الشهادات عندما تكون ضمن 30 يومًا من انتهاء صلاحيتها. يمكنك التحقق من ذلك عن طريق:

# التحقق مما إذا كان مؤقت systemd نشطًا (معظم أنظمة Ubuntu الحديثة)
systemctl status certbot.timer

# أو التحقق مما إذا تمت إضافة مهمة cron
cat /etc/cron.d/certbot

لديك الآن شهادات TLS على الخادم الخاص بك لاسم نطاق مُستقبِل البريد الجديد. إنها ليست في مكان يمكن استخدامه.

5 — إعداد برنامج نصي للنشر لنقل الملفات
نظرًا لأن certbot يقوم بالتجديد التلقائي، فأنت تحتاج فقط إلى البرنامج النصي الخاص بك للتعامل مع أجزاء Discourse الخاصة - نسخ الشهادات المجددة وإعادة بناء مُستقبِل البريد. يمكنك تبسيط البرنامج النصي بشكل كبير باستخدام خطاف النشر (deploy hook) المدمج في certbot، والذي يتم تشغيله تلقائيًا بعد التجديد الناجح.

إنشاء ملف خطاف النشر:

nano /etc/letsencrypt/renewal-hooks/deploy/mail-receiver-deploy.sh
chmod +x /etc/letsencrypt/renewal-hooks/deploy/mail-receiver-deploy.sh

ألصق هذا:

#!/bin/bash
DOMAIN="mail.domain.tld"
DISCOURSE_DIR="/var/discourse"
CERT_SRC="/etc/letsencrypt/live/${DOMAIN}"
CERT_DEST_1="${DISCOURSE_DIR}/shared/mail-receiver/letsencrypt/${DOMAIN}"
CERT_DEST_2="${DISCOURSE_DIR}/shared/mail-receiver/letsencrypt/${DOMAIN}_ecc"
ADMIN_EMAIL="admin email address"
LOG_FILE="/var/log/mail-cert-renewal.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log "=== Certbot deploy hook triggered for ${DOMAIN} ==="

# نسخ الشهادات (استخدم -L لحل الروابط الرمزية)
for DEST in "$CERT_DEST_1" "$CERT_DEST_2"; do
    mkdir -p "$DEST"
    cp -L "${CERT_SRC}/fullchain.pem" "${DEST}/fullchain.pem"
    cp -L "${CERT_SRC}/privkey.pem"   "${DEST}/privkey.pem"
    cp -L "${CERT_SRC}/cert.pem"      "${DEST}/cert.pem"
    cp -L "${CERT_SRC}/chain.pem"     "${DEST}/chain.pem"
    chmod 644 "${DEST}/fullchain.pem" "${DEST}/cert.pem" "${DEST}/chain.pem"
    chmod 600 "${DEST}/privkey.pem"
    log "Certs copied to ${DEST}"
done

# إعادة بناء مُستقبِل البريد
cd "$DISCOURSE_DIR" || { echo "Cannot cd to ${DISCOURSE_DIR}" | mail -s "[FAILURE] Mail cert deploy hook failed" "$ADMIN_EMAIL"; exit 1; }
log "Rebuilding mail-receiver..."
if ./launcher rebuild mail-receiver >> "$LOG_FILE" 2>&1; then
    log "mail-receiver rebuilt successfully"
else
    log "ERROR: rebuild failed"
    echo "mail-receiver rebuild failed after cert renewal. Check ${LOG_FILE}" | \
        mail -s "[FAILURE] Mail cert deploy hook failed" "$ADMIN_EMAIL"
    exit 1
fi

log "=== Deploy hook completed successfully ==="

لا حاجة إلى مهمة cron يدوية على الإطلاق — يقوم certbot بتنظيم العملية بأكملها. يتم تشغيل خطاف النشر فقط عند حدوث تجديد فعلي، لذلك لن يخضع مُستقبِل البريد الخاص بك لإعادة بناء غير ضرورية في الأيام التي يتحقق فيها certbot ولكنه لا يقوم بالتجديد.

لاختبار خطاف التجديد، قم بتشغيل ما يلي:

bash /etc/letsencrypt/renewal-hooks/deploy/mail-receiver-deploy.sh

إذا تم إعداد كل شيء بشكل صحيح، فسيقوم بما يلي:
← نسخ الشهادات إلى أدلة Discourse
← إعادة بناء مُستقبِل البريد
← تسجيل كل شيء

6 — إعداد TLS في mail-receiver.yml