App Deployments on Amazon Web Services using CodePipeline and GitHub


Browse by products and services

  • Applies to: AWS
    • Difficulty: Easy
    • Time Needed: 45
    • Tools Required: Command line access, GitHub Account

Prerequisite

  • AWS CodeDeploy
  • GitHub Account
  • Strong understanding of Git usage

Instructions

  1. Download the following example
    1. https://github.com/aws-samples/aws-codedeploy-samples/tree/master/load-balancing/elb-v2
  2. Determine what branch will be used to deploy to each AWS Environment. In most cases, customers will deploy "master" to production and a branch named "staging" to staging. Ensure to advise Media Temple of this mapping through a support request.

    Submit MT Support Request:
    Please ensure to advise Media Temple Managed Operations of this mapping through a support request.
    https://support.mediatemple.net

  3. Create a GitHub personal access token, which has full admin access to the repo you wish to deploy. Generally speaking, we suggest creating a new "Automation User" rather than using a personal user.
  4. Copy the code from step 1 into your repo. The files should be put in the following directory hierarchy:
    1. The appspec.yaml file must remain at the root level.
    2. All scripts should be moved into a "scripts" folder.
    3. All web files should be moved into a "web" folder. In this example, we are dealing with a WordPress site.
      README.md
      The README.MD file can stay at the root level. You can add a README file to your repository to tell other people why your project is useful, what they can do with your project, and how they can use it. Here is a link where you can read more about READMEs: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-readmes
      aws-1.png
  5. The appspec.yaml file should be adjusted with the path to your files and scripts:
    aws-2.png
  6. In the appspec.yaml file you will add a new ValidateService hook to run a custom Media Temple sizing validation.
    aws-3.png
  7. Create a file named "validate_service.sh" inside the scripts folder. That file should contain the following content:
    /usr/local/bin/mt-codedeploy ensure-asg-min
    This script ensures your ASG size is properly set in certain cases where previous AWS CodeDeploys fail.
  8. We would suggest using the permissions attribute in the app spec files to ensure your files and directories have the correct users and groups.
    Permissions in appspec.yaml:

    Please reference the appspec.yaml documentation for available options: https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file.html#reference-appspec-file-spacing

    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:
    

Secret Storage

While some customers choose to commit their application configuration files into their Git repo, we generally would suggest storing your secrets in AWS's SSM service and using a template to create those config files or storing them as ENV vars at runtime. After you request Media Temple adjust your access to include SSM permissions, you can add new Secure Strings to SSM using the AWS Console or CLI.

Environment Variables

If you wish to use ENV vars, you can create a script, which you call during any AWS CodeDeploy hook, to read the variables from SSM and store them as system ENV vars. Media Temple does not have any examples or tooling to provide on this method.

Ansible

To ease the templating, we suggest using Ansible, as it makes it quite easy to template files and use secrets in SSM. Below is an example of an Ansible Playbook that accomplishes this:

NOTE: The keys in SSM Parameter Store must be the exact same as the variables used in Ansible, for this to work. We also suggest prefixing the secrets with the application name. In this example, that is /wordpress/

- 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 }}"

For this to work, you essentially convert your wp-config.php file into a Jinja2 template. To do this, you will need to 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 }}' );

This process ensures your application secrets are never stored in Git. For more information on using Ansible Templates, please view: