Installation de Discourse derrière un reverse proxy en utilisant l'installation recommandée (supportée)

Dans ce post, je vais vous montrer exactement comment exécuter Discourse derrière un proxy inverse Nginx. Tout en utilisant toujours les méthodes d’installation prises en charge.

Exigences :

  1. Nom de domaine valide.
  2. Certificat SSL valide.
  3. Entrées DNS valides pointant vers le nom de domaine.
  4. Serveur d’e-mails valide et fonctionnel ou fournisseur SMTP.
  5. Proxy inverse Nginx fonctionnel et capacité à atteindre l’instance et à créer le certificat SSL pour une utilisation ultérieure.
  6. VM ou conteneur LxC capable d’exécuter Docker.

Pour ce guide, j’utiliserai ma propre instance comme exemple, avec toutes les fonctionnalités opérationnelles, les sauvegardes, les mises à niveau, etc. Testé pendant environ 2 semaines.

Mes spécifications de VM Discourse :

  • CPU : 4 cœurs
  • RAM : 6 Go
  • Swap : 8 Go (swapfile SSD)
  • Stockage : 50 Go (SSD)
  • OS : Ubuntu 22.04.3

Vous pouvez utiliser le minimum, mais lors des tests. Discourse utilise facilement 2 Go. L’utilisation inactive est d’environ 1,48 Go sur 6 Go.

NOTE : Cette installation utilise le proxy inverse pour créer les certificats SSL. Certbot peut être utilisé si vous préférez.

ÉTAPE 1 :

Téléchargez la dernière version du serveur Ubuntu depuis Get Ubuntu Server | Download | Ubuntu

ÉTAPE 2 :

  1. Installez Ubuntu Server sur le modèle VM/LxC
    1.1 Assurez-vous qu’Ubuntu est à jour avec tous les packages serveur.
  2. Utilisez les commandes suivantes pour installer tous les packages requis :
apt update -y && apt upgrade -y && apt wget curl zip git docker.io nginx -y && reboot

ÉTAPE 3 :
Installation de Discourse. Suivez le Guide du débutant discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub

Connectez-vous à votre serveur via SSH et entrez simplement ceci :

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

Après avoir terminé ce qui précède. Vous pouvez ensuite exécuter ./discourse-setup

Suivez toutes les étapes et entrez-les correctement, car cela sera essentiel pour une installation réussie.
Les étapes demanderont ce qui suit ; exemple du guide de configuration :

Laissez l’installation se dérouler, cela peut prendre un certain temps en fonction de votre connexion Internet et des spécifications du serveur. L’installation complète a pris environ 5 à 8 minutes en utilisant ma configuration VM.

ÉTAPE 4 :

Une fois l’installation terminée, vous verrez la commande de démarrage que le conteneur Docker utilise et l’ID du conteneur généré (hash).

NOTE : Puisque vous êtes derrière un proxy via le WAN, vous verrez une erreur 502 et comme le conteneur utilise le réseau Docker. Il sera inaccessible depuis le WAN ou le LAN, à moins que vous ne vous connectiez au réseau 172.17.0.1/16, dont nous n’aurons pas besoin.

Vérifiez que l’installation est terminée et que le conteneur Docker est en cours d’exécution en utilisant :

docker ps

Vous devriez obtenir le résultat suivant.

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

ÉTAPE 5 :
Mise à jour du fichier app.yml pour s’adapter à la configuration du proxy inverse.

Utilisez votre éditeur de texte préféré pour ouvrir /var/discourse/container/app.yml
Remplacez/Commentez les lignes suivantes : (cela sera géré par le Nginx local)

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

Immédiatement après #- "templates/web.letsencrypt.ssl.template.yml", ajoutez ce qui suit :

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

Commentez ensuite la section expose car Discourse utilisera désormais un websocket, Nginx pourra alors démarrer car il libérera les ports 80 et 443 requis localement.

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

Maintenant, pour forcer Discourse à ne fournir que des liens avec HTTPS, ajoutez ce qui suit dans la section env :

# FORCE SSL
DISCOURSE_FORCE_HTTPS: true

Maintenant, pour enfin lancer les choses, vous devrez reconstruire l’application. En utilisant ce qui suit :

cd /var/discourse
./launcher rebuild app

