Need to force HTTPS in NGINX behind a classic AWS Load Balancer? It’s important and easy-to-do. Here’s how:
First of all, TLS/SSL is a good thing for your website. Quite often HTTP over TLS will be used only on pages requiring extra security, such as login, signup and “my account” pages. In the past, this extra layer of security was seen as slower and therefore unnecessary for sections of a site that don’t expose or transmit private information and user data. However, while it is more CPU and resource intensive, modern hardware and systems can handle it just fine.
In fact, in 2014 Google began calling for “HTTPS Everywhere” and indicated in a blog post that entire-site HTTPS would begin to be a ranking factor for websites in their search algorithms. It was a lightweight factor at the time, but of increasing importance ever since.
So, yes HTTPS is a good thing for your website… and easy to implement, too. If you’re using an AWS ELB (Elastic Load Balancer), you can load the SSL cert directly on the ELB and it can handle the secure traffic for all server instances behind that balancer. This removes the need to manage the cert on each instance, which is nice. However, I found it to be a bit tricky when I attempted to redirect all traffic to HTTPS in NGINX. Typically when doing this on servers that are not behind an ELB, I would add two server blocks in my configuration file – one for port 80 and one for 443. The 80 block would simply redirect to HTTPS and then the 443 block would accept that traffic and handle the certificate. This just wouldn’t work for me behind the ELB. I would get infinite redirects or in some attempted configurations, it just wouldn’t serve up the HTTPS version.
So, here’s how to force HTTPS in NGINX behind an AWS Load Balancer:
First, attach your SSL cert to the load balancer. And then configure both port 80 and 443 to send traffic to each instance through port 80 like this:
In your NGINX site configuration file (typically in the /etc/nginx/sites-available/ folder), add a single server block listening on port 80 since all traffic is now flowing through that port. Now you only need to a bit to check for HTTPS and redirect if it’s not. You can do that with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
server {
# all traffic, secure or otherwise, comes in on 80 from the ELB
listen 80;
# ELB stores the protocol used between the client
# and the load balancer in the X-Forwarded-Proto request header.
# Check for ‘https’ and redirect if not
if ($http_x_forwarded_proto != ‘https’) {
return 301 https://$host$request_uri;
}
server_name your–secure–site.com www.your–secure–site.com;
.... (the rest of your config)
}
|
And that’s it! All traffic on your site should now run through the secure protocol. Your visitors will be happy and Google will like your site more 🙂