Part I: Setting Up AWS CodeDeploy/CodePipeline to Automate the Deployment of a Node Web Service

By Bobby Gill on November 24, 2021

At Blue Label Labs, we build a lot of apps! For many of those apps we use Node to build out JSON-based web services that provide backend functionality to these apps. Our typical deployment of a Node backend involves hosting the Node app on a Linux-based EC2 machine. As part of our development process, we leverage AWS CodePipeline/CodeDeploy CD/CI tools to automate the deployment of these backend components every time a PR is merged into a deployment branch. In this series of articles, I will walk through the step-by-step process necessary to create and configure everything needed to get CodePipeline/CodeDeploy to deploy a Node powered web service to a EC2 machine.

This is Part 1 of 3 articles that walk through the various steps necessary to get the CD/CI pipeline working. In this article, I walk through the necessary setup and preparation of the AWS and EC2 environments that is required prior to actually setting up the pipeline. Once you are done with these steps, please look at Part II which outlines the scripts and configuration necessary to work with CodeDeploy. Finally, Part III outlines the setup of the CodeDeploy and CodePipeline applications to bring the entire pipeline to life.

Applies To:

  • The deployment of a Node-based web service project to an EC2 machine in AWS. (This guide does not cover the setting up of a CodePipeline for deploying web apps frontends)
  • This example assumes the use of NGINX as the web server on the EC2 machine and that the EC2 machine sits behind a load balancer which handles SSL termination, thus all traffic to the EC2 machine is done over HTTP.
  • The source code repository is assumed to be a Bitbucket git repository using a deployment branch strategy. In this example, I will walk through the steps of setting up a sandbox environment that is fed off a source branch named ‘sandbox’.

Prerequisites

  • An AWS account and administrator level permissions to it.
  • SSH access to a Amazon Linux EC2 machine to be used as the target of the deployment.
  • A Source code repository hosted on Bitbucket.
  • The specific version of Node used to build the project.

1. Configure IAM Roles and Policies

The first thing we need to do is setup the Roles necessary to enable an EC2 machine to receive deployments from CodeDeploy. There are 2 seperate roles that need to be defined, one that will be used by CodeDeploy and the second which will be attached to the EC2 machine and used by it to access artifacts generated by CodeDeploy.

Create an IAM Policy and Role to be Used by the EC2 Instance

  • Login to the IAM console in AWS, under Policies click “Create Policy”.
  • In the resulting screen, paste the following JSON policy document which will grant our EC2 instance access to read from any S3 bucket in the AWS account:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:Get*",
                "s3:List*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
  • Name the policy “CodeDeploy-EC2-Permission” and save it.
  • Now under Roles, create a new Role with the following options:
    • Service: EC2
    • Permissions: Find and select the “CodeDeploy-EC2-Permission” created previously.
    • Name: “EC2-Instance-Role”

Create IAM Role to be Used by the CodeDeploy Service

  • Within the IAM console, go to Roles, click “Create Role” and create a new Role with the following options:
    • Service: CodeDeploy
    • Use Case: CodeDeploy
    • Permissions: The built in policy named AWSCodeDeplkoyRole should already be selected by default.
    • Name: “CodeDeploy-Role”

Attach “EC2-Instance-Role” Role to the EC2 Instance

  • Open up the EC2 console, find the EC2 instance that is to be used as part of this deploy, select it, and then under Actions->Security, select “Modify IAM Role”.
  • In the resulting screen, select the Role named “EC2-Instance-Role”.
  • With the same EC2 machine selected, click the Tags tab and then click “Manage Tags”.
  • In the Tag editing screen, add a new Tag to the EC2 instance with a Key of “EC2-Sandbox”, leave the Value blank. This tag is what CodeDeploy is going to use to identify which EC2 machine to deploy to.

2. Configure the EC2 Machine

An important step in the setup of CodeDeploy is to first setup and prep our EC2 machine with the necessary components and configurations to host the Node project once it is deployed. In this guide, we are looking at deploying a Node project that will be hosted on a NGINX web server running on the machine, with the Node process being managed by the PM2 orchestration tool. The following steps will walk through setting up each of these components.

Note, that for both the install of NVM and PM2, I do these steps as the root user (by first doing a sudo -i). Before your cheeto encrusted fingers start lambasting me on the pitfalls of doing things as ‘root’, trust me, I know. It’s just simpler to get everything setup and running when done as the root user.

Prepare the Directory to Host the Deployed App

SSH into the EC2 machine and create a directory where you will look to deploy the Node project. Since I have fond memories of Apache, I generally create a new directory under the path /var/www/html/<project name>, where project name is the name of the top level folder where your Node project will deploy. At Blue Label Labs, we generally use the internal project code as the project name in these contexts.

Install Node Version Manager (NVM)

We are going to be using NVM on the EC2 machine to install the specific version of Node needed.

  • To install NVM onto the EC2 machine, follow the instructions here. Remember to install NVM under the root user.
  • Once NVM is installed, install the specific version of Node needed by your project. For example, if you are using Node 14.9.0, you will type in:
nvm install 14.9.0

Install the CodeDeploy Agent

We need to configure the CodeDeploy agent on the Ec2 machine, this is the service that is going to connect to CodeDeploy and perform the deployments on this machine when instructed. While there is now the option for the CodeDeploy agent to be automatically installed and updated by the CodeDeploy application, I like to do this part myself as I have run into a bunch of issues with CodeDeploy being unable to install the agent.

The instructions to install the CodeDeploy agent can be found in this article

Install and Configure NGINX

Within the SSH session, install NGINX by running:

sudo amazon-linux-extras install nginx

Once NGINX is installed, then you will need to configure it to properly forward all HTTP requests received by the EC2 machine to the running Node instance. There are many different ways to skin the NGINX feline, for simplicity we edit the /etc/nginx/nginx.conf file and make it look like the following:

  server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location /elb-status {
                access_log off;
                return 200 'healthy!\n';
                add_header Content-Type text/plain;
        }

        location /api {
               proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        Host $http_host;
                proxy_pass              http://127.0.0.1:4200 #Replace 4200 with whatever port your Node service listens on

       }
}

The first NGINX configuration block under /elb-status is a simple endpoint we create that always returns a 200 when the /elb-status path is called. This is used by the Application Load Balancer we setup to test whether a particular EC2 instance is healthy or not. The second configuration element instructs NGINX to forward any request under the /api path to the Node service we are going to have listening on port 4200. (Change this to the port that your Node project is using)

Once you make the above changes make sure to restart the NGINX service by typing:

sudo service nginx restart

Install Sequelize-CLI

If you are using Sequelize as the tool to manage and database migrations in Node, then you will need to make sure the Sequelize CLI is installed globally on the machine. Under the root context, type in the following:

npm i -g sequelize-cli

Install PM2

Finally, the last step to configuring the EC2 machine is to install the PM2 tool via npm. Once again, using the root context, execute the following:

npm i -g pm2

At this point, we now have completed preparation of the AWS account and the EC2 machine in order for it to be used by CodePipeline and CodeDeploy to deploy a Node web service project onto it. In the next part, I will cover the how to add the appropriate scripts needed by CodeDeploy and then finally the steps necessary in the AWS UI to create the CodePipeline that will bring all of these pieces together.

This Part 1 of a 3-part series that walks through the steps of using Amazon CodePipeline and CodeDeploy to automate the deployment of a Node based web service to an EC2 environment. After reading this article, please make sure to review Part II and Part III