SSL with Apache reverse proxy and docker container


(ariddell) #1

I’d like to run discourse (in docker container) along with another site on my machine. I cannot get apache to reverse proxy SSL (reverse proxy with HTTP works fine).

  1. Does anyone have a working apache setup where one has a reverse proxy to a https discourse site?
  2. Alternatively, are there any problems with just letting apache add the SSL and leaving the discourse docker container serving http? (should I set the ssl SiteSettings setting?)

My Apache setup looks like this:

<VirtualHost *:443>
    ServerName forum.mydomain.org

    SSLEngine On
    SSLCertificateFile    /var/docker/shared/standalone/ssl/ssl.crt
    SSLCertificateKeyFile /var/docker/shared/standalone/ssl/ssl.key

    SSLProxyEngine On
    SSLProxyCACertificateFile /var/docker/shared/standalone/ssl/ssl.crt

    ProxyPreserveHost On
    ProxyRequests Off
    ProxyPass / https://localhost:7000/
    ProxyPassReverse / https://localhost:7000/

    CustomLog /var/log/apache2/discourse_apache_proxy_https_access.log combined
    ErrorLog /var/log/apache2/discourse_apache_proxy_https_error.log
</VirtualHost>

and the error Apache gives is this:

The proxy server could not handle the request GET /.

Discourse automatically switched from http to https
(ariddell) #2

Adding the following lines fixed the problem.

SSLProxyVerify none 
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off

But I am still curious about whether or not I should just add SSL at the proxy level (Apache/nginx) level. Are there any reasons not to do that?


(Jens Maier) #3

By securing the connection between Apache and Nginx in the container, you gain protection against a man in the middle between exactly these two nodes. As long as both run on the same physical machine and communicate via local-only networking (i.e. loopback, virtual ethernet devices), there is no point at all in doing that.

The error you’re experiencing is because Apache tries to verify the SSL certificate presented by Nginx; however, you’ve configured Apache to proxy to a machine named localhost, so it rightfully expects the other server to present a certificate for that hostname; in that context, your certificate for your user-facing domain name is invalid and must be rejected by Apache.

Bottomline, only the server facing directly the end user should present your public certificate. Communication between servers in the backend can be secured with SSL, but you might want to create your own CA certificate, issue server certificates for each server and configure them to verify certificates against your own CA certificate instead those from the system’s default store.


(Nordize) #4

Apologies for resurecting this, but it’s the mostr suitable topic. Being new to Discourse, I wanted to ask: is there any danger (failed URLs or redirects etc) if I set up Apache SSL on 443 but ProxyPass to the non-SSL version of Discourse? Like so

<VirtualHost *:443>
    ServerName host.domain.com
    [...]
    ProxyPass / http://localhost:7000/
    ProxyPassReverse / http://localhost:7000/
    [...]
</VirtualHost>

I already have an automatic redirect from :80 to :443 on the host, so any http:// links in Discourse should be redirected just fine to https://

<VirtualHost *:80>
    [...]
    Redirect permanent / https://host.domain.com/
</VirtualHost>

Are there any remaining pitfalls?

I’d like to avoid the double encryption (once in Apache, then again in Nginx) if this is expected to be error free.


(Felix Freiberger) #5

No, as long as Apache and Discourse run on the same host, you’re fine.
(The official guide uses nginx and a socket, but also uses plain HTTP for the internal communication.)


(Nordize) #6

I thought so too. I met a small bug with this: the home page has a hard coded redirect to http://discourse.domain.com/login (note the http://) when visited for the first time. This gives a 404

https://discourse.domain.com  # redirect to login
http://discourse.domain.com/login  # http:// is hard-coded, gives 404

Fixed by creating a redirect in Apache for http:// to https:// like I did above, which then adds an uneccessary redirect

https://discourse.domain.com  # redirect to login
http://discourse.domain.com/login   # http:// is hard-coded, redirect again to https://
https://discourse.domain.com/login

(Felix Freiberger) #7

Did you enable the force https site setting?
Does Apache set the appropriate headers (especially X-Forwarded-Proto)?


(Nordize) #8

Good catch! Adding

RequestHeader set X-Forwarded-Proto "https"

to the ssl virtualhost did the trick and login is redirected directly to https://. I didn’t have to enable force https. does that help with other things?


(Felix Freiberger) #9

It does a bunch of things, including making sure that cookies are marked as secure :slight_smile:


(Nordize) #10

Ah, indeed. force https it is then. Many thanks for replying (great community!).

A tip to anyone wanting to do this: you’ll want to use the event mpm in Apache (not prefork or worker) for higher performance, particularly with Discourse’s long polling


(Felix Freiberger) #11

(or use nginx, which has awesome performance out of the box :slight_smile:)


(Nordize) #12

I was expecting someone to say that :), and you are right of course. For one, I’m stuck with Apache for other reasons, so the information in this thread should be useful. But truth be told, Apache 2.4 is much faster than it used to be. With the event mpm speed should be comparable with nginx (both event based, not process based). Also, I kind of still like Apache for its richer community and docs so unless i really need to squeeze all possible speed out of the machine, I usually go Apache.