How to run Discourse as an Apache VirtualHost

I’ve successfully been able to install Discourse on my server, register as the first user, and post my first topic. So everything on the Discourse side of things seems to be working.

However, in order to get Discourse installed and running, I had to disable my Apache httpd daemon. This is a major problem for me as I’ve basically shutdown my entire web server, which includes a bunch of domains as well as a Jitsi conference server.

My Jitsi installation runs as a separate virtual host using a subdomain of one of the websites I’m hosting. Since Jitsi is able to share port 443 with the other web traffic, I would like to do the same with Discourse.

Has anyone got a template virtualhost definition that allows traffic to be handed over to Discourse when it comes in on the Discourse subdomain?

2 Likes

Yes ,there are guides here on meta which discuss running Discourse alongside other sites.

I’m confident that if you use the search you can find them.

2 Likes

Essentially solved, however the homepage seems to take a long time to finish the request, even after the page appears to be fully loaded. (I’m not sure if this is a normal behaviour or not.)

Discourse
I modified the expose block in /var/discourse/containers/app.yml to

expose:
  - "127.0.0.1:8000:80"   # http
  - "127.0.0.1:8443:443"  # https

Which forwards from the localhost to the docker container. After doing this, a rebuild is required using ./launcher rebuild app

Apache2 2.4.43 (Ubuntu)
I added a new virtual host for the subdomain: discourse..com.conf in sites-available which forwards the subdomain’s traffic to the localhost port the Discourse docker instance is listening to. The virtual host definition is below:

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

As I don’t spend a lot of time configuring Apache, there may be some unnecessary lines, or lines that could be added or improved. Any feedback is welcome.

1 Like

Hi @Nap,

Good to read you solved your problem.

I’m running Discourse on a number of servers with Apache2 as the front end reverse proxy to a unix socket and the configuration works just fine (as we all know, it is a little bit slower than nginx, which I also run on some servers, but it works fine.)

Basically, I configure the virtual host like this:

Port 80 configuration

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName  discourse.mygreatwebsite.com
    DocumentRoot /website/discourse  # often not necessary

    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>

Port 443 configuration:

<VirtualHost *:443>
  ServerAdmin webmaster@localhost
  ServerName  discourse.mygreatwebsite.com
  DocumentRoot /website/nginx  # mostly not required  in this configuration
  
  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>

Notes:

  1. Normally, I let the letsecrypt certbot do all the work regarding setting up all the SSL certs and redirects, etc.

  2. We use the IP address which apache2 is bound (to) in the apache2 config files.

  3. We always configure this (expose) with unix sockets in the discourse container, and do not expose any TCP/IP container ports in this configuration.

Cheers and hopes this adds some value, late in the game.

5 Likes

Two quick additions:

  1. If you’d like to use a unix socket instead of a direct proxy, you can do that (after enabling the web.socketed.template.yml in your app.yml) thusly:
  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>

Note you will probably need to deal with selinux if you try and have apache read from /var/discourse like that. Something like semanage fcontext -a -t httpd_sys_rw_content_t /var/discourse/shared/standalone/nginx.http.sock follwed by a restorecon /var/discourse/shared/standalone/nginx.http.sock should do you for that.

  1. Apache has the rather awesome mod_md that can get your LetsEncrypt certificates for you automatically. I highly recommend it.
2 Likes

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