So I recently started running WPChat over HTTPS. This will basically serve as a noob version of the documentation already provided in the allowing SSL for your Discourse Docker setup guide by Discourse co-founder, Sam Saffron.

Not even Discourse supports non-Docker installs anymore, so I won’t either. If you installed Discourse a long time ago without Docker, get up to speed. As I covered in my WPChat launch post, I’ve already done this.

Luckily, Discourse already has a lot of HTTPS features already baked in. It’s just a matter of you enabling it.

Before you do anything, backup

We’re going to be messing with terminal commands, altering configuration files, and doing other stuff that if done incorrectly, can potentially break your site.

I’ll explain later why there’s not much to really worry about. But just for the peace of mind, run a backup and store the backup file in a safe place.

Generate a CSR and Private Key

We’ll cover buying an SSL certificate in the next step. At some point in the process, the company you buy it from is going to ask for your CSR, which stands for certificate signing request. We’ll get that step out of the way now.

SSH into your server and navigate to the /var/discourse/shared/standalone/ssl/ directory.

If you find these directories missing, depending on how you originally installed Discourse, you may find this directory in /var/docker/shared/standalone/ssl/ instead.

This is where you’ll be storing all of your key files.

Once in the proper directory, type out the following command to generate your CSR and private key.

openssl req -nodes -newkey rsa:2048 -keyout ssl.key -out ssl.csr

