Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I redirect http to https for Elastic Beanstalk running nginx?

I know there are a lot of SO questions on this exact topic. However, none seem to work with the latest version of Elastic Beanstalk / Docker combination.

I am running a Django/Python web app inside a Docker, which I then deploy to Elastic Beanstalk. I want http and https to be active, so I enabled both port 80 and 443 in the AWS EB configuration console. This works great. My site is accessible over both http and https. However, this isn't really what I want. I want port 80 (http) automatically forward to port 443 (https).

I've followed every piece of advice out there on SO and other forums to debug this, but I think the info out there is too old. (Ie., this no longer works).

I have found where EB sets up its servers (in a file called: /etc/nginx/sites-enabled/elasticbeanstalk-nginx-docker-proxy.conf), and it's contents are:

map $http_upgrade $connection_upgrade {
  default  "upgrade";
  ""       "";
}

server {
  listen 80;
  location / {
    proxy_pass          http://docker;
    proxy_http_version  1.1;
    proxy_set_header    Connection       $connection_upgrade;
    proxy_set_header    Upgrade          $http_upgrade;
    proxy_set_header    Host             $host;
    proxy_set_header    X-Real-IP        $remote_addr;
    proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;
  }
}

When I modify this file from listen 80; to listen 443 ssl; and the try to load my site on https, I get ERR_CONNECTION_REFUSED.

Can someone point me in the correct direction to modify this config file to redirect from http to https?

like image 295
Brett Avatar asked Apr 30 '15 00:04

Brett


People also ask

How do I change HTTP to HTTPS on AWS?

Select a load balancer, and then choose HTTP Listener. Under Rules, choose View/edit rules. Choose Edit Rule to modify the existing default rule to redirect all HTTP requests to HTTPS.

Does Elastic Beanstalk use nginx?

Elastic Beanstalk uses nginx as the reverse proxy to map your application to your Elastic Load Balancing load balancer on port 80. Elastic Beanstalk provides a default nginx configuration that you can either extend or override completely with your own configuration.


2 Answers

As of August 2018, for a Python (Flask) app placed in a Docker container with nginx placed in front and SSL certificate in AWS Certificate Manager.

After configuring the load balancer to listen on both ports 80 and 443 you can configure the redirection from http to https by creating one file. In general, it will add one if statement into an nginx configuration for you:

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

TL;DR: This is done by the following file placed in .ebextensions directory which you create in the parent directory of your Beanstalk app project. Give the file a chosen name, for e.g. force-https, but remember to use the .config extension. Don't forget to commit the new file if you're using git!

My app/.ebextensions/force-https.config file (YAML - indentation matters!):

files:

  "/etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf" :
    mode: "000755"
    owner: root
    group: root
    content: |
      map $http_upgrade $connection_upgrade {
          default        "upgrade";
          ""            "";
      }

      server {
          listen 80;

          gzip on;
              gzip_comp_level 4;
              gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

          if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
              set $year $1;
              set $month $2;
              set $day $3;
              set $hour $4;
          }
          access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;

          access_log    /var/log/nginx/access.log;

          location / {
              if ($http_x_forwarded_proto = 'http') {
                  return 301 https://$host$request_uri;
              }
              proxy_pass            http://docker;
              proxy_http_version    1.1;

              proxy_set_header    Connection            $connection_upgrade;
              proxy_set_header    Upgrade                $http_upgrade;
              proxy_set_header    Host                $host;
              proxy_set_header    X-Real-IP            $remote_addr;
              proxy_set_header    X-Forwarded-For        $proxy_add_x_forwarded_for;
          }
      }

Explanation: If you want the redirection to work for every new deployment and every new EC2 instance that will be started for your app, you need to modify the nginx configuration through Elastic Beanstalk .ebextensions directory. In theory, this change could be done directly in the app's EC2 instance's nginx configuration file (using ssh to connect to the machine), this however is not a good solution, because the changes will be lost when the instance is terminated or when you deploy a new version of the app.

The file where we intend to add the aforementioned if statement is placed in /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf in the app's EC2 instance. Our file with replacement instructions needs to be created in the .ebextensions directory that you create in the parent directory of your project. It needs to specify which files you want to overwrite (files: in the code above). Elastic Beanstalk will apply this .config file while deploying your app by overwriting the indicated nginx file in every new machine.

like image 76
arudzinska Avatar answered Sep 29 '22 09:09

arudzinska


Have you tried configuring this in settings.py and let django handle the process.

SECURE_SSL_REDIRECT = True
like image 28
thedzy Avatar answered Sep 29 '22 08:09

thedzy