Laissez cela s’exécuter et se terminer. Pour vérifier si cela a réussi, assurez-vous que la commande de démarrage Docker est affichée ou exécutez simplement docker ps et vous verrez le conteneur en cours d’exécution.

ÉTAPE 6 :

Activation de Nginx et configuration du site par défaut pour pointer vers le conteneur Docker. Permettant au proxy inverse d’accéder au conteneur en utilisant le Nginx local.

Exécutez ce qui suit :

systemctl enable nginx && systemctl start nginx

Pour vérifier s’il est en cours d’exécution. Essayez d’accéder à la page d’accueil par défaut de Nginx en utilisant votre navigateur et votre IP locale.
PAR EXEMPLE :

http://10.10.0.4

Vous devriez obtenir une page de félicitations de Nginx.

ÉTAPE 7 :
Mise à jour de la configuration par défaut comme suit :
Videz d’abord le fichier de configuration :

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

Utilisez votre éditeur de texte pour ouvrir le fichier de configuration et ajoutez ce qui suit :
NOTE : Mettez à jour server_name avec votre domaine et ssl_certificate, ssl_certificate_key avec l’emplacement de votre certificat SSL et de votre clé.
Certbot peut être utilisé, mais je synchronise simplement mon certificat et ma clé depuis mon proxy inverse.

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

Enregistrez le nouveau fichier par défaut et exécutez systemctl restart nginx.

ÉTAPE 8 :

Ouvrez votre navigateur et accédez au domaine de votre forum https://mondomaine.com et vous serez accueilli par la page suivante.

C’est tout, c’est terminé. Vous pouvez ensuite suivre les étapes pour vous enregistrer et lancer votre forum/communauté :).

ÉTAPE SUPPLÉMENTAIRE :

Maintenance post-installation
Nous vous suggérons fortement d’activer les mises à jour de sécurité automatiques pour votre système d’exploitation. Sous Ubuntu, utilisez dpkg-reconfigure -plow unattended-upgrades

Pour obtenir de l’aide, vous pouvez simplement utiliser cette communauté, pour le Nginx local, n’hésitez pas à demander de l’aide sur ce post.

10 « J'aime »

C’est super. Merci.

Une chose que j’aimerais voir comme amélioration de ce guide est de pouvoir servir des actifs statiques via nginx.

Actuellement, toutes les requêtes statiques vont au worker dans la configuration ci-dessus. J’essaie toujours de trouver une solution de contournement, je publierai une mise à jour si je la trouve.

Pouvez-vous préciser de quels fichiers statiques il s’agit ?

Parlez-vous peut-être des pages statiques 404, 302, 500 de nginx ou des pages statiques de Discourse ?

Je me suis penché sur la question et j’ai constaté que la redirection pour les pages 404 fonctionne. La seule page que je n’arrive pas à configurer est la page d’erreur 500.

Pouvez-vous être un peu plus précis afin que je sache exactement ce que je recherche. :slight_smile:

Ce guide est excellent. J’ai pu suivre l’intégralité jusqu’à ce que j’arrive au chargement du site Web. J’obtiens une erreur « trop de redirections ». Lorsque j’utilise l’adresse IP, Discourse se charge correctement, mais je n’arrive pas à résoudre le problème des redirections. Si près du but.

Toute aide serait appréciée.

Merci.

Quelqu’un sait comment je peux résoudre ce problème ? Le site fonctionne, mais je remarque ces erreurs dans le fichier error.log du conteneur nginx. J’ai utilisé un proxy inverse configuré selon ces instructions ci-dessus.

En regardant /etc/nginx/conf.d/discourse.conf dans le conteneur, je vois :

upstream discourse { server 127.0.0.1:3000; }

Est-ce que cela devrait être quelque chose comme :

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

En regardant dans /var/log/nginx dans le conteneur, je vois des erreurs comme :

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"

Merci !

Avez-vous suivi correctement l’étape 5 ? Il semble que vous n’utilisiez pas de socket.

Oui, j’utilise une socket sur le proxy inverse local en dehors du conteneur, et vérifiez, j’ai suivi l’étape 5 dans 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

J’ai consulté ceci : Discourse working with jwilder /nginx proxy & acme-companion

mais je n’arrive pas vraiment à comprendre en quoi cela concerne mon problème…