تثبيت Discourse خلف وكيل عكسي باستخدام التثبيت الموصى به (الداعم)

في هذا المنشور، سأوضح لك بالضبط كيفية تشغيل discourse خلف وكيل عكسي nginx. مع الاستمرار في استخدام طرق التثبيت المدعومة.

المتطلبات:

  1. اسم نطاق صالح.
  2. شهادة SSL صالحة.
  3. إدخالات DNS صالحة تشير إلى اسم النطاق.
  4. خادم بريد إلكتروني صالح يعمل أو مزود SMTP.
  5. وكيل عكسي Nginx يعمل والقدرة على الوصول إلى المثيل وإنشاء شهادة SSL للاستخدام لاحقًا.
  6. جهاز افتراضي أو حاوية LxC يمكنها تشغيل docker.

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

مواصفات جهاز Discourse الافتراضي الخاص بي:

  • وحدة المعالجة المركزية: 4 أنوية
  • ذاكرة الوصول العشوائي: 6 جيجابايت
  • التبديل: 8 جيجابايت (ملف تبديل SSD)
  • التخزين: 50 جيجابايت (SSD)
  • نظام التشغيل: Ubuntu 22.04.3

يمكنك استخدام الحد الأدنى ولكن عند الاختبار. يستغل Discourse بسهولة 2 جيجابايت. الاستخدام غير النشط حوالي 1.48 جيجابايت من 6 جيجابايت.

ملاحظة: يستخدم هذا التثبيت الوكيل العكسي لإنشاء شهادات SSL. يمكن استخدام certbot إذا كنت تفضل ذلك.

الخطوة 1:

قم بتنزيل أحدث إصدار من Ubuntu Server من Get Ubuntu Server | Download | Ubuntu

الخطوة 2:

  1. قم بتثبيت Ubuntu Server على قالب الجهاز الافتراضي/LxC
    1.1 تأكد من أن Ubuntu محدث بجميع حزم الخادم.
  2. استخدم الأوامر التالية لتثبيت جميع الحزم المطلوبة:
apt update -y && apt upgrade -y && apt wget curl zip git docker.io nginx -y && reboot

الخطوة 3:
تثبيت Discourse. اتبع دليل المبتدئين discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub

قم بتسجيل الدخول إلى الخادم الخاص بك عبر SSH وأدخل ببساطة ما يلي:

sudo -s
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
chmod 700 containers

بعد إكمال ما سبق. يمكنك بعد ذلك تشغيل ./discourse-setup

اتبع جميع الخطوات وأدخلها بشكل صحيح، حيث سيكون هذا أمرًا حيويًا للتثبيت الناجح.
ستطلب الخطوات ما يلي؛ مثال من دليل الإعداد:

دع التثبيت يعمل، قد يستغرق الأمر بعض الوقت اعتمادًا على اتصالك بالإنترنت ومواصفات الخادم. استغرق الأمر حوالي 5-8 دقائق لإكمال التثبيت بالكامل باستخدام إعداد الجهاز الافتراضي الخاص بي.

الخطوة 4:

بمجرد اكتمال التثبيت، سترى أمر البدء الذي يستخدمه حاوية docker ومعرف الحاوية الذي تم إنشاؤه (التجزئة).

ملاحظة: نظرًا لأنك خلف وكيل عبر WAN، فسوف يعرض لك خطأ 502 ولأن الحاوية تستخدم شبكة docker. لن يكون من الممكن الوصول إليها عبر WAN أو LAN، ما لم تقم بالاتصال بشبكة 172.17.0.1/16، والتي لن نحتاجها.

تحقق مرة أخرى من اكتمال التثبيت وأن حاوية docker قيد التشغيل باستخدام:

docker ps

يجب أن تحصل على المخرجات التالية.

CONTAINER ID   IMAGE                 COMMAND        CREATED      STATUS       PORTS     NAMES
XXXXXX   local_discourse/app   \"/sbin/boot\"   6 days ago   Up 7 hours             app

الخطوة 5:
تحديث ملف app.yml ليناسب تكوين الوكيل العكسي.

