Cloudflare and Heroku: Encrypting End-to-End HTTPS

September 25, 2024
We believe that our greatest asset is our people. Our employee spotlight series aims to showcase the talent, careers, and culture of our team members and Kilterset. Join us in celebrating their personalities, stories and contributions that make our company culture vibrant and our success possible.

I recently set up a Rails app in Heroku. I wanted Cloudflare to act as a WAF, sitting at the edge and proxying requests to the Heroku app. When I set it up, I got an endless 301 redirect loop:

$ curl -i https://my-cool-websiteHTTP/2 301…location: https://my-cool-website/…

Why? It turned out Cloudflare was forwarding the HTTPS request as an HTTP requests to Heroku. My Rails app noticed that the request was not HTTPS, and then issued a redirect to the HTTPS site, resulting in an infinite loop.

After doing some reading, I realised that this behaviour is controlled by Cloudflare’s TLS Custom SSL/TLS settings (under Websites > Website > TLS/SSL). The setting was set to Flexible, which issues your requests as HTTP.

Now this might be suitable for your use case, but I wanted Cloudflare to both handle TLS termination to the client but also make HTTPS requests to Heroku, making it end-to-end encrypted. I tried the Full (Strict) mode, and immediately got this “525 SSL handshake failed” error:

What happened? Even though I had SSL configured on Heroku through Heroku’s Automatic Certificate Management (which uses Let’s Encrypt under the hood), Cloudflare didn’t accept it.

I decided to issue an Origin Server certificate through Cloudflare and install it on Heroku. In Cloudflare, visit Websites > Website > TLS/SSL > Origin Server and generate a certificate.

In Heroku, open your app > Settings > SSL Certificates and add a manual certificate. Copy the public and private keys as prompted.

With that in place, Cloudflare trusts the certificate on the Heroku app and does end-to-end encryption with HTTPS both between Cloudflare and the user and between Cloudflare and the app.

One side-effect of this is that the Cloudflare certificate will not work for the public web. This is probably what you want – nobody should be accessing your Heroku app unless via Cloudflare.

Like what you've read?
Let's talk
Connect with us on LinkedIn to see our latest content!

Want to work with people like this?

Kilterset is always looking for great people to join our team

Get in contact