Issues with SSL termination and Docker

docker

(Sam Nazarko) #1

Hi

I have a Discourse forum at http://discourse.osmc.tv. It’s running a Docker instance in a virtual machine and has been fine.

I’ve tried migrating to SSL. As we serve multiple SSL sites from that IPv4 I can’t add the certificate and key and have nginx listen on 443. I’m using Pound, so I’ve added the key and certificate to that and I’m reverse proxying to HTTP.

I can now make posts (issues deleting though) and access everything via SSL. However I can’t change any settings under admin/ when I’m on SSL, but can if I access via HTTP. I’ve tried:

  • Going to http://SITEURL/admin and changing the SSL enabled setting to ON. It’s now ON (what does this do? I’m still able to access the http:// so it doesn’t seem to be forcing redirects).
  • Rebuilding the Docker instance

If I try edit a setting such as the Site Name and click the green tick, I’ll get ‘Sorry, an error occured’. I don’t see anything in my browser console, so I’m wondering the best way to debug this. I suspect the AJAX requests might be going via HTTP even though I’m on HTTPS – although that wouldn’t explain why posting functionality seems to work without too many problems.

Does Discourse support this? I want Discourse to realise I’m on SSL but let me terminate at Pound and proxy it this way.

Many thanks


(Kane York) #2

This setting changes generated URLs to have https at the beginning instead of plain http, which you do want here.

The server should also be respecting X-Forwarded-Proto headers for the same effect.


(Sam Nazarko) #3

Hi

And thanks for your response!

We want to have https in our URLS (be SSL enabled).

We do this change to the header:

HeadRemove "X-Forwarded-Proto"
AddHeader "X-Forwarded-Proto: https"

This is so we can hash it in Varnish and distinguish it from HTTP traffic (thus, not get any HTTP links). Here’s the Varnish VCL that handles that in vcl_hash:

if (req.http.X-Forwarded-Proto ~ "https") {
        hash_data(req.http.X-Forwarded-Proto);
      }
     return (hash);

The above is done indiscriminantly for all of our traffic. It’s so a request to http://somedomain.com/somepage doesn’t return the same page as https://somedomain.com/somepage. Although the content would be the same, that would be a nightmare for CSS and JS includes.

  • Changing a setting under admin/ when on HTTPS gives me an error. If I go to the http:// version it’s fine. I’m surprised I’m not automatically redirected to an HTTPS page when I try this.
  • Same as above for deleting posts. Deleting under HTTPS doesn’t work, but as HTTP it does.

I’m starting to think this is a bug in Discourse and I’m happy to provide debugging info to help resolve this. I don’t do much in terms of web development, so I may have missed something here. If that’s the case, let me know.

Thanks

Sam


(Kane York) #4

Wait, so you’re offering the forum under mixed HTTP and HTTPS? Hm.

Does the Javascript console have anything to say when you get the error?


(Sam Nazarko) #5

No – we’re trying to serve exclusively on HTTPS. This is why I’m asking if Discourse should be serving on HTTP at all. I would expect it to 301 over to the HTTPS page like most web applications. It just so happens the forum behaves properly under HTTP, but not HTTPS. This is why I asked what Discourse actually does when you ‘enable SSL’ in the Security part of Admin settings, as we’ve not noticed observed a difference in behaviour at all.

We do our VCL-fu for sites that we do serve under HTTP and HTTPS, but Discourse is not one of them.

I suspect we’ve found a bug in Discourse. I haven’t found an example of someone doing SSL-termination with Discourse on the web in Docker. I suspect the nginx example you guys give uses SSL termination and forwards to the original Ruby port, but that’s within the container itself and part of the yaml configuration, so might change something else internally. I’d add the SSL certs to the shared directory and get nginx to handle SSL, but we can’t have nginx bind to 443 as we’re serving multiple sites via HTTPS (hence Pound)

Re. console: nothing at all oddly enough

Many thanks

Sam


(Jeff Atwood) #6

So this is the underlying issue?


(Sam Nazarko) #7

Hi Jeff,

I don’t think so. I’d expect if SSL is enabled, Discourse to serve on HTTPS and not care where that SSL/TLS connection is terminated. Allow me to explain:

  • I presume that if I put my SSL certificate in your Docker installation, nginx would terminate the SSL and serve the certificate to clients (then reverse proxy an HTTP request to the Ruby port)
  • Instead, I’m using Pound which does the same thing (teminates SSL), but before it hits nginx. So our first approach was to not enable SSL in Docker and not let it know we’re doing SSL at all and just change the site URL. But this gave errors, so we enabled SSL in Admin -> Security, but didn’t notice any change in behaviour (still getting these AJAX errors)

Pages are serving on SSL just fine if I visit the HTTPS site, however some AJAX elements seem to be causing problems (the tick or cross option for saving settings, deleting a post, etc). My suspicion is Discourse is probably trying to send these requests via HTTP, not HTTPS, but I’m not web-dev oriented enough to investigate this.

I am happy to give you guys access to the box and the admin panel if you’d like to have a look at this

Cheers

Sam


(Jeff Atwood) #8

Unfortunately we only have that kind of time for existing customers – are you a customer?


(Sam Nazarko) #9

Hi Jeff,

We’re not a customer – I wasn’t aware we could buy a support license. From what I could gather we can only purchase a one-time installation which would be on a specific platform such as DigitalOcean which won’t meet our requirements.

I don’t think this is a setup issue at our end. I’m not asking for support in that sense, but more that someone takes a look and confirms that it is indeed not a Discourse issue. If it is a bug and the problem is resolved then I’m sure it will help other future users in time.

Cheers

Sam


(Kane York) #10

You’re sending back a 501 Not Implemented error code. That’s pretty weird, but definitely an issue with your proxy.

Additionally, your Google auth is giving this error message:

Error: redirect_uri_mismatch

Application: Discourse Forum

You can email the developer of this application at: removed

The redirect URI in the request: OSMC Forums did not match a registered redirect URI.

It might be better to use NGINX for ssl termination?


(Sam Nazarko) #11

Hi

I know Google integration is broken but we’ll fix that.

Can you let me know what action gave you a 501? We get normal responses (200) on browsing forum posts – was the 501 when you tried to change a setting?

Unfortunately we can’t terminate with Nginx (at least not in the Docker instance) as we’ve got multiple SSL sites on that IP.

I’m very appreciative of your support

Sam


(Kane York) #12

Any PUT request, such as… changing a setting. Yes.

Well, NGINX has SNI support, of course. The actual reason is that you’re already using another proxy :stuck_out_tongue:


(Sam Nazarko) #13

Thanks for making it clear that this is caused with PUT. I’ll look into the issue with Pound and Varnish and post here when/if I find a solution so others can benefit.

Yes – we could probably terminate a higher up nginx (it couldn’t be in Docker though).

Sam


(Kane York) #14

That’s what I meant.

note: you can skip all the stuff about stopping the container there, that’s just to make sure the port isn’t bound


(Kane York) #15

Found it! :smile:

By default Pound only supports GET, POST, and HEAD. Pound will return an HTTP status code of 501 (not implemented) if it encounters a different method, such as PUT or DELETE.

Resolving this issue is easy.

ListenHTTP
   # ... some settings
   xHTTP 1 #Support GET, POST, HEAD, PUT, and DELETE
   # ... some more settings
End

In the meantime, things like deleting drafts were broken on your forum (DELETE request).


(Sam Nazarko) #16

Thank you. And excellent catch!