استخدم محرر النصوص المفضل لديك لفتح /var/discourse/container/app.yml
استبدل/علّق الأسطر التالية: (سيتم التعامل مع هذا بواسطة Nginx المحلي)

  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

مباشرة بعد #- "templates/web.letsencrypt.ssl.template.yml" أضف ما يلي:

- "templates/web.socketed.template.yml"

ثم علّق قسم الكشف لأن Discourse سيستخدم الآن WebSocket، وأخيرًا سيكون Nginx قادرًا على البدء لأنه سيحرر المنافذ 80 و 443 المطلوبة محليًا.

#expose:
# - "80:80" # http
# - "443:443" # https

الآن لإجبار Discourse على توفير الروابط باستخدام HTTPS فقط، أضف ما يلي في قسم env:

# FORCE SSL
DISCOURSE_FORCE_HTTPS: true

الآن للحصول على الأمور جارية أخيرًا، ستحتاج إلى إعادة بناء التطبيق. باستخدام ما يلي:

cd /var/discourse
./launcher rebuild app

دع ذلك يعمل ويكتمل. للتحقق مما إذا كان ناجحًا، تأكد من أن أمر تشغيل docker معروض أو ببساطة قم بتشغيل docker ps وسترى الحاوية قيد التشغيل.

الخطوة 6:

تمكين Nginx وتكوين الموقع الافتراضي للإشارة إلى حاوية docker. السماح للوكيل العكسي بالوصول إلى الحاوية باستخدام nginx المحلي.

قم بتشغيل ما يلي:

systemctl enable nginx && systemctl start nginx

للتحقق مما إذا كان قيد التشغيل. حاول الوصول إلى صفحة الهبوط الافتراضية لـ nginx باستخدام متصفحك وعنوان IP المحلي.
مثال:

http://10.10.0.4

يجب أن تحصل على صفحة تهنئة من Nginx.

الخطوة 7:
تحديث التكوين الافتراضي إلى ما يلي:
أولاً، قم بإفراغ ملف التكوين:

echo "" > /etc/nginx/sites-available/default

استخدم محرر النصوص الخاص بك لفتح ملف التكوين وإضافة ما يلي:
ملاحظة: قم بتحديث server_name باسم النطاق الخاص بك و ssl_certificate و ssl_certificate_key بموقع شهادة SSL وملف المفتاح الخاص بك.
يمكن استخدام Certbot ولكنني ببساطة أقوم بنسخ شهادتي ومفتاحي من الوكيل العكسي.

server {
    listen 80; listen [::]:80;
    server_name add.yourdomain.com;
    server_tokens off;
    return 301 https://$host$request_uri;
}
# Default server configuration
#
server {
	# SSL configuration
	#
	server_tokens off;
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;

    server_name add.yourdomain.com;
	ssl_certificate /etc/ssl/certs/your_ssl_cert.bundle;
	ssl_certificate_key /etc/ssl/private/your_ssl_cert.key;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
	ssl_prefer_server_ciphers on;
	location / {
		proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock;
		proxy_set_header Host $http_host;
		proxy_http_version 1.1;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header X-Real-IP $remote_addr;
	}
}

احفظ الملف الافتراضي الجديد وقم بتشغيل systemctl restart nginx.

الخطوة 8:

افتح متصفحك وانتقل إلى نطاق المنتدى الخاص بك https://somedomain.com وستتم الترحيب بك بالصفحة التالية.

هذا كل شيء، تم الانتهاء. يمكنك بعد ذلك اتباع الخطوات للتسجيل والحصول على منتدى/مجتمع خاص بك :).

خطوة إضافية:

الصيانة بعد التثبيت
نقترح بشدة تشغيل التحديثات الأمنية التلقائية لنظام التشغيل الخاص بك. في Ubuntu استخدم dpkg-reconfigure -plow unattended-upgrades

للحصول على الدعم، يمكنك ببساطة استخدام هذا المجتمع، بالنسبة لـ Nginx المحلي، لا تتردد في طلب المساعدة في هذا المنشور.

10 إعجابات

هذا رائع. شكرًا لك.

