Discourse + Let's Encrypt مع أسماء نطاقات متعددة

عند ترحيل (عبر نسخة احتياطية) نظام Discourse من اسم نطاق (hostname) إلى آخر، قد يرغب المسؤول في الاحتفاظ باسم النطاق القديم ولكن إعادة توجيه طلبات خادم الويب لاستخدام الاسم الرسمي الجديد، على سبيل المثال:

https://old.example.org/t/my-great-topic/12345 :arrow_heading_down:
https://new.example.org/t/my-great-topic/12345

للأسف، لا يكون ذلك سهلاً بمجرد تغيير سجل CNAME أو A في نظام أسماء النطاقات (DNS)؛ حيث سيُنتج عميل المتصفح خطأً أو تحذيرًا لأن اسم النطاق لا يطابق الشهادة المُنشأة من قبل تثبيت Discourse عبر Let’s Encrypt.

في حالة التثبيت اليدوي لخادم الويب، سأستخدم أداة certbot لـ إنشاء شهادة بأسماء متعددة تُعيّن لها. ومع ذلك، فإن إعدادات Discourse تُمرّر اسم نطاق Discourse (فقط) إلى Let’s Encrypt، ولا يوجد مفهوم واضح في إعدادات Discourse للأسماء البديلة (aliases).

هل قام أي شخص بإعداد مثل هذا الترتيب، أم لديه فكرة حول أفضل طريقة لتحقيق ذلك؟ أتخيل أن الأمر سيتضمن بعض التعديلات على قوالب SSL و Let’s Encrypt.

ليس مخصصًا لـ Discourse، ولكن عندما أحتاج إلى إعادة التوجيه عبر HTTPS، أقوم بإعادة توجيه كل شيء. وهذا يعني وجود خادم يقوم بإعادة التوجيه من العنوان القديم إلى العنوان الجديد. بعض خيارات الاستضافة تتولى هذا الأمر في الخلفية، ويُشار إليها أحيانًا بـ “إعادة توجيه النطاق” أو خدمة “التحويل”.

لم أعد أفكر في هذا الأمر بعد الآن، لأن كل محاولة أخرى كانت محفوفة بالمشاكل. :thinking:

لن يستجيب Discourse إلا لاسم مضيف واحد. إذا كنت تريد أكثر من اسم مضيف — حيث أن حالتك الاستخدامية، المتمثلة في دعم اسم المضيف السابق، هي الأكثر شيوعًا — فستحتاج إلى إعادة توجيه أحدهما إلى الآخر.

أوصي بذلك خارج نطاق Discourse. فقط قم بإنشاء تكوين nginx سيحمل شهادة خاصة به، ويحتوي على server_name لاسم المضيف القديم، ويعيد توجيه كل شيء إلى اسم المضيف الجديد.

في الواقع، إذا كنت تستخدم تثبيتًا قائمًا على Docker بنسخة واحدة لكل خادم، فسيستجيب بشكل صحيح لأي عدد من إدخالات DNS (حيث يستمع nginx إلى المنفذ 80 والمنفذ 443 لجميع أسماء النطاقات)، ويعيد كتابة عنوان URL بشكل صحيح إلى اسم النطاق “الجديد” المعيارى دون مشاكل. هذا الجزء يعمل بشكل ممتاز وسلس. (يمكن للأشخاص الراغبين في تجربة ذلك إضافة اسم نطاق وهمي إلى ملف localhost على جهازهم وتوجيهه إلى عنوان IP لموقع Discourse المفضل لديهم.)

المشكلة الوحيدة التي أواجهها هي تحذير SSL لأن استجابة إعادة الكتابة من nginx تأتي من https://old.example.org/foo وترسل إعادة توجيه HTTP 302 إلى عنوان URL الجديد.

أفضل عدم الاضطرار إلى صيانة خادم ويب منفصل فقط لتنفيذ قاعدة إعادة كتابة، إذا أمكن. :slight_smile:

لا تحتاج إلى ذلك، فأنت فقط بحاجة إلى قسم server إضافي في إعداداتك.

ربما تنظر إلى Set up Let’s Encrypt with multiple domains / redirects

تحديث: تم تكوين اسم النطاق الثانوي بنجاح في التثبيت المستقل، وتم إصدار شهادة Let’s Encrypt للتعامل مع الأسماء القديمة والجديدة.

