Setting up AWS CICD
Tags: aws, cicd, ec2, webdev
Published: 2023-11-08 05:53:45

Continuous Integration and Continuous Deployment (CICD) are crucial for ensuring the efficient and consistent delivery of software applications. Amazon Web Services (AWS) offers a suite of tools and services to facilitate CICD pipelines. In this guide, we will walk you through the process of setting up a CICD pipeline on AWS, step by step.

## Overview
Before we dive into the details, let's outline the AWS services we'll be using in this setup:

**Roles:** These are used to define permissions for the services we will be using.
**CodeBuild:** This service builds your application code by fetching it from your GitHub repository and executing a set of defined commands.
**S3 Bucket:** CodeBuild uploads the build artifacts to an S3 bucket.
**EC2 Instance:** This is a Linux virtual machine where your application will run.
**CodeDeploy:** It's responsible for deploying your code from S3 to the EC2 instance.
**CodePipeline:** This service connects all the above services to create a pipeline for your CICD workflow.
Let's break down each step of setting up the CICD pipeline:

## 1. EC2

### Setup EC2 Roles

1. Navigate to IAM (Identity and Access Management) → Roles → Create Role.
2. Select "EC2" as the use case.
3. Select "AWSCodeDeployRole" and "AmazonS3ReadOnlyAccess."
4. Give your role a name, for example, "ec2-codedeploy-role."

## Setup EC2 Instance

1. Navigate to EC2 → Launch instance.
2. Choose "Ubuntu Linux" in the settings.
3. In Advanced details, under IAM instance profile, choose the role you created (e.g., "ec2-codedeploy-role").
4. Fill in all the necessary fields and name your instance (e.g., "hello-gov-ec2").

## Installing Required Dependencies

1. Navigate to the EC2 Dashboard.
2. Click on your instance.
3. Click "Connect" and then click "Connect" in the EC2 Instance Connect tab.
Now, you need to install several dependencies on your EC2 instance, including Node.js, PM2, and PostgreSQL. You can do this by creating and executing a shell script. Ensure that these tools are accessible from the root user.

```
#!/bin/bash
# Run all these commands as sudo

sudo su

# Update packages without prompts
sudo apt-get update -y
sudo apt-get upgrade -y

# Install the CodeDeploy agent on EC2
sudo yum install -y ruby
wget https://aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
sudo service codedeploy-agent start

# Install NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc

# Install LTS Node.js version (Hydrogen) without prompts
nvm install lts/hydrogen -y

# Install PM2 globally without prompts
npm install pm2@latest -g

# Installing Yarn
npm install -g yarn

# Install PostgreSQL DB
sudo apt install postgresql postgresql-contrib -y
# Also, create a DB and DB user
sudo -u postgres psql

# Create DB
CREATE DATABASE dbname_db;

# Select the DB
\c dbname_db

# Set Password
ALTER USER postgres WITH PASSWORD 'postgres';

echo "Installation complete."

```

## 2. S3 Bucket

1. Navigate to S3 Bucket → Create Bucket.
2. Give the bucket a name (e.g., "hello-gov-bucket").

## 3. CodeBuild

1. Navigate to CodeBuild → Create Build Project.
2. Give it a name (e.g., "hello-gov-codebuild").
3. Select a source (e.g., GitHub).
4. Connect your account, add the repository link, and fill in the required fields.
5. In Artifacts, select S3 and choose the bucket name (e.g., "hello-gov-bucket").
6. In namespace, choose BuildID.
7. Click "Create build project."

## 4. CodeDeploy

1. Navigate to CodeDeploy → Create application. Name the application and select the compute platform (EC2/on-premises).
2. Proceed to create a deployment group, name the deployment group.
3. In the service, attach the CodeDeploy service role you created for CodeDeploy.
4. In the environment configuration, select "Amazon EC2 instance," and choose the instance you created.
5. In the deployment setting, select "CodeDeployDefault.AllAtOnce."
6. Uncheck the "enable load balancing" option.
7. Then select "create deployment."

## 5. CodePipeline

1. Navigate to CodePipeline → Create pipeline.
2. Name the pipeline and select the default settings.
3. In the source provider, select GitHub (version 2), authenticate AWS with GitHub, and select your repository and branch.
4. In the build stage, select the CodeBuild project you created.
5. Add environment variables if needed.
6. In the deployment stage, select the CodeDeploy application and deployment group you created.
7. Then select "create pipeline."

## Note

- For the creation of CodeBuild, please refer to the appropriate documentation.
- For the creation of CodeDeploy, please refer to the relevant documentation.
- For the creation of CodePipeline, please refer to the corresponding documentation.
- You will find the scripts related to CodeBuild in the buildspec.yml and CodeDeploy in appspec.yml within your repository.
- Ensure that the above-mentioned files and the scripts directory are in the root directory of your project.

If everything is working correctly, navigate to the directory on your EC2 instance where your application is running. Now, it's time to install Nginx to act as a reverse proxy and run your application with PM2.

```
# Run the application by PM2 as the root user (inside the app directory)
pm2 start yarn --name projectname_build -- start:prod

# Check if the app is running
pm2 status
# Or
pm2 logs

# Install Nginx
sudo apt-get install nginx

sudo apt-get install certbot python3-certbot-nginx

# Get the SSL keys for the registered domain by
# Use Certbot to obtain SSL/TLS certificates for your domain:
sudo certbot --nginx -d api.yourdomain.dev

# Edit the Nginx configuration file
sudo nano /etc/nginx/sites-available/apiname

```
Inside the configuration file, write the following content:

```
server {
    listen 80;
    server_name api.yourdomain.dev;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /graphql {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Redirect HTTP requests to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name api.yourdomain.dev;

    ssl_certificate /etc/letsencrypt/live/api.yourdomain.dev/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.dev/privkey.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /graphql {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

```
Then create a symlink to the sites-enabled folder and test the Nginx configuration:

```
# Create the symlink to the sites-enabled
sudo ln -s /etc/nginx/sites-available/apiname /etc/nginx/sites-enabled/

# Test the config file
sudo nginx -t

# Reload Nginx
sudo systemctl reload nginx

```
Your AWS CICD setup is now complete, and your application is running with Nginx as a reverse proxy, secured with SSL/TLS.

## References

- [AWS CodeBuild Documentation](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html)
- [AWS CodeDeploy Documentation](https://docs.aws.amazon.com/codedeploy/latest/userguide/welcome.html)
- [AWS CodePipeline Documentation](https://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html)
- [Cloud and DevOps Services in USA](https://www.codingcrafts.io/services/cloud-and-devops-services)