AWS Elastic Beanstalk

Elastic Beanstalk is a platform-as-a-service (PaaS) for hosting web apps. Below are notes on configuring an Elastic Beanstalk environment with a new web app.

Table of contents

  1. Configure Your App to Run on Elastic Beanstalk
    1. Aligning Environment Software Versions
    2. Installing Dependencies on Elastic Beanstalk
  2. Deploying Your App
  3. Configuring DNS for Your App
  4. Setup SSL on EB Environment
    1. Install Certbot
    2. Allow Traffic on Port 443
    3. Donwload and Configure Certificate
    4. Automatically Renew the Certificate
  5. CI/CD on Elastic Beanstalk
  6. Where To Look For Logs

Configure Your App to Run on Elastic Beanstalk

Aligning Environment Software Versions

Elastic Beanstalk only supports a few specific versions for the software used in our web app (e.g. Ruby, Puma Server), so we’ll need to make sure our web app is configured to use those versions as well. Otherwise, we’ll run into app install errors.

First, take a look at our Gemfile to check the version of Ruby being used. If the Gemfile isn’t using the correct version (3.0.6 at the time of writing), then install the correct version using rbenv.

Next, update your Gemfile to use that version of Ruby. The easiest way to do this is to let the Gemfile read .ruby-version file created by rbenv.

Next, check the version of Puma being used. Look for puma ... in your Gemfile. If the Gemfile isn’t using the correct version (6.2.2 at the time of writing), then update uninstall the old version and reinstall the new version.

Installing Dependencies on Elastic Beanstalk

Elastic Beanstalk uses CentOS on the EC2 instances it spins up, and the default CentOS image is missing some common package dependencies. For example, a default Rails app will need the sqlite Gem which requires a sqlite development package to create the headers.

Elastic Beanstalk allows various script hooks and configuration files to be included in your app that will customize the CentOS environment during deployment. We can write a YAML configuration file to install the sqlite-devel dependency from yum package manager.

Deploying Your App

If you don’t already have an EB environment configured, follow the guide AWS provides for setting up an EB environment. However, instead of using the sample application option, you can jump right to deploying your app from the environment setup.

To deploy your app, create an app source bundle. In the root of your project directory, run the following commands.

This will generate a app source bundle named <my-app-source-bundle>.zip in the directory about your app root directory. Use this file as the app source bundle, then use the AWS EB console to ‘Upload and Deploy’ the source bundle.

If your Elastic Beanstalk environment goes to into a ‘Warning’ or ‘Critical’ state, see Where to Look For Logs to debug.

Configuring DNS for Your App

By default, the EB environment will serve your app over HTTP (port 80) using a public domain that looks like <env-name>.<env-prefix>.<region>.elasticbeanstalk.com. If you have a custom domain purchased through a non-AWS provider, this section will walk through routing traffic from your custom domain to your EB environment.

First, we’ll use AWS Route 53 to configure our DNS records. Go to Route 53 console. Create a ‘Hosted Zone’ using your root domain for the ‘Domain Name’.

Next, we’ll create alias records to route traffic from our root domain and subdomains to go to our EB environment domain. Go to ‘Hosted Zones’ in Route 53 console and select the hosted zone we just created.

  1. Select ‘Create Record’
  2. Leave subdomain blank for the first record we create so we can create a root record
  3. Select record type ‘A’
  4. Enable ‘Alias’ toggle
  5. From the ‘Route traffic to’ dropdown, select ‘Alias to Elastic Beanstalk environment’, the region where your EB environment resides, and finally the public domain of your EB environment.
  6. Leave ‘Simple routing’ as the routing policy and ‘Evaluate target health’ enabled.

Finally, we’ll your configure your domain registrar to use Amazons name servers instead of any default name servers they may be using. For example, in Google Domains under DNS select ‘Custom name servers’. Add the four name servers from the AWS Route 53 NS record.

Give the records a few minutes to propagate, then use dig and whois to check that your DNS setup is correct. For example, you can check that your custom domain and EB environment domain point to the same public IP.

If you go to your custom domain in a browser and receive a timeout, it’s probably because browsers are forcing connection to HTTPS (port 443) but EB environments serve only on HTTP (port 80) by default. Read on to Setup SSL to install an SSL certificate and serve traffic on port 443.

Setup SSL on EB Environment

We’ll use certbot to automatically install and renew our certs in our EB environment. The general process is as follows:

  1. Install Certbot on our EC2 instances
  2. Open 443 port on EC2 instances
  3. Download and configure the certificate in Nginx
  4. Automatically renew the certificate

Install Certbot

We’ll use our EB configuration files described earlier to install certbot while bringing up EC2 instances.

Allow Traffic on Port 443

We’ll create another EB configuration file to allow traffic from any IP on port 443.

Donwload and Configure Certificate

We’ll create a script hook to run certbot after Nginx has been installed and configured on the new EC2 instance. The following file is a script hook as opposed to a configuration file, so it should be placed in .platform/hooks/postdeploy in our app root directory.

We also have to have an EB configuration file to grant execute permissions to that script hook.

Automatically Renew the Certificate

Finally, we’ll use EB configuration to create a crontab entry to renew the cert every 12 hours.

That’s it! Go ahead and redeploy your app and try connecting to the site. You should see the site being served over port 443 (i.e. a lock icon in the browser).

CI/CD on Elastic Beanstalk

Additional resources:

Where To Look For Logs

Here’s a list of EB log file locations and what they contain:

  • /var/log/eb-engine.log - All deployment steps. If EB configuration or app install fails, the logs will be here.
  • /var/log/cfn-init.log - EB extension configuration logs only.
  • /var/log/eb-hooks.log - EB script hooks.
  • /var/log/puma/ - Logs for Puma server.

For a full list of log file locations as well as how to customize locations, see the AWS guide.