Consegui instalar o Discourse com sucesso no meu servidor, registrar o primeiro usuário e publicar meu primeiro tópico. Portanto, tudo parece estar funcionando do lado do Discourse.
No entanto, para instalar e executar o Discourse, precisei desativar meu daemon Apache httpd. Isso é um grande problema para mim, pois basicamente desliguei todo o meu servidor web, que inclui vários domínios, além de um servidor de conferência Jitsi.
Minha instalação do Jitsi roda como um virtual host separado usando um subdomínio de um dos sites que estou hospedando. Como o Jitsi consegue compartilhar a porta 443 com o restante do tráfego web, gostaria de fazer o mesmo com o Discourse.
Alguém tem um modelo de definição de virtualhost que permita que o tráfego seja direcionado para o Discourse quando chegar no subdomínio do Discourse?
Essencialmente resolvido, no entanto a página inicial parece levar muito tempo para finalizar a requisição, mesmo após a página parecer estar totalmente carregada. (Não tenho certeza se esse é um comportamento normal ou não.)
Discourse
Modifiquei o bloco expose em /var/discourse/containers/app.yml para:
Isso encaminha do localhost para o contêiner Docker. Após fazer isso, é necessário executar um rebuild usando ./launcher rebuild app
Apache2 2.4.43 (Ubuntu)
Adicionei um novo virtual host para o subdomínio: discourse..com.conf em sites-available, que encaminha o tráfego do subdomínio para a porta localhost na qual a instância Docker do Discourse está escutando. A definição do virtual host está abaixo:
<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>
Como não passo muito tempo configurando o Apache, pode haver algumas linhas desnecessárias, ou linhas que poderiam ser adicionadas ou melhoradas. Qualquer feedback é bem-vindo.
Estou rodando o Discourse em vários servidores com o Apache2 como proxy reverso de front-end para um socket Unix, e a configuração funciona perfeitamente (como todos sabemos, é um pouco mais lento que o nginx, que também uso em alguns servidores, mas funciona bem.)
Basicamente, configuro o virtual host assim:
Configuração da porta 80
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName discourse.mygreatwebsite.com
DocumentRoot /website/discourse # muitas vezes não é necessário
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>
Configuração da porta 443:
<VirtualHost *:443>
ServerAdmin webmaster@localhost
ServerName discourse.mygreatwebsite.com
DocumentRoot /website/nginx # na maioria das vezes não é necessário nesta configuração
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>
Observações:
Normalmente, deixo o letsecrypt certbot fazer todo o trabalho relacionado à configuração de todos os certificados SSL e redirecionamentos, etc.
Usamos o endereço IP ao qual o apache2 está vinculado nos arquivos de configuração do apache2.
Sempre configuramos isso (expondo) com sockets Unix no contêiner do Discourse e não expomos nenhuma porta TCP/IP do contêiner nesta configuração.
Abraços e espero que isso adicione algum valor, mesmo no final do jogo.
Se você preferir usar um socket Unix em vez de um proxy direto, é possível fazê-lo (após habilitar o web.socketed.template.yml no seu app.yml) da seguinte forma:
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>
Observe que, provavelmente, você precisará lidar com o SELinux se tentar fazer o Apache ler de /var/discourse dessa maneira. Algo como semanage fcontext -a -t httpd_sys_rw_content_t /var/discourse/shared/standalone/nginx.http.sock, seguido de restorecon /var/discourse/shared/standalone/nginx.http.sock, deve resolver isso.
O Apache possui o excelente mod_md, que pode obter automaticamente seus certificados LetsEncrypt. Recomendo fortemente.