Discourse ne se charge pas avec Apache et la redirection de proxy

I’ve spent the last few days trying to find a way to pair Discourse with Apache on the same DigitalOcean droplet and the tutorials available here on Discourse are either outdated or not applicable to me. One tutorial uses CentOS and HAProxy (I use Ubuntu) and the other uses Nginx (I use Apache).

I came across a comment on a DigitalOcean thread and followed the instructions there on a test droplet: Install Discourse on a droplet with WordPress served by Apache ? | DigitalOcean

Everything seems to have gone smoothly, including the Let’s Encrypt SSL. My homepage, a few static HTML documents, works just fine. Discourse, despite installing without errors, does not show. When navigating to community.mysite.com, I just see my homepage with an unsecured HTTPS in the URL. Yes, my DNS settings are accurate and pointing to the correct server.

This is my mysite.com.conf:

<VirtualHost *:80>
	ServerAdmin webmaster@localhost
	ServerName mysite.com
	ServerAlias www.mysite.com
	DocumentRoot /var/www/mysite.com
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.mysite.com [OR]
RewriteCond %{SERVER_NAME} =mysite.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

This is my mysite.com-le-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
	ServerAdmin webmaster@localhost
	ServerName mysite.com
	ServerAlias www.mysite.com
	DocumentRoot /var/www/mysite.com
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mysite.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mysite.com/privkey.pem
</VirtualHost>
</IfModule>

This is my community.mysite.com.conf:

<VirtualHost *:80>
  ServerName community.mysite.com
  ServerAlias www.community.mysite.com

  <IfModule proxy_module>
    ProxyPreserveHost on
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
  </IfModule>
</VirtualHost>

And finally, here is my app.yml (edited of course):

## this is the all-in-one, standalone Discourse Docker container template
##
## After making changes to this file, you MUST rebuild
## /var/discourse/launcher rebuild app
##
## BE *VERY* CAREFUL WHEN EDITING!
## YAML FILES ARE SUPER SUPER SENSITIVE TO MISTAKES IN WHITESPACE OR ALIGNMENT!
## visit http://www.yamllint.com/ to validate this file as needed

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.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"

## 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:
      - "8080:80"   # fwd host port 8080   to container port 80 (http)
      - "8443:443"   # fwd host port 8443 to container port 443 (http)

params:
  db_default_text_search_config: "pg_catalog.english"

  ## Set db_shared_buffers to a max of 25% of the total memory.
  ## will be set automatically by bootstrap based on detected RAM, or you can override
  db_shared_buffers: "128MB"

  ## can improve sorting performance, but adds memory usage per-connection
  #db_work_mem: "40MB"

  ## Which Git revision should this container use? (default: tests-passed)
  #version: tests-passed

env:
  LANG: en_US.UTF-8
  # DISCOURSE_DEFAULT_LOCALE: en

  ## How many concurrent web requests are supported? Depends on memory and CPU cores.
  ## will be set automatically by bootstrap based on detected CPUs, or you can override
  UNICORN_WORKERS: 2

  ## TODO: The domain name this Discourse instance will respond to
  ## Required. Discourse will not work with a bare IP number.
  DISCOURSE_HOSTNAME: community.mysite.com

  ## Uncomment if you want the container to be started with the same
  ## hostname (-h option) as specified above (default "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: List of comma delimited emails that will be made admin and developer
  ## on initial signup example 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'myemail'

  ## TODO: The SMTP mail server used to validate new accounts and send notifications
  # SMTP ADDRESS, username, and password are required
  # WARNING the char '#' in SMTP password can cause problems!
  DISCOURSE_SMTP_ADDRESS: smtp.mailgun.org
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: my-smtp-username
  DISCOURSE_SMTP_PASSWORD: "my-smtp-password"
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)

  ## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
  LETSENCRYPT_ACCOUNT_EMAIL: myemail

  ## The http or https CDN address for this Discourse instance (configured to pull)
  ## see https://meta.discourse.org/t/14857 for details
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

## The Docker container is stateless; all data is stored in /shared
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## Plugins go here
## see https://meta.discourse.org/t/19157 for details
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git

## Any custom commands to run after building
run:
  - exec: echo "Beginning of custom commands"
  ## If you want to set the 'From' email address for your first registration, uncomment and change:
  ## After getting the first signup email, re-comment the line. It only needs to run once.
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  - exec: echo "End of custom commands"

Can anyone tell me where I went wrong with this or what I might be missing? Thanks!

You’ll have a much better luck trying nginx as a reverse proxy.

If your system allows, consider using nginx instead of apache2

2 « J'aime »

so community does not redirect to your domain but points to your IP, is the symlink present in /etc/apache2/sites-enabled/ ?

Is proxy_module loaded ?
apache2ctl -M

