AWS Application Deployment: Getting Started with AWS CodeDeploy & GitHub

Media Temple has been helping developers, designers, and content creators move a variety of workflows to the cloud since 2015. As an Amazon Web Services (AWS) Advanced Consulting Partner and a trusted provider of reliable web hosting, we understand the needs — and growing pains — associated with transitioning to AWS. 

The good news is that Amazon Web Services offers a number of robust tools that can help you rapidly scale while minimizing deployment errors — and better manage costs and resources.

To help you get started, we’ve outlined the steps you’ll need to take to get up and running in the cloud with either BitBucket and AWS CodeDeploy or AWS CodePipeline and Github. Once set up, this application deployment process will minimize deployment errors, removing the need for a network file system and drastically reducing associated cloud costs. 

Prerequisites

We’ve outlined a few prerequisites you’ll need to have to successfully deploy to the cloud using CodePipeline and CodeDeploy. 

AWS CodeDeploy

Before you use CodeDeploy, you’ll need to sign up for an AWS account if you don’t have one already. We are happy to help you get started. If you are a Media Temple customer already, please contact your customer success manager.  

You can navigate to https://aws.amazon.com/ and choose Create an AWS Account.

  1. Once your AWS account is created, follow these instructions to create an AWS Identity and Access Management (IAM) user for CodeDeploy. IAM helps you securely control who is authenticated and authorized to access and use AWS services and resources. 
  2. Next, you’ll need to install (or upgrade) and configure the AWS CLI
  3. Create a service role for CodeDeploy to grant sufficient privileges.
  4. Finally, create an IAM instance to allow Amazon EC2 to work on your behalf. 

GitHub Account & Git Usage

A second important prerequisite to this tutorial is a GitHub account. This service offers hosting for source code management using Git. 

You can create a GitHub account if you don’t have one already, but we recommend a thorough understanding of Git before setting up your application deployment process. 

CodeDeploy & Github

Already installed AWS CodeDeploy and set up your GitHub account? Great, let’s get started. For the purpose of this tutorial, we’ll be using a WordPress website, AWS, and Media Temple Managed Services for AWS. 

1. Download Event Scripts for Load Balancing

To begin, download the following example from GitHub: https://github.com/aws-samples/aws-codedeploy-samples/tree/master/load-balancing/elb-v2

This event script sample will help you register your AWS instance with a load balancer, essentially preventing your website traffic from being sent to a service during deployment. 

2. Define Environment Branches

Next, you’ll need to determine what branch will be used to deploy to each AWS environment. In most cases, you’ll be deploying a “master” branch to production and a “staging” branch to your staging environment. 

You can easily create or delete existing branches within your repository by following these official GitHub instructions.

Another important consideration is notifying your hosting provider about your branches. For example, Media Temple customers will need to advise the support team of this mapping to complete the setup. 

3. Create Automation User & Access Token

To access protected environments, you’ll need to create a GitHub personal access token with full administrative access to your repository. 

As a recommendation to follow security best practices and further isolate your environment, create a new “Automation User” to obtain the token, instead of using a personal user profile. 

4. Add Load Balancing Event Scripts to Repo

Remember those GitHub event scripts you downloaded in step 1? Copy the samples into your GitHub repository. 

You’ll need to ensure that the following directory hierarchy is respected:

  • Move all scripts to a scripts folder.
  • Move all web files to a web folder. 
  • Keep the appsec.yaml file at the root level.
  • Keep the README.MD file at the root level.

You can read more about these assets from GitHub’s help documentation.

Web folder

5. Adjust the appsec.yaml Paths

To ensure that the script handles the appropriate destination in your website, you’ll need to adjust the appsec.yaml file to match the path of your files and scripts. 

appsec.yaml file

6. Add New ValidateService

In this same appsec.yaml file, add a new ValidateService hook to run custom Media Temple sizing validation:

ValidateService:

– location: scripts/validate_service.sh

This should be entered under hooks, as seen below. 

Validate Service

7. Create validate_service.sh & Add to Scripts

To ensure that your AWS scaling size is properly set in case CodeDeploy fails, create a file named validate_service.sh and place it inside the /scripts directory with the following contents:

–  /usr/local/bin/mt-codedeploy ensure-asg-min