المتطلبات المسبقة: لم أقوم بعد بتغيير إعدادات DNS لتوجيه المستخدمين إلى الموقع الجديد؛ أردت التأكد من عمل كل شيء مسبقًا. لذلك كنت أستخدم إدخال localhost على جهاز الاختبار الخاص بي. وهذا يعني أنني لم أستطع إجراء التحقق العادي من Let’s Encrypt، واضطررت لاستخدام طريقة “DNS” في acme.sh التي لا يُنصح بها عمومًا لأنها لا تدعم التجديد التلقائي. وهذا مقبول بالنسبة لي؛ لأنني سأقوم بالتبديل خلال مدة 30 يومًا لشهادة “الأولى” (الشهادة المصدرة حديثًا والتي تغطي اسمين).

  1. في ملف web_only.yml (قد تستخدم app.yml) تحت قسم hooks:، وقبل الإضافات، أضف ما يلي:
  after_ssl:
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d second-domain.com --keylength"
  1. في إعدادات DNS، أنشئ سجل TXT مؤقت/وهمي لـ _acme-challenge.old.example.org بمدة صلاحية (TTL) مدتها 5 دقائق (يمكنك جعلها أقصر إذا أردت)، وانتظر حتى يتم نشرها لتتمكن من إجراء التغيير بسرعة باستخدام مفتاح التحقق من acme.sh (Let’s Encrypt).

  2. أوقف الموقع وقم بإجراء تحقق من التصحيح (اختباري) لجعل النظام يدرك أن الإدخال الجديد له مدة صلاحية قصيرة:

./launcher enter app
sv stop nginx
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf
LE_WORKING_DIR=/shared/letsencrypt DEBUG=1 /shared/letsencrypt/acme.sh --issue -d new.example.org -d old.example.org -k 4096 -w /var/www/discourse/public --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
  1. قم بتنفيذ الطلب فعليًا هذه المرة دون إعداد التصحيح. سيظهر لك تحذير يحتوي على القيمة التي يجب استخدامها في DNS للإدخال الذي أنشأته في الخطوة 2:
LE_WORKING_DIR=/shared/letsencrypt /shared/letsencrypt/acme.sh --issue -d new.example.org -d old.example.org -k 4096 -w /var/www/discourse/public --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
  1. قم بتحديث DNS ثم انتظر 5 دقائق. نعم، يجب أن تنتظر طوال الوقت لتتجنب قيود Let’s Encrypt.

  2. قم بتشغيل أمر مشابه للأمر الأخير ولكن في وضع renew:

LE_WORKING_DIR=/shared/letsencrypt /shared/letsencrypt/acme.sh --issue -d new.example.org -d old.example.org -k 4096 -w /var/www/discourse/public --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force --renew
  1. يجب أن تحصل على تأكيد. قم بتشغيل الأمر التالي لتنظيف الأمور ووضع الشهادة الجديدة في مكانها:
LE_WORKING_DIR=/shared/letsencrypt /shared/letsencrypt/acme.sh --installcert -d new.example.org -d old.example.org --fullchainpath /shared/ssl/new.example.org.cer --keypath /shared/ssl/new.example.org.key --reloadcmd "sv reload nginx"
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop
exit
  1. الخطوة الأخيرة الآن بعد خروجك من launcher:
rm -rf /var/discourse/shared/standalone/ssl
rm -rf /var/discourse/shared/standalone/letsencrypt
./launcher rebuild app

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

شكرًا للأشخاص الذين وجهوني في الاتجاه الصحيح!

هذا تطبيق مثالي لقاعدة Cloudflare - لا يلزم أي تكوين للخادم. ما عليك سوى إرسال معلمات URL نفسها إلى النطاق الجديد.

يجب تمكين السحابة البرتقالية للنطاق القديم.

نعم، يمكن لوضع وكيل عكسي مثل كلاودفلر (أو أي وكيل عكسي تفضله أمام موقع ديسكورش) تجاوز المشكلة من خلال تطبيق قواعد إعادة الكتابة “على مستوى أعلى”. في هذه الحالة، لم تكن كلاودفلر خيارًا لأسباب أمنية وأخلاقية. :slight_smile:

(انظر ما ورد أعلاه للحل المستقل.)