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

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


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.


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

SECURE_SSL_REDIRECT = True


I assumed you used Python 3.4 with uWSGI 2 (Docker) version 1.4.3. As my answer in here, you need to coustumized your Elastic Beanstalk environment:

  • Elastic Load Balancer:
    • Listen on port 80 and proxy it to EC2 instance port 80.
    • Listen on port 443 and proxy it to EC2 instance port 443.
  • EC2 Web Server/Proxy:
    • Listen on port 80 and response with redirect to HTTPS.
    • Listen on port 443 and serve the request.

I though EB Predefined Python 3.4 (Docker) and Single Docker Container is almost same, except in the Python thing. I've written a post in Enable HTTPS and HTTP-Redirect on AWS Elastic Beanstalk. You could read the guide there. It tells you how to configure Elastic Beanstalk Single Docker Container serve HTTPS and HTTP (redirect to HTTPS).

If you got error (usually if you started it from Elastic Beanstalk sample on first landing page):

Updating security group named: sg-xxxxxxxx failed Reason: SecurityGroupEgress cannot be specified without VpcId

You need to specify your VpcId inside AWSEBLoadBalancerSecurityGroup > Properties. So, the config should be:

..."AWSEBLoadBalancerSecurityGroup": {  "Type": "AWS::EC2::SecurityGroup",  "Properties": {    "GroupDescription": "Allow HTTP and HTTPS",    "VpcId": "vpc-xxxxxxxx",    "SecurityGroupIngress": [      {        "IpProtocol": "tcp",        "FromPort": 80,        "ToPort": 80,        "CidrIp": "0.0.0.0/0"      },      {        "IpProtocol": "tcp",        "FromPort": 443,        "ToPort": 443,        "CidrIp": "0.0.0.0/0"      }    ],    "SecurityGroupEgress": [      {        "IpProtocol": "tcp",        "FromPort": 80,        "ToPort": 80,        "CidrIp": "0.0.0.0/0"      },      {        "IpProtocol": "tcp",        "FromPort": 443,        "ToPort": 443,        "CidrIp": "0.0.0.0/0"      }    ]  }},...