8. Configure appspec.yaml Permissions

The final setup step is an important one: 

To ensure that your files and directories are associated with the correct users and groups, properly define the permissions attribute in appspec.yaml. Amazon has some excellent documentation to guide you through the available configuration options.

version: 0.0

os: linux

files:

           – source: /web

           destination: /path/to/doc/root

permissions:

           – object: /path/to/doc/root

            owner: cms.web.com

            group: cms.web.com

hooks:

Security Considerations: Configuration Files

While you might choose to commit application configuration files into your Git repo, we recommend instead storing your secrets in an AWS’s System Manager (SSM) service. You can use a template to create your config files or store them as environment variables at runtime. 

Media Temple customers will need to reach out to our support team to adjust access to include SSM permissions. After this is complete, you’ll be able to add new Secure Strings to SSM using the AWS Console or CLI (Command Line Interface).

Environment Variables

If you intend to use environment (ENV) variables, you can create a script to read SSM variables and store them as ENV variables at runtime. These can be called during your Code Deploy hook. We encourage you to research this method thoroughly to ensure proper implementation. 

Ansible

For easy templating, you can use Ansible to easily build template files and manage secrets in SSM. This process ensures that your application secrets are never directly stored in GIT, significantly enhancing the security of your setup. 

Important Note:  The keys found in the SSM must exactly match the variables used in Ansible.

We’ve provided an example of an Ansible Playbook that you can use to easily template your files. We encourage you to prefix any secrets with the application name in this example, we used /wordpress/.

Ansible Playbook:

- name: "Set SSM_DICT dict fact"

set_fact:

SSM_DICT: "{{ lookup('aws_ssm', '/wordpress/', region='us-west-2',

bypath=true, recursive=true, shortnames=true ) }}"

- name: "For each item in dict, set fact"

set_fact:

"{{ item.key }}": "{{ item.value }}"

loop: "{{ SSM_DICT | dict2items }}"

- name: "Configure WordPress Config"

template:

src: wp-config.php.j2

dest: /path/to/doc/root/wp-config.php

mode: 0644

vars:

DB_PASSWORD: "{{ DB_PASSWORD }}"

DB_NAME: "{{ DB_NAME }}"

DB_USER: "{{ DB_USER }}"

DB_HOSTNAME: "{{ DB_HOSTNAME }}"

To properly set up Ansible you will need to essentially convert your wp-config.php file into a JINJA 2 template. To accomplish this, copy over your wp-config.php file into the Ansible template folder and change the strings to variables filled by Jinja2.

Before: 

// ** MySQL settings - You can get this info from your web host ** //

/** The name of the database for WordPress */

define( 'DB_NAME', 'database_name_here' );

/** MySQL database username */

define( 'DB_USER', 'username_here' );

/** MySQL database password */define( 'DB_PASSWORD', 'password_here' );

/** MySQL hostname */

define( 'DB_HOST', 'localhost' );
After: 

// ** MySQL settings - You can get this info from your web host ** //

/** The name of the database for WordPress */

define( 'DB_NAME', '{{ DB_NAME}}' );

/** MySQL database username */

define( 'DB_USER', '{{ DB_USER }}' );

/** MySQL database password */

define( 'DB_PASSWORD', '{{ DB_PASSWORD }}' );

/** MySQL hostname */

define( 'DB_HOST', '{{ DB_HOSTNAME }}' );

Questions & Tutorials

An application deployment process like the one outlined above can significantly increase uptime and streamline your processes by removing the need for a network file system. 

Sounds idyllic, right? But if you’ve never set up AWS before and are looking for a tutorial, we encourage you to watch the replay of our webinar App Deployments on Amazon Web Services using CodeDeploy and GitHub.

Our AWS professionals will show you how to easily push from your staging to production environments with fewer errors and more redundancy. 

Have a question or comment about these setup instructions? Our team is always happy to help! Shoot us an email at support@mediatemple.com to get in touch. 

About the Author Eddie Jauregui is a product manager for Media Temple's Managed Services for AWS. Having been with Media Temple for over 5 years, he makes it his personal mission to deliver simplicity-as-a-service while helping customers solve for problems through solutions in products. More by this Author