Search code examples
amazon-web-servicesssl-certificateamazon-elastic-beanstalkcertbotamazon-linux-2

How to automatically generate HTTPS/SSL certificates in AWS Beanstalk without a load balancer?


I am using Elastic Beanstalk on AWS to host a single-tenant application with Amazon Linux 2 + Nginx server. Is there any way to automatically generate a HTTPS certificate without recurring to a Load Balancer?


Solution

  • A solution would be to create an AWS Linux 2 + Nginx image based on your Elastic Beanstalk image with Certbot (application needed to generate the certificates) preinstalled and roll out this image to your instances. Then, with a .posthook script Certbot can be called to renew the certificate each time the server is started or updated (restart/new version upload)

    For the first step you can create an AWS Beanstalk environment through the wizard : the instance will be made available on your EC2 tab. Then, you can access your EC2 instance through SSH (there is a tutorial at this link : Putty is a good choice of a SSH client on Windows) and run the following commands to install Certbot:

    sudo wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
    
    sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
    
    sudo yum-config-manager --enable epel*
    
    sudo yum install -y certbot python2-certbot-nginx 
    

    After that you can go to the EC2 tab, find your instance and create an image based on your EC2 Elastic Beanstalk instance: EC2 screen - image creation

    With the image created, it can be reused on several instances by inserting the newly created AMI on the Instance Traffic and Scaling menu on the Elastic Beanstalk Configuration tab. AMI designation

    The next step is to assign a DOMAIN environment variable to your EB environment. This variable corresponds to the domain that has been assigned to your server IP through DNS. DOMAIN environment variable

    Lastly, a script should be placed in the .zip /.jar file or docker image that is uploaded on Beanstalk. The file should be located on:

    -- .zip file root
       -- .platform
          -- hooks
             -- postdeploy
                -- update_certificate.sh
    

    The file content is:

    #!/bin/bash
    sleep 60
    sudo certbot --nginx --non-interactive --redirect --email [email protected] --agree-tos -d $(sudo /opt/elasticbeanstalk/bin/get-config environment -k DOMAIN) --cert-name $(sudo /opt/elasticbeanstalk/bin/get-config environment -k DOMAIN) || echo 'The certificate could not be generated/updated. Initialization will continue'
    

    The --email parameter should be replaced with a real e-mail and could also be set up as an environment variable.

    The sleep command waits for the server IP to correspond to the Elastic IP : if Certbot is called before that the certificate will not be generated.

    Also note that this command instructs Nginx to redirect traffic from port 80 (HTTP) to 443 (HTTPS), so this port should be enabled on your EC2 instance: Enabling inbound 443 port

    This solution should be resilient to an Application server / Nginx server restart and to the upload of new application versions.