How to configure AWS Beanstalk NGINX requests to redirect http to https πŸ”’

1. Overview

In the very default configuration of AWS Beanstalk with Tomcat there is Apache configured as a reverse proxy to handle the http requests.

For performance reasons one would want to change from Apache to NGINX and use Transport Layer Security (SSL/TLS) for http connection to get the desired green padlock in the browser.

The easiest way to do this is by adapting a load balancer configuration as shown here. However, sometimes you do not want to use a load balancer for cost or other reasons. Then you have to take care that apache/nginx handles the http encryption and forwards the requests to the tomcat server.

It will also be shown how to automatically obtain a letsencrypt certificate and configure nginx to use it by using ebextension .config files.

How to do this is shown in the following. We assume a configuration like this:

  • AWS Beanstalk with Tomcat
  • AWS Apache Reverse Proxy
  • Single instance (no load balancer)
  • IDE: NetBeans 8.2 with Maven
  • Access to DNS entry

2. Switch from Apache to NGINX with Beanstalk

Assuming you are familiar with AWS ebextension and their usefulness, we create a tomcat-settings.config file in our /src/main/.ebextension folder that was created beforehand. Make sure to modify “YOURENDPOINT” to your beanstalk endpoint.

option_settings:
  aws:elasticbeanstalk:application:environment:
    API_ENDPOINT: YOURENDPOINT.elasticbeanstalk.com
  aws:elasticbeanstalk:environment:proxy:
    GzipCompression: 'true'
    ProxyServer: nginx

Next we have to tell Maven to include the .ebextension config files in the war deployment file. This is accomplished by the modifying the maven-war-plugin in the pom.xml file.

<!-- ... -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <webResources>
            <resource>
                <directory>src/main/.ebextensions</directory>
                <targetPath>.ebextensions</targetPath>
                <filtering>true</filtering>
            </resource>
        </webResources>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
</plugin>
<!-- ... -->

The folder structure in our NetBeans project with the .ebextension folder looks like this:

3. Allow ssl traffic and obtain certificates

Next we create another https-instance-securitygroup.config file in the .ebextension folder. This tells to allow incoming traffic on port 443. In order to use Certbot, packages from the EPEL repository need to be installed. Finally, the list the commands that will download Certbot, stop nginx, get the certificates, dynamically link the certs and start nginx again.

Resources:
  sslSecurityGroupIngress: 
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      CidrIp: 0.0.0.0/0

packages: 
  yum:
    epel-release: [] 


container_commands:
  10_installcertbot:
    command: "sudo wget https://dl.eff.org/certbot-auto; sudo chmod a+x certbot-auto"
  20_stopngninx:
    command: "sudo nginx -s stop"
    ignoreErrors: true
  30_getcertwebrootmode:
    command: "sudo ./certbot-auto certonly --debug --non-interactive --email YOUREMAIL --agree-tos --standalone --domains YOURDOMAIN --keep-until-expiring"
  40_link:
    command: "sudo ln -sf /etc/letsencrypt/live/YOURDOMAIN /etc/letsencrypt/live/ebcert"
  50_startngninx:
    command: "sudo nginx"

Make sure to adjust YOUREMAIL and YOURDOMAIN or use env variables!

4. Overwrite nginx.conf default configuration

Lastly, we overwrite the default http configuration for port 80 in the ngxinx.conf file and add the required adjustments for https and 301 forwarding.

Any incoming requests (“listen 80 default_server;”) will now be answered with a 301 to https (“listen 443 ssl;”). From there the reverse nginx proxy sends the encrypted communication to our tomcat server (“proxy_pass http://127.0.0.1:8080/;”).

user                    nginx;
error_log               /var/log/nginx/error.log warn;
pid                     /var/run/nginx.pid;
worker_processes        auto;
worker_rlimit_nofile    15967;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    include       conf.d/*.conf;

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

    server {
        listen        80 default_server;
        access_log    /var/log/nginx/access.log main;

        client_header_timeout 60;
        client_body_timeout   60;
        keepalive_timeout     60;
        gzip                  on;
        gzip_comp_level       4;
        gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

        # Include the Elastic Beanstalk generated locations
        include conf.d/elasticbeanstalk/*.conf;
       server_name    YOURDOMAIN;
       return         301 https://$server_name$request_uri;
    }
 

    server {
           listen 443 ssl;
           server_name YOURDOMAIN;
           ssl_certificate /etc/letsencrypt/live/ebcert/fullchain.pem;
           ssl_certificate_key /etc/letsencrypt/live/ebcert/privkey.pem;
           ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
           ssl_prefer_server_ciphers on;
           ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

           location / {
             proxy_pass http://127.0.0.1:8080/;
           }
         }
}

Make sure to adjust YOUREMAIL and YOURDOMAIN or use env variables!

5. Check and Troubleshooting

HTTPS with elastic beanstalk involves multiple configurations that have to be working in synchrony. For troubleshooting we can use the (not comprehensive) checklist:

  • Inbound traffic on 443 allowed?
  • Is nginx up and running? => see process list
  • Was certbot installed successfully?
  • Did certbot obtain the certificates => check destination folder
  • Are the certificates linked correctly?
  • Is nginx listening to port 443
  • Is http 301 redirect working? => check with chrome debugger tools, for example

In general, it is worthwhile to have a look at the eb log files to find and fix the errors quickly.

6. Conclusion

Even though it requires some time to set everything up and chances are you have to do some troubleshooting, setting up tomcat with nginx and ssl encryption is worth it. After the steep learning curve of AWS elastic beanstalk and nginx configuration you can now enjoy encrypted communication to your applications handling private user data, financial credentials and more!

Leave a Reply

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