Как запустить Discourse в качестве виртуального хоста Apache

Мне удалось успешно установить Discourse на свой сервер, зарегистрироваться как первый пользователь и создать первую тему. Похоже, что всё на стороне Discourse работает.

Однако для установки и запуска Discourse мне пришлось отключить демон Apache httpd. Это серьёзная проблема, так как я фактически остановил весь свой веб-сервер, на котором размещены несколько доменов, а также сервер конференций Jitsi.

Моя установка Jitsi работает как отдельный виртуальный хост, используя поддомен одного из размещаемых мной сайтов. Поскольку Jitsi может совместно использовать порт 443 с другим веб-трафиком, я хотел бы сделать то же самое с Discourse.

У кого-нибудь есть шаблон определения виртуального хоста, который позволяет перенаправлять трафик на Discourse, когда запросы поступают на поддомен Discourse?

Да, здесь есть руководства на Meta, в которых обсуждается запуск 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.<myDomain>.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 в качестве обратного прокси-сервера на уровне фронтенда, работающего через unix-сокет, и конфигурация работает отлично (как мы все знаем, она немного медленнее, чем nginx, который я также использую на некоторых серверах, но работает без проблем).

В основном я настраиваю виртуальный хост следующим образом:

Конфигурация порта 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-сокеты в контейнере 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, который может автоматически получать для вас сертификаты LetsEncrypt. Настоятельно рекомендую его.