كيفية تشغيل Discourse كـ Apache VirtualHost

تمكنت بنجاح من تثبيت Discourse على خادمي، وتسجيلي كمستخدم أول، ونشر موضوعي الأول. لذا يبدو أن كل شيء يعمل بشكل صحيح من جانب Discourse.

ومع ذلك، ولتثبيت وتشغيل Discourse، اضطررت إلى تعطيل خدمة Apache httpd. وهذا يمثل مشكلة كبيرة بالنسبة لي، حيث أنني أغلقت فعليًا خادم الويب بالكامل، والذي يتضمن مجموعة من النطاقات بالإضافة إلى خادم مؤتمرات Jitsi.

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

هل لدى أحدكم تعريف استضافة افتراضية (template virtualhost) يسمح بتحويل الحركة إلى Discourse عندما تصل عبر نطاقه الفرعي؟

نعم، هناك أدلة هنا على ميتا تناقش تشغيل Discourse جنبًا إلى جنب مع مواقع أخرى.

أنا واثق من أنه إذا استخدمت البحث، يمكنك العثور عليها.

تم الحل إلى حد كبير، ومع ذلك يبدو أن الصفحة الرئيسية تستغرق وقتًا طويلاً لإنهاء الطلب، حتى بعد اكتمال تحميل الصفحة بالكامل. (لست متأكدًا مما إذا كان هذا سلوكًا طبيعيًا أم لا.)

Discourse
عدّلت كتلة expose في /var/discourse/containers/app.yml لتصبح:

expose:
  - "127.0.0.1:8000:80"   # http
  - "127.0.0.1:8443:443"  # https

وهو ما يقوم بإعادة التوجيه من localhost إلى حاوية Docker. بعد القيام بذلك، يلزم إعادة البناء باستخدام ./launcher rebuild app

Apache2 2.4.43 (Ubuntu)
أضفت استضافة افتراضية جديدة للنطاق الفرعي: discourse..com.conf في sites-available تقوم بإعادة توجيه حركة مرور النطاق الفرعي إلى منفذ localhost الذي تستمع إليه حاوية Discourse Docker. تعريف الاستضافة الافتراضية هو التالي:

<VirtualHost *:80>
    ServerName discourse.<myDomain>.com
    Redirect permanent / https://discourse.<myDomain>.com/
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

<VirtualHost *:443>

  ServerName discourse.<myDomain>.com

  SSLProtocol TLSv1 TLSv1.1 TLSv1.2
  SSLEngine on
  SSLProxyEngine on
  SSLCertificateFile /etc/letsencrypt/live/<myDomain>.com/cert.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/<myDomain>.com/privkey.pem
  SSLCACertificateFile /etc/letsencrypt/live/<myDomain>.com/chain.pem
  SSLCipherSuite "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED"
  SSLHonorCipherOrder on
  Header set Strict-Transport-Security "max-age=31536000"

  <Location />
    Order allow,deny
    Allow from all
    Require all granted
  </Location>

  ProxyPreserveHost on
  ProxyRequests Off
  RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
  RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
  ProxyPass / https://127.0.0.1:8443/
  ProxyPassReverse / https://127.0.0.1:8443/

</VirtualHost>

بما أنني لا أقضي وقتًا طويلاً في إعداد Apache، فقد تكون هناك بعض الأسطر غير الضرورية، أو أسطر يمكن إضافتها أو تحسينها. أي ملاحظات ترحيب بها.

مرحبًا @Nap،

سعيد جدًا بأنك نجحت في حل مشكلتك.

أنا أدير Discourse على عدد من الخوادم باستخدام Apache2 كواجهة أمامية لعكس البروكسي (reverse proxy) إلى منفذ Unix socket، ويعمل التكوين بشكل ممتاز (كما نعلم جميعًا، إنه أبطأ قليلًا من nginx، الذي أديره أيضًا على بعض الخوادم، لكنه يعمل بشكل جيد).

بشكل أساسي، أقوم بتكوين الـ virtual host على النحو التالي:

إعدادات المنفذ 80:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName  discourse.mygreatwebsite.com
    DocumentRoot /website/discourse  # غالبًا غير ضروري

    RewriteEngine On
    ProxyPreserveHost On
    ProxyRequests Off
    ErrorLog /var/log/apache2/discourse.error.log
    LogLevel warn
    CustomLog /var/log/apache2/discourse.access.log combined

    RewriteCond %{SERVER_NAME} =discourse.mygreatwebsite.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

إعدادات المنفذ 443:

<VirtualHost *:443>
  ServerAdmin webmaster@localhost
  ServerName  discourse.mygreatwebsite.com
  DocumentRoot /website/nginx  # في الغالب غير مطلوب في هذا التكوين
  
  SSLProxyEngine on
  RewriteEngine On
  ProxyPreserveHost On
  ProxyRequests Off
  RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
  RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
  
  ProxyPass / unix:/var/discourse/shared/socket-only/discourse.http.sock|http://my.ip.address.here/
  ProxyPassReverse  / unix:/var/discourse/shared/socket-only/discourse.http.sock|http://my.ip.address.here/
  ErrorLog /var/log/apache2/discourse-ssl.error.log
  LogLevel warn
  CustomLog /var/log/apache2/discourse-ssl.access.log combined

  Include /etc/letsencrypt/options-ssl-apache.conf
  SSLCertificateFile /etc/letsencrypt/live/discourse.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/discourse.com/privkey.pem
</VirtualHost>

ملاحظات:

  1. عادةً، أترك أداة letsecrypt certbot تقوم بكل العمل المتعلق بإعداد جميع شهادات SSL وإعادة التوجيه، وما إلى ذلك.

  2. نستخدم عنوان IP الذي يرتبط به apache2 في ملفات تكوين apache2.

  3. نقوم دائمًا بتكوين هذا (التعريض) باستخدام منافذ Unix sockets في حاوية discourse، ولا نقوم بتعريض أي منافذ TCP/IP للحاوية في هذا التكوين.

أهلاً وسهلاً، وآمل أن يضيف هذا بعض القيمة، حتى لو كان ذلك متأخرًا في اللعبة.

إضافتان سريعتان:

  1. إذا كنت ترغب في استخدام وصلة Unix بدلاً من وكيل مباشر، فيمكنك فعل ذلك (بعد تمكين web.socketed.template.yml في ملف app.yml) على النحو التالي:
  ProxyPreserveHost On
  ProxyRequests Off
  RequestHeader set X-Forwarded-Proto https
  RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
  <Location />
    ProxyPass unix:/var/discourse/shared/standalone/nginx.http.sock|http://localhost/
    ProxyPassReverse unix:/var/discourse/shared/standalone/nginx.http.sock|http://localhost/
  </Location>

لاحظ أنه قد تحتاج إلى التعامل مع SELinux إذا حاولت أن يقوم Apache بقراءة البيانات من /var/discourse بهذه الطريقة. شيء مثل semanage fcontext -a -t httpd_sys_rw_content_t /var/discourse/shared/standalone/nginx.http.sock متبوعًا بـ restorecon /var/discourse/shared/standalone/nginx.http.sock يجب أن يحل المشكلة.

  1. يحتوي Apache على mod_md الرائع الذي يمكنه الحصول على شهادات Let’s Encrypt لك تلقائيًا. أنصح به بشدة.