AWS: “Free” SSL Certs

If you’re running your own web server in AWS EC2, then you’ll likely want to setup SSL for your site. This ordinarily means purchasing an SSL cert. There are some cheap providers on the market but generally you should expect a cert to cost you in the region of USD 50-100 per year for a “good” cert. For experimental projects this might be a cost you don’t want to pay, at least until you’re certain that there’s value in your site. You might also not want to have to purchase and manage SSL certs for each site you set up.

There’s a “trick” with AWS here which allows you to sidestep this issue, potentially indefinitely. If you put an Elastic Load Balancer in front of your EC2 instance then you can get a free SSL cert issued by Amazon. This of course means you must pay the cost for the load balancer. Unfortunately this means you’ll be paying close to USD 20 per month for a load balancer and that’s before the cost of it actually handling requests. So if you decide to leave your site up for a while then you should probably just buy an SSL cert 🙂

Note that this topic has been covered by others. I’m just using this blog as an excuse to type up some notes. The contents beyond here will largely be bullet points with little context. You’ll need some pre-existing AWS experience to use this else you might be a little lost

Instructions

Pre-Condition: We will assume that you already have a HTTP web server running on an EC2 instance.

Step 1: Allocate Elastic IP to your EC2 Instance

This isn’t strictly necessary if you don’t plan to ever migrate your web server to another EC2 instance as EC2 IPs are permanent until you destroy the instance.

  • Go to EC2 dashboard
  • Go to Elastic IPs
  • Click “Allocate Elastic IP address”
  • Once created, select the IP and choose the action to associate the IP
  • Associate it with your EC2 instance

Note that you don’t get charged for elastic IPs unless you hold one and fail to associate it to a resource.

Step 2: Create the SSL Cert

  • Go to ACM dashboard
  • Request a (public) certificate
  • Add domains
    • Likely you want to add both yourdomain.com and www.yourdomain.com
  • Choose DNS validation (better option IMO)
  • Go to your DNS manager
  • Add the CNAME records that AWS is looking for
  • Wait ⏳

Step 3: Create the load balancer

  • Go to EC2 dashboard
  • Go to Load Balancers
  • Create a HTTP HTTPS load balancer
  • Give it a name and ensure you have “internet-facing” selected (and probably IPv4)
  • Select HTTPS as the protocol (this is the listen protocol as opposed to the protocol you’re proxying to)
  • Choose some availability zones (don’t worry too much about this)
  • Choose your cert from ACM
  • Create a new security group and setup firewall rules to allow TCP 443
  • Create a target group
    • Instance
    • HTTP
    • Port 80 (probably, depending on what port your web server is listening on)
    • Health check can be any valid path on your server, but you might want to pick one which has a low overhead. Consider even just setting up something to respond with a 200 status
  • Register your web server as a target (on port 80)
    • N.B. You’ll only have one target in this simple case. For real world load balancers you’d have multiple targets

Step 4: Point your DNS to the load balancer

This is straightforward if you’re using Route53. My domains are registered with GoDaddy so these instructions reflect that.

  • Go to EC2 dashboard
  • Go to Load Balancers
  • Select your load balancer and look at the Description underneath
  • Copy the “DNS name”
  • Paste that into the CNAME record for www on your site
  • Wait ⏳

Note that this setup is a bit janky. You cannot point your apex A record to another CNAME (see here). This is why I’m using www. I haven’t figured out yet if there’s a clean way to handle this with GoDaddy + AWS Load Balancer. If there isn’t then transferring my DNS to AWS is probably the way to go. Note that GoDaddy’s site forwarding doesn’t seem to work well for me.

Leave a Reply

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