1 « J'aime »

No symlink.

Yes. Fortunately, that’s one of the steps in the tutorial I linked to.

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_balancer
a2enmod lbmethod_byrequests

the step

a2ensite community.yoursite.com

might not have gone well then, might need a sudo.

sudo ln -s /etc/apache2/sites-available/community.yoursite.com.conf /etc/apache2/sites-enabled/

should also do it.
then

sudo apachectl configtest

and fingers cross

sudo systemctl restart apache2

Dear @OrbitStorm,

I took a quick look at your Apache2 virtual hosts configuration for you and your yml file for Discourse and they do not appear to be correctly configured.

Here are some hints:

First of all, when you run Discourse behind a reverse proxy, you do not enable SSL LETSENCRYPT in the Discourse yml configuration (see working example below). Discourse only needs a single port to communicate with the reverse proxy and that is not an SSL encrypted connection.

Second, if you look at your main virtual host configuration, which is the port 443 on the reverse proxy:

<IfModule mod_ssl.c>
<VirtualHost *:443>
	ServerAdmin webmaster@localhost
	ServerName mysite.com
	ServerAlias www.mysite.com
	DocumentRoot /var/www/mysite.com
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

       Include /etc/letsencrypt/options-ssl-apache.conf
       SSLCertificateFile /etc/letsencrypt/live/mysite.com/fullchain.pem
       SSLCertificateKeyFile /etc/letsencrypt/live/mysite.com/privkey.pem
</VirtualHost>
</IfModule>

That configuration above is missing all necessary reverse proxy information (see attached working configurations below).

Here is a working configuration for you, which is basically the same as outlined in the various tutorials on meta (well documented on this site in other posts, so this is basically duplicating other documentation here at meta):

<VirtualHost *:80>
        ServerName discourse.your-great-web-site.com
        ServerAdmin webmaster@localhost
        ProxyPreserveHost On
        ErrorLog ${APACHE_LOG_DIR}/discourse_errors.log
        CustomLog ${APACHE_LOG_DIR}/discourse.log combined
        ModPagespeed Off
        RewriteEngine on
        RewriteCond %{SERVER_NAME} =discourse.your-great-web-site.com
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Note that in the port 80 configuration, there is the main required directives are the ServerName, RewriteEngine and rewrite rules to redirect to port 443.

Also, if you are running Apache2 mod_pagespeed you should disable as I have not yet got mod_pagespeed working with Discourse (and see no reason to do so either).

Here is the main config, where the “real-work” is done:

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerName discourse.your-great-web-site.com
        ServerAdmin webmaster@localhost
        SSLProxyEngine on      # enable this only after let's encrypt is configured and working
  	    RewriteEngine on
  	    ProxyPreserveHost On
  	    ProxyRequests Off
  	    RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
 	    RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}

        #ProxyPass / http://127.0.0.1:8888/           # we do not use port, we use your-great-web-site sockets
        #ProxyPassReverse / http://127.0.0.1:8888/    # we do not use port, we use your-great-web-site sockets
        ProxyPass / your-great-web-site:/var/discourse/shared/socket-only/nginx.http.sock|http://localhost/
        ProxyPassReverse  / your-great-web-site:/var/discourse/shared/socket-only/nginx.http.sock|http://localhost/

        ErrorLog ${APACHE_LOG_DIR}/discourse_errors_ssl.log
        #CustomLog ${APACHE_LOG_DIR}/discourse_ssl.log combined   #access log disabled for production

        ModPagespeed Off
        SSLCertificateFile /etc/letsencrypt/live/discourse.your-great-web-site.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/discourse.your-great-web-site.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

All our discourse configurations use unix domain sockets, so you will need to change the configuration to match your desired configuration.

The main point to understand (in summary), is that you should disable LETSENCRYPT in your Discourse build (yml) configuration and only expose a single entry point into Discourse, in our case a unix domain socket, in your case a single TCP/IP socket.

Then you reverse proxy to that entry point from the virtual host file for port 443 (not from the port 80 virtual host). The port 80 virtual host simply redirects to 443. Your 443 SSL is all done by LETSENCRYPT in the reverse proxy. There is no SSL required in your Discourse yml file (see working example below).

Here is one of our working yml files (for the configuration above) for you to review:

/var/discourse/containers$ cat socket-only.yml
# IMPORTANT: SET A SECRET PASSWORD in Postgres for the Discourse User
# TODO: change SOME_SECRET in this template

templates:
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml"
#  - "templates/sshd.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"

## 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

# Use 'links' key to link containers together, aka use Docker --link flag.
links:
  - link:
      name: data
      alias: data

# any extra arguments for Docker?
# docker_args:

params:
  ## Which Git revision should this container use? (default: tests-passed)
  #version: latest
  db_shared_buffers: "4GB"