أحد الأشياء التي أود رؤيتها كتحسين لهذا الدليل هو القدرة على تقديم الأصول الثابتة عبر nginx.

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

هل يمكنك التوسع في ماهية الملفات الثابتة؟

هل تتحدث ربما عن الصفحات الثابتة 404، 302، 500 من nginx أو الصفحات الثابتة من Discourse؟

لقد بحثت في الأمر قليلاً ووجدت أن إعادة التوجيه لصفحات 404 تعمل. الصفحة الوحيدة التي لا يبدو أنني أستطيع تعيينها هي صفحة خطأ 500.

هل يمكنك أن تكون أكثر تحديدًا حتى أعرف بالضبط ما الذي أبحث عنه. :slight_smile:

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

أي مساعدة ستكون موضع تقدير.

شكرًا.

هل يعرف أحد كيف يمكنني حل هذه المشكلة؟ الموقع يعمل، لكنني ألاحظ هذه الأخطاء في سجل أخطاء حاوية nginx. لقد كنت أستخدم وكيلًا عكسيًا تم إعداده وفقًا لهذه التعليمات أعلاه.

بالنظر إلى /etc/nginx/conf.d/discourse.conf في الحاوية، أرى

upstream discourse { server 127.0.0.1:3000; }

هل يجب أن يكون شيئًا كهذا؟

upstream discourse { http://unix:/var/discourse/shared/standalone/nginx.http.sock; }

بالنظر إلى /var/log/nginx في الحاوية، أرى أخطاء مثل:

2025/02/09 21:00:21 [error] 69#69: *1 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xxx.xxx, server: _, request: "POST /message-bus/b39980c2387e4750bc1e320cb6195424/poll?dlp=t HTTP/1.1", upstream: "http://127.0.0.1:3000/message-bus/b39980c2387e4750bc1e320cb6195424/poll?dlp=t", host: "discourse.xxxx.com"

2025/02/09 21:00:23 [error] 67#67: *3 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xx.xxx, server: _, request: "GET /chat/api/me/channels HTTP/1.1", upstream: "http://127.0.0.1:3000/chat/api/me/channels", host: "discourse.xxxx.com"

2025/02/09 21:00:23 [error] 70#70: *5 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xx.xxx, server: _, request: "POST /message-bus/d95b6999d26242f28f4875732b195440/poll HTTP/1.1", upstream: "http://127.0.0.1:3000/message-bus/d95b6999d26242f28f4875732b195440/poll", host: "discourse.xxxx.com"

شكرا لك!

هل اتبعت الخطوة 5 بشكل صحيح؟ يبدو أنك لا تستخدم مقبسًا.

نعم، أنا أستخدم مقبسًا على وكيل الاسترجاع المحلي خارج الحاوية، وتحقق، لقد اتبعت الخطوة 5 في app.yml.

/var/discourse/containers# grep web.socketed.template.yml app.yml
  - "templates/web.socketed.template.yml"

/var/discourse/containers# grep templates/web.ssl.template.yml app.yml
  #  - "templates/web.ssl.template.yml"

/var/discourse/containers# grep templates/web.letsencrypt.ssl.template.yml app.yml
  #  - "templates/web.letsencrypt.ssl.template.yml"

/var/discourse/containers# grep http app.yml

#  - "80:80"   # http
#  - "443:443" # https

/var/discourse/containers# grep DISCOURSE_FORCE_HTTPS app.yml
DISCOURSE_FORCE_HTTPS: true
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  ## Uncomment the next line to enable the IPv6 listener
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
  ## Uncomment these two lines if you wish to add Lets Encrypt (https)
  #  - "templates/web.ssl.template.yml"
  #  - "templates/web.letsencrypt.ssl.template.yml"
  - "templates/web.socketed.template.yml"
## which TCP/IP ports should this container expose?
## If you want Discourse to share a port with another webserver like Apache or nginx,
## see https://meta.discourse.org/t/17247 for details
#expose:
#  - "80:80"   # http
#  - "443:443" # https

لقد راجعت هذا: Discourse working with jwilder /nginx proxy & acme-companion

لكنني لا أستطيع حقًا فهم أي شيء منه فيما يتعلق بمشكلتي…