SyntaxHighlighter

Monday, January 8, 2018

NGINX HTTPS Redirect on AWS Elastic Beanstalk

We run a NodeJS app on AWS Elastic Beanstalk. Their node environment works well for us and on the machine is NGINX running on port 8080, and our node app running at port 8081. Some proxy table forwards port 80 to 8080, so NGINX receives all the traffic.

The SSL certificate is managed by AWS Certificate Manager, and is configured at the Load Balancer. That load balancer is serving traffic on port 80 (HTTP) and 443 (HTTPS), but always to port 80 on the beanstalk instance(s). It's very good to not have to worry about SSL in NGINX or node, and I could access our pages via HTTP or HTTPS.

However, I always wanted to use HTTPS. How could I automatically forward? Changing the Load Balancer to different ports (like 443 -> 80 to 443 -> 443) would have required some deep system changes on the beanstalk instances, which is handled by some complex beanstalk scripts. Examples are out there, but it all seemed overly complex and then I was tying our system to some random internet script that I did not write or understand.

Thankfully the solution was much simpler.

This is in my NGINX setup:

  server {
    listen 8080;

    if ($http_x_forwarded_proto = "http") {
      return 301 https://$host$request_uri;
    }

    // lots of other stuff
  }

That's all it took, and I understand it! If the protocol is "http", redirect for "https" and keep everything else (host and URI) the same. Mostly this will only affect the first load of the page, after that all future requests will remain HTTPS anyway.

(Only downside is sometimes I forget the "s" when pasting a `curl` command, and the response doesn't follow the redirect, responding with 301.)