env:
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8

  # DISCOURSE_DEFAULT_LOCALE: en

  ## How many concurrent web requests are supported? Depends on memory and CPU cores.
  ## will be set automatically by bootstrap based on detected CPUs, or you can override
  #UNICORN_WORKERS: 3
  UNICORN_WORKERS: 8

  ## TODO: The domain name this Discourse instance will respond to
  DISCOURSE_HOSTNAME: 'discourse.your-great-web-site.com'

  ## Uncomment if you want the container to be started with the same
  ## hostname (-h option) as specified above (default "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: List of comma delimited emails that will be made admin and developer
  ## on initial signup example 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'tim@discourse.your-great-web-site.com'

  ## TODO: The SMTP mail server used to validate new accounts and send notifications
  # SMTP ADDRESS, username, and password are required
  # WARNING the char '#' in SMTP password can cause problems!
  DISCOURSE_SMTP_ADDRESS: smtp.gmail.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: not_for_reply@discourse.your-great-web-site.com
  DISCOURSE_SMTP_PASSWORD: my_super_secret_cool_password
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)

  ## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
  #LETSENCRYPT_ACCOUNT_EMAIL: me@example.com

  ## TODO: configure connectivity to the databases
  DISCOURSE_DB_SOCKET: ''
  #DISCOURSE_DB_USERNAME: discourse
  DISCOURSE_DB_PASSWORD: another_super_secret_cool_password
  DISCOURSE_DB_HOST: data
  DISCOURSE_REDIS_HOST: data

  DISCOURSE_MAXMIND_LICENSE_KEY: my_max_mind_key
  ## The http or https CDN address for this Discourse instance (configured to pull)
  ## see https://meta.discourse.org/t/14857 for details
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

volumes:
  - volume:
      host: /var/discourse/shared/socket-only
      guest: /shared
  - volume:
      host: /var/discourse/shared/socket-only/log/var-log
      guest: /var/log

## Plugins go here
## see https://meta.discourse.org/t/19157 for details
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-bbcode.git
          - git clone https://github.com/discourse/discourse-sitemap.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-whos-online.git
          - git clone https://github.com/unixneo/legacy-info.git

## Remember, this is YAML syntax - you can only have one block with a name
run:
  - exec: echo "Beginning of custom commands"

  ## If you want to configure password login for root, uncomment and change:
  ## Use only one of the following lines:
  #- exec: /usr/sbin/usermod -p 'PASSWORD_HASH' root
  #- exec: /usr/sbin/usermod -p "$(mkpasswd -m sha-256 'RAW_PASSWORD')" root

  ## If you want to authorized additional users, uncomment and change:
  #- exec: ssh-import-id username
  #- exec: ssh-import-id anotherusername

  - exec: echo "End of custom commands"
  #- exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Authorized SSH keys for this container:"; } NF>=2 {print $NF;}'

It’s really easy once you understand the basics; and understanding the basics does help quite a lot :slight_smile:

Please keep in mind that in our Discourse configurations, we do not run a single container (actually, we rarely run in single container mode), so our yml file will not work in a single container (standalone) configuration. I am providing it to you for reference to help you, by showing you what a fully working configuration behind Apache2 looks like.

We run Discourse behind both Apache2 and nginx reverse proxies. In fact, we only use reverse proxies for many reasons. One reason is that we can use the reverse proxy to filter bad bots, etc (a totally different subject).

There is nothing difficult about running Dockerized Discourse (as many sites as you want, one or 100) behind a reverse proxy on a site with Apache2; but it does help to understand the basic concepts.

I hope providing you both the basic concepts and working example configuration files help you move forward and get Discourse up and running.

Best Regards…

1 « J'aime »

@neounix I appreciate that incredibly in-depth response but it seems most of the issues I’m running into are a result of not being able to find a suitable updated tutorial. Several tutorials here say to enable SSL for Discourse in the yml file and one such tutorial says that I don’t need to add proxy information to my VirtualHost files because Let’s Encrypt should do it automatically. Your examples are wildly different even from my defaults making them just as confusing as trying to blend a CentOS configuration with Ubuntu.

You’re absolutely right in saying that understanding the basics goes a long way but the problem is the basics aren’t properly covered and when they are, they’re dated from three years ago and without any consideration that someone uses Apache instead of Nginx or Ubuntu instead of CentOS. It’s worth noting too that Discourse is the only reason I have any use for Docker.

After spending four days just trying to get the application installed alongside Apache, I’m done. Free or not, this isn’t worth the headache and I’m not going to continue combing the forums just to keep finding copy/pasted links to the same two outdated and incomplete tutorials. I’ve never had a frustrating experience with simply installing forum software until Discourse. Speaks volumes. XenForo and Invision are two platforms I have immeasurable experience with and they’re a cakewalk to install/use.

