Instalando Discourse por trás de um Reverse Proxy usando instalação recomendada (suportada)

Nesta postagem, mostrarei exatamente como executar o Discourse por trás de um proxy reverso Nginx. Ainda utilizando os métodos de instalação suportados.

Requisitos:

  1. Nome de domínio válido.
  2. Certificado SSL válido.
  3. Entradas DNS válidas apontando para o nome de domínio.
  4. Servidor de e-mail ou provedor SMTP válido e funcionando.
  5. Proxy reverso Nginx funcionando e capacidade de acessar a instância e criar o certificado SSL para uso posterior.
  6. VM ou contêiner LxC que possa executar o Docker.

Para este guia, usarei minha própria instância como exemplo, com todos os recursos funcionando, backups, atualizações, etc. Testado por cerca de 2 semanas.

Especificações da minha VM Discourse:

  • CPU: 4 núcleos
  • RAM: 6 GB
  • Swap: 8 GB (swapfile SSD)
  • Armazenamento: 50 GB (SSD)
  • SO: Ubuntu 22.04.3

Você pode usar o mínimo, mas ao testar. O Discourse basicamente abusa de 2 GB facilmente. O uso inativo é de cerca de 1,48 GB de 6 GB.

OBSERVAÇÃO: Esta instalação usa o proxy reverso para criar os certificados SSL. O Certbot pode ser usado se preferir.

PASSO 1:

Baixe o Ubuntu Server mais recente em Get Ubuntu Server | Download | Ubuntu

PASSO 2:

  1. Instale o Ubuntu Server no template da VM/LxC
    1.1 Certifique-se de que o Ubuntu esteja atualizado com todos os pacotes do servidor.
  2. Use os seguintes comandos para instalar todos os pacotes necessários:
apt update -y && apt upgrade -y && apt wget curl zip git docker.io nginx -y && reboot

PASSO 3:
Instalando o Discourse. Seguindo o Guia para Iniciantes discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub

Conecte-se ao seu servidor via SSH e simplesmente digite o seguinte:

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

Após concluir o acima. Você pode então executar o ./discourse-setup

Siga todas as etapas e insira-as corretamente, pois isso será vital para uma instalação bem-sucedida.
As etapas solicitarão o seguinte; exemplo do guia de configuração:

Deixe a instalação rodar, pode levar um tempo dependendo da sua conexão com a internet e das especificações do servidor. Levou cerca de 5-8 minutos para concluir totalmente a instalação usando minha configuração de VM.

PASSO 4:

Assim que a instalação for concluída, você verá o comando de inicialização que o contêiner Docker está usando e o ID do contêiner gerado (hash).

OBSERVAÇÃO: Como você está atrás de um proxy pela WAN, ele mostrará um erro 502 e, como o contêiner está usando a rede do Docker. Ele será inacessível pela WAN ou LAN, a menos que você se conecte à rede 172.17.0.1/16, que não precisaremos.

Verifique novamente se a instalação foi concluída e se o contêiner Docker está em execução usando:

docker ps

Você deverá obter a seguinte saída.

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

PASSO 5:
Atualizando o arquivo app.yml para se adequar à configuração do proxy reverso.

Use seu editor de texto preferido para abrir /var/discourse/container/app.yml
Substitua/Comente as seguintes linhas: (isso será tratado pelo Nginx local)

  #- “templates/web.ssl.template.yml”
  #- “templates/web.letsencrypt.ssl.template.yml”

Imediatamente após #- "templates/web.letsencrypt.ssl.template.yml" adicione o seguinte:

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

Em seguida, comente a seção expose, pois o Discourse agora usará um websocket, finalmente o Nginx poderá iniciar, pois liberará as portas 80 e 443 necessárias localmente.

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

Agora, para forçar o Discourse a fornecer apenas links com HTTPS, adicione o seguinte na seção env:

# FORCE SSL
DISCOURSE_FORCE_HTTPS: true

Agora, para finalmente colocar as coisas em funcionamento, você precisará reconstruir o aplicativo. Usando o seguinte:

cd /var/discourse
./launcher rebuild app

Deixe isso rodar e concluir. Para verificar se foi bem-sucedido, certifique-se de que o comando docker run esteja sendo exibido ou simplesmente execute docker ps e você verá o contêiner em execução.

PASSO 6:

Habilitando o Nginx e configurando o site padrão para apontar para o contêiner Docker. Permitindo que o proxy reverso acesse o contêiner usando o Nginx local.

Execute o seguinte:

systemctl enable nginx && systemctl start nginx

Para verificar se está em execução. Tente acessar a página de destino padrão do Nginx usando seu navegador e IP local.
EX:

http://10.10.0.4

Você deverá receber uma página de parabéns do Nginx.

PASSO 7:
Atualizando a configuração padrão para o seguinte:
Primeiro, esvazie o arquivo de configuração:

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

Usando seu editor de texto, abra o arquivo de configuração e adicione o seguinte:
OBSERVAÇÃO: Atualize server_name com seu domínio e ssl_certificate, ssl_certificate_key com seu certificado SSL e a localização do arquivo de chave.
O Certbot pode ser usado, mas eu simplesmente rsync meu certificado e chave do meu proxy reverso.

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;
	}
}

Salve o novo arquivo padrão e execute systemctl restart nginx.

PASSO 8:

Abra seu navegador e acesse o domínio do seu fórum https://seudominio.com e você será recebido com a seguinte página.

É isso, tudo pronto. Você pode então seguir as etapas para se registrar e colocar seu fórum/comunidade em funcionamento :).

PASSO ADICIONAL:

Manutenção Pós-Instalação
Sugerimos fortemente que você ative as atualizações automáticas de segurança para o seu SO. No Ubuntu, use dpkg-reconfigure -plow unattended-upgrades

Para suporte, você pode simplesmente usar esta comunidade, para o Nginx local, sinta-se à vontade para pedir ajuda nesta postagem.

10 curtidas

Isto é ótimo. Obrigado.

Uma coisa que eu gostaria de ver como uma melhoria para este guia é poder servir ativos estáticos via nginx.

Atualmente, todas as requisições estáticas estão indo para o worker na configuração acima. Ainda estou tentando descobrir como contornar isso, postarei uma atualização se eu descobrir.

Você pode detalhar quais arquivos estáticos?

Você talvez esteja falando sobre as páginas estáticas 404, 302, 500 do nginx ou páginas estáticas do Discourse?

Eu investiguei um pouco e descobri que o redirecionamento para as páginas 404 funciona. A única página que parece que não consigo configurar é a página de erro 500.

Você pode ser um pouco mais específico para que eu saiba exatamente o que estou procurando. :slight_smile:

Este guia é excelente. Consegui seguir tudo até chegar ao carregamento do site. Recebo um erro de “muitos redirecionamentos”. Quando uso o IP, o Discourse carrega bem, mas não consigo resolver o problema dos redirecionamentos. Tão perto.

Qualquer ajuda seria apreciada.

Obrigado.

Alguém sabe como posso resolver este problema? O site funciona, mas noto esses erros no log de erros do contêiner nginx. Tenho usado um proxy reverso configurado de acordo com estas instruções acima.

Olhando para /etc/nginx/conf.d/discourse.conf no contêiner, vejo

upstream discourse { server 127.0.0.1:3000; }

Deveria ser algo como?:

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

Olhando em /var/log/nginx no contêiner, vejo erros como:

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"

Obrigado!

Você seguiu a etapa 5 corretamente? Parece que você não está usando um socket.

Sim, estou usando um soquete no proxy reverso local fora do contêiner e verifiquei, segui o Passo 5 em 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

Revisei isto: Discourse working with jwilder /nginx proxy & acme-companion

mas não consigo realmente entender nada em relação ao meu problema…