After a set of questions, the two new files will be generated in the directory. The answers to these questions don’t matter much, just answer them to the best of your ability. Although when it asks for your FQDN, make sure you input your domain name (i.e.

Once the ssl.csr file is generated, we use the cat program to output its contents in the terminal with the following command: cat ssl.csr. We can then copy this to the clipboard and save it for later.

It’s very important the ssl.key file is named exactly that, otherwise we’ll run into some problems later. This is your private key, so like the name suggests, keep it to yourself.

Buy An SSL Cert

An essential step of running Discourse over HTTPS is acquiring an SSL certificate. Luckily, there are a several cheap (and even free!) options.

I prefer to go with a reseller like (a NameCheap company). There’s absolutely zero reason to buy a certificate directly from the authority for full price when you can get literally the exact same thing for a fraction of the price.

I went with the PositiveSSL for 5 years at $4.95 per year. At $24.75 for 5 years, that’s almost exactly half the cost of buying it directly from Comodo for one year ($49).

I’m not going to go into too much detail on the checkout process as it’s pretty self explanatory.

You also have the option of going with a free certificate from StartSSL. There’s nothing wrong with it, but they do charge for reissues should you ever need to. As you might imagine, it generated a bit of controversy over Heartbleed.

For the rest of the tutorial, I’ll be walking through the PositiveSSL product.

Whip out your CSR

Remember that CSR file we copied to our clipboard? After paying for your SSL certificate, it’s going to ask you for it.


Just paste it in the box provided, and proceed to the next step.

Also, select your web server as “Other” because for some reason, this dropdown list includes every type of server under the sun except for Nginx, which is what Discourse uses.

Verify Domain Ownership

Certificate authorities have instant, automated means of verifying your control of the domain, usually over email.

You’ll receive this correspondence from the certificate authority (like Comodo, for example) and not from the reseller you bought it from. So don’t be confused when you start receiving domain verification emails from Comodo.

To verify by email, you’ll need to make sure that you have access to one of the following email addresses:

  • The email address listed under your admin contact on WHOIS


On this step, you’ll notice that the SSL company has extracted the information to the questions you answered during the CSR generation step. This is a good opportunity to check if there are any problems.

Simply select the email address you want to use to verify, fill out your contact information on the next step. and the certificate authority (in my case, Comodo) will take it from there. Keep your eyes peeled on your email for the verification, and later, the certificate files. It will all be pretty instant.

If you use WHOIS privacy, make sure it forwards to an email box you control so you can receive the verification code. If your WHOIS privacy service doesn’t support that, you’ll need to set up an email box at one of the above addresses only.

I’m not going to get into too much detail on alternative ways of verifying domain ownership because email verification should be easy enough, but if for some reason that’s not an option, here’s Comodo’s help article on alternative methods of Domain Control Validation.

Combine Your Certificates

After purchasing your SSL certificate and verifying domain ownership, you’ll receive a set of four certificate files.

  • Root CA Certificate – AddTrustExternalCARoot.crt
  • Intermediate CA Certificate – COMODORSAAddTrustCA.crt
  • Intermediate CA Certificate – COMODORSADomainValidationSecureServerCA.crt
  • Your PositiveSSL Certificate – wpchat_com.crt

We’ll need to combine three of these files in a certain order. You can do this locally on Mac OSX or on your server with the cat program (the same program we used to output the CSR file contents earlier).

cat wpchat_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt > ssl.crt

Note that these file names may differ depending on who you purchase the certificate from and the domain name you’re SSLing.

In the following asciinema, I do it on the server itself. Assume that I’ve already placed those three files in the directory through sFTP or other means.

Utilize tab completion to avoid manually typing out those long file names. You can safely remove all the files except for ssl.key and ssl.crt after this is complete.

rm wpchat_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt ssl.csr

Note the ls commands I use throughout to illustrate what files should be on each step.

Make sure you do NOT include the Root CA Certificate (in my case, AddTrustExternalCARoot.crt) in the bundle. This is already included in the browser and may cause errors if you duplicate it.

Edit Config Files

You’ll need to edit your app.yml file to include the SSL template, and listen on port 443.

nano /var/discourse/containers/app.yml

Then add the following bold parts to the designated areas.

  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/sshd.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ssl.template.yml"

  - "80:80"
  - "2222:22"
  - "443:443"

Note that the templates/web.ssl.template.yml is already in your Docker container, just waiting to be unlocked for Discourse over HTTPS goodness.

Rebuild Discourse

At this point, you should have all your certificates in the right place and associated configurations properly set up.

But you’re still not seeing that green padlock icon up in your address bar. That’s because you have to rebuild your Discourse app before the changes will take place.

In your /var/discourse/ directory, input the following command:

./launcher rebuild app

You’ll notice I typed this out in the asciinema above, but backspaced and logged out before entering the command. In a live situation, this takes a while.

Be patient.

The rebuild can take anywhere from 5 to 20 minutes, in my experience. It’s nerve racking. And your site will be unavailable during the rebuild.

In the rare event the rebuild fails (which it shouldn’t if you followed all the steps correctly!) rest assured that your site isn’t lost.

Discourse actually stores all of its data outside of the Docker container, so there’s nothing you can do (at least with the rebuild command) to permanently damage your site.

You can troubleshoot with the following command if you do have problems.

./launcher logs app

Test Your SSL

Thanks to all the configuration goodness we unlocked in the previously mentioned templates/web.ssl.template.yml file, you should receive a grade of A+.


If you find your grade is capped because of some issue, chances are you missed one of the steps above. I know my grade was capped at a B because I mistakenly included the root certificate in my bundle. After removing it and rebuilding, I got my A+ grade.

Also, standards change over time. Make sure you keep your Discourse installation up-to-date to keep up with whatever updates they may provide to the SSL template.

Mixed Content Warnings

Even after you get an A+ grade at SSL Labs, you may still find mixed content warnings throughout your Discourse install. This is evidenced by the exclamation point icon instead of padlock icon in your address bar.


Mixed content warnings happen when you load an insecure resource over http onto an https site. This could be an image, script, stylesheet, or video embed.

Discourse does a pretty good job of using relative URLs over absolute URLs for things like uploaded images (i.e. /uploads/image.png instead of

However, I’ve found that video embeds from users cause these problems. To remedy this, I’ve edited users’ posts to embed the https version instead of the http version as I’ve come across them.

Due to the nature of Discourse as a single page application, the mixed content warnings will persist even after you navigate away from the thread that contained the mixed content in the same session.

All Done

So as you can see, you can get your Discourse installation running over HTTPs with pretty minimal effort and cost. The whole process should take you less than an hour.

Now let’s see some more Discourse installs running over SSL!


Leave a Reply

Your email address will not be published. Required fields are marked *