I truly do appreciate the effort you put into your response but I’m not going to ask you to do the work for me, nor should I have to if proper documentation existed. It’s simply amazing to me that my specific circumstances, which aren’t so specific to me, have not been highlighted in a new tutorial that would make this process easier for new users.

Whatever the case, best of luck to you.

3 « J'aime »

Malgré mon intention initiale de passer à autre chose avec Discourse, étant donné l’absence totale de documentation actuelle qui ne soit pas hyper-centrée sur CentOS/Nginx, une personne incroyablement généreuse et patiente chez DigitalOcean a répondu à un fil que j’avais créé là-bas. Après quelques essais et erreurs, elle m’a aidé à mettre au point un tutoriel simple à suivre pour les futurs utilisateurs de Discourse se trouvant dans la même situation que moi.

Pour rappel, ces circonstances sont les suivantes :

Installer Discourse sur le même serveur qu’Apache | Utilisation d’Ubuntu 18.04 | DigitalOcean

crédit à Bobbyiliev @ DigitalOcean
Install Discourse on a droplet with WordPress served by Apache ? | DigitalOcean (première réponse)

Prérequis

  • Par mesure de précaution, assurez-vous de sauvegarder votre Droplet, afin de pouvoir revenir à une version fonctionnelle en cas de problème.
  • Connectez-vous en SSH à votre Droplet.
  • Apache doit être installé. Vous pouvez suivre les étapes pour cela ici :

Étape 1 - Installer Docker

Pour installer Docker, veuillez suivre les étapes indiquées ici :

Étape 2 - Télécharger Discourse

Tout d’abord, créez un répertoire où vous stockerez vos fichiers Discourse :

mkdir /var/discourse

Ensuite, clonez l’image Docker officielle de Discourse dans /var/discourse.

git clone https://github.com/discourse/discourse_docker.git /var/discourse

Étape 3 - Configurer Discourse pour écouter sur le port 8080

Nous utiliserons le modèle standalone.yml qui inclut tous les services nécessaires tels que PostgreSQL, Redis, etc.

Copiez le fichier exemple avec la commande suivante :

cp /var/discourse/samples/standalone.yml /var/discourse/containers/app.yml

Ensuite, éditez le fichier avec votre éditeur préféré. Ouvrez /var/discourse/containers/app.yml et mettez à jour les ports aux lignes 23 et 24 :

## Quels ports TCP/IP ce conteneur doit-il exposer ?
expose:
  - "8080:80"   # transférer le port hôte 8080 vers le port 80 du conteneur (http)
  - "8443:443"   # transférer le port hôte 8443 vers le port 443 du conteneur (https)

Si vous ne possédez pas encore de certificat SSL, assurez-vous de commenter la ligne 16 :

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

Ajoutez simplement le symbole # devant la ligne - "templates/web.ssl.template.yml", sinon Discourse ne démarrera pas.

Étape 4 - Configurer Discourse

Changez de répertoire :

cd /var/discourse

Ensuite, démarrez Discourse (comme c’est la première fois que vous lancez le service, cela initialisera l’application avec les nouvelles modifications présentes dans votre fichier app.yml) :

./discourse-setup

Remarque : Assurez-vous de fournir des paramètres de serveur de messagerie valides, sinon la configuration pourrait échouer.

Étape 5 - Configurer Apache

Dans votre répertoire /etc/apache2/sites-available/, créez un nouveau fichier nommé forum.example.com.conf et ajoutez le contenu Vhost suivant :

<VirtualHost *:80>
  ServerName forum.example.com
  ServerAlias www.forum.example.com

  <IfModule proxy_module>
    ProxyPreserveHost on
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
  </IfModule>
</VirtualHost>
  • Activez le Vhost avec la commande suivante :
a2ensite forum.example.com
  • Activez le module Proxy :
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_balancer
a2enmod lbmethod_byrequests
  • Redémarrez Apache :
systemctl restart apache2

Après cela, vous pourrez accéder directement à Discourse via votre nom de domaine.


Remarque 1 : Lors de l’installation de Discourse, le fichier app.yml peut être écrasé et les lignes 16/17 (SSL) seront décommentées. Vous devrez les commenter à nouveau, puis reconstruire l’application (n’oubliez pas de changer de répertoire) : ./launcher rebuild app

Remarque 2 : SSL n’est pas activé pour Discourse avec ce guide. Il est peu surprenant qu’aucune documentation n’existe pour activer SSL Let’s Encrypt si vous l’avez déjà activé pour Apache. Si quelqu’un tombe sur une solution à ce problème, n’hésitez pas à me contacter.

4 « J'aime »

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.