Tutorial: Adding https to a custom domain on Elastic Beanstalk

James Beswick
Jul 20, 2017 · 5 min read

The elusive green padlock has thwarted many a budding AWS Architect.

Image for post
Image for post

As much as I love AWS, sometimes it feels like it’s the world’s best toy store but the aisles are covered with landmines.

With many procedures, they’re really easy once you know the exact steps and the gotchas along the way, but getting to that point can be a miserable experience of wading through incomplete documentation and tangential Stack Overflow advice.

Elastic Beanstalk is one such example. It’s a fantastic tool once you get it configured but I’ve come close to breaking a few keyboards in the process. In between where the documentation says “type eb deploy” and “you’re done”, there’s a good weekend’s worth of pain deciphering cryptic error messages and wondering why the environments are not the same.

In this tutorial, I have an Elastic Beanstalk application with a custom domain name and I want to deploy https. Let’s do this thing.

EB = Elastic Beanstalk
ELB = Elastic Load Balancer
OMG = Sometimes I hate my choice of career!!

Foolish assumptions

  1. In your EB setup, you are using a load balancer and not running a “no ELB/single-instance” config. If you are running a single-instance EB, there are ways to get SSL running but that’s not what I’m covering here.

The tutorial

  1. Go to Certificate Manager, click “Request a certificate” and follow the verification process. For this example, our app will be myapplication.mydomain.com.
Image for post
Image for post

If you select the ELB target, it will work until the environment changes and the ELB is reconfigured. I learned this the hard way.

3. Go to Elastic Beanstalk in the console, select your environment and click “Configuration” on the left. Find Network Tier and click the “Load Balancing” cog icon. Change Secure listener port to 443 and find the SSL certificate from the drop-down (you created this in step 1):

Image for post
Image for post

4. Allow the environment to reconfigure itself and https://myapplication.mydomain.com will now work. You may have to clear your dns on your local machine or at least wait a while if it doesn’t work straight away.

Pitfalls, gotchas, and ‘why was this so hard’?

The configuration in Elastic Beanstalk is relatively new — previously, you had to edit files in .ebextensions, configure load balancers and set security groups manually. Consequently, the official documentation is inconsistent and advice in tech forums is out of date.

I made some critical errors that cost me a weekend. Specifically:

  • If the Route 53 configuration is wrong, it will all appear to work with http (good) but https always loads without a certificate (bad).

Like many AWS services, it’s the minor, tiny details that can derail you. But once you’ve found the path through the maze, it really looks extremely simple. Joyously, this setup will auto-renew itself forever and ever so automation FTW.

So this was the easy way of creating your very own custom domain with https on an Elastic Beanstalk application using Certificate Manager. I honestly hope it saves somebody a weekend.

Bonus Tip: Redirecting http to https at the Apache level.

One immediate annoyance is that if your visitors goes to the http version of the site, they are not redirected to https. And if you use a framework like Flask, which I know and love well, functions such as url_for can often direct between the two somewhat arbitrarily.

There are a couple of ways to deal with this, so I’ll start with the bad ones together with their levels of terribleness:

  • Use CloudFront in front of ElasticBeanstalk — it works but good God, no, what a terrible idea. Pour holy water on this one.

And it’s pretty simple — and I don’t know who figured this out originally because it wasn’t me. Just create a file in the .ebextensions directory called apache.config (the name doesn’t matter) and paste the following:

mode: "000644"
owner: root
group: root
content: |
RewriteEngine On
<If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

Note! YAML uses spaces, not tabs, so make sure you use spaces in the snippet above or you will get a cryptic error message.

On the next eb deploy, everything will now always be https. Phew.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store