<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vihaan Verma</title>
    <description>The latest articles on DEV Community by Vihaan Verma (@vihaanv07).</description>
    <link>https://dev.to/vihaanv07</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2893333%2Ff38c5292-a6b8-4ea0-b6a8-5efdc332f96e.png</url>
      <title>DEV Community: Vihaan Verma</title>
      <link>https://dev.to/vihaanv07</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vihaanv07"/>
    <language>en</language>
    <item>
      <title>Setting Up CI/CD for EC2 Deployment with AWS CodeDeploy</title>
      <dc:creator>Vihaan Verma</dc:creator>
      <pubDate>Wed, 26 Feb 2025 16:55:24 +0000</pubDate>
      <link>https://dev.to/vihaanv07/setting-up-cicd-for-ec2-deployment-with-aws-codedeploy-9h3</link>
      <guid>https://dev.to/vihaanv07/setting-up-cicd-for-ec2-deployment-with-aws-codedeploy-9h3</guid>
      <description>&lt;p&gt;In this guide, I'll walk you through the process of setting up a continuous integration and deployment (CI/CD) pipeline using GitHub Actions and AWS CodeDeploy for an EC2 instance. Having recently gone through this process myself and facing several challenges along the way, I wanted to share my experience to help others navigate this setup more smoothly.&lt;br&gt;
If you just want to see potential issues and fixes:&lt;br&gt;
See potential issues and fixes&lt;/p&gt;
&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When it comes to setting up a CI/CD pipeline with AWS CodeDeploy, there are two major approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; GitHub Actions&lt;/li&gt;
&lt;li&gt; AWS CodePipeline&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This article focuses on the GitHub Actions approach, demonstrating the deployment of a simple Node.js server. The process outlined here can be adapted for other applications with minor modifications to the scripts.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Create a Node.js Web App
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a simple Node.js application that we'll deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//app.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;   
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from our deployed Node.js application!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;    
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;    
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App listening at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to create a &lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"nodejs-aws-codedeploy-demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"A simple Node.js app for AWS CodeDeploy demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"app.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    
        &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"node app.js"&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    
        &lt;/span&gt;&lt;span class="nl"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"^4.17.1"&lt;/span&gt;&lt;span class="w"&gt;    

    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create the appspec.yml and Necessary Script Files
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;appspec.yml&lt;/code&gt; file is essential for AWS CodeDeploy to understand how to deploy your application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# appspec.yml &lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.0&lt;/span&gt;
&lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
&lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/ubuntu/my-express-app&lt;/span&gt;
&lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;BeforeInstall&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scripts/before_install.sh&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
      &lt;span class="na"&gt;runas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
  &lt;span class="na"&gt;AfterInstall&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scripts/after_install.sh&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
      &lt;span class="na"&gt;runas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
  &lt;span class="na"&gt;ApplicationStart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scripts/application_start.sh&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
      &lt;span class="na"&gt;runas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
&lt;span class="na"&gt;file_exists_behavior&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OVERWRITE&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Properties used above&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;OS&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Defines the &lt;strong&gt;operating system&lt;/strong&gt; of the deployment target.&lt;/li&gt;
&lt;li&gt;  Supported values:

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;linux&lt;/code&gt; → For Amazon EC2 instances running Linux.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;windows&lt;/code&gt; → For Windows Server instances&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Specifies &lt;strong&gt;which files should be copied&lt;/strong&gt; during deployment.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;source&lt;/code&gt;&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;.&lt;/code&gt; means the entire application directory in the deployment package. This is the local path.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;destination&lt;/code&gt;&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;/home/ubuntu/my-express-app&lt;/code&gt; is where the application will be copied to on the instance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Hooks define &lt;strong&gt;lifecycle event scripts&lt;/strong&gt; that run during different phases of deployment.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hook Properties&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;location&lt;/code&gt;&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Specifies the script to execute (e.g., &lt;code&gt;scripts/before_install.sh&lt;/code&gt;, local path).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;timeout&lt;/code&gt;&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Maximum time (in seconds) the script can run before timing out.

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Note&lt;/strong&gt;: Set it to a higher number for longer scripts (eg: if a script runs the build command)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;runas&lt;/code&gt;&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Specifies the user who runs the script (&lt;code&gt;ubuntu&lt;/code&gt; in this case).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  Reference: &lt;a href="https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, create the script files referenced in the &lt;code&gt;appspec.yml&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;scripts/before_install.sh&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# scripts/before_install.sh  &lt;/span&gt;

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;#download node and npm&lt;/span&gt;
curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
&lt;span class="nb"&gt;.&lt;/span&gt; ~/.nvm/nvm.sh
nvm &lt;span class="nb"&gt;install &lt;/span&gt;node

&lt;span class="c"&gt;#create our working directory if it doesnt exist&lt;/span&gt;
&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/home/ubuntu/my-express-app"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; exists"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; directory"&lt;/span&gt;
  &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;scripts/after_install.sh&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# scripts/after_install.sh  &lt;/span&gt;

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;#cd in working directory&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/ubuntu/my-express-app
&lt;span class="c"&gt;#add npm and node to path&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NVM_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.nvm"&lt;/span&gt; 
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/nvm.sh"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/nvm.sh"&lt;/span&gt;  &lt;span class="c"&gt;# loads nvm &lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/bash_completion"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/bash_completion"&lt;/span&gt;  &lt;span class="c"&gt;# loads nvm bash_completion (node is in path now)&lt;/span&gt;
&lt;span class="c"&gt;#install dependencies&lt;/span&gt;
npm i
npm i pm2 &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;scripts/application_start.sh&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# scripts/application_start.sh  &lt;/span&gt;

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;#give permission for everything in the express-app directory&lt;/span&gt;
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 777 /home/ubuntu/my-express-app

&lt;span class="c"&gt;#navigate into our working directory where we have all our github files&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/ubuntu/my-express-app
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NVM_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.nvm"&lt;/span&gt; 
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/nvm.sh"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/nvm.sh"&lt;/span&gt;  &lt;span class="c"&gt;# loads nvm &lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/bash_completion"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/bash_completion"&lt;/span&gt;  &lt;span class="c"&gt;# loads nvm bash_completion (node is in path now)&lt;/span&gt;

pm2 stop my-express-app
&lt;span class="c"&gt;#start our node app in the background&lt;/span&gt;
pm2 start app.js &lt;span class="nt"&gt;--name&lt;/span&gt; my-express-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our directory structure after the above steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqewxxzuasuigu08rqpke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqewxxzuasuigu08rqpke.png" alt="current directory" width="157" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Create the Necessary IAM Roles
&lt;/h2&gt;

&lt;p&gt;You'll need to create two IAM roles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; A role for your EC2 instance to communicate with CodeDeploy&lt;/li&gt;
&lt;li&gt; A service role for CodeDeploy&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  EC2 IAM Role:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  We need to create a new role with the &lt;code&gt;AmazonEC2RoleforAWSCodeDeploy&lt;/code&gt; policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, you need to go to the AWS console and select the IAM web service. Then select Roles under the Access management section.&lt;/p&gt;

&lt;p&gt;Then click "Create Role". You will see a dashboard like below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4irvriqwf10kbmr8wjkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4irvriqwf10kbmr8wjkh.png" alt="Create role" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select "AWS Service" as Trusted Entity Type and then select &lt;code&gt;EC2&lt;/code&gt; use case like below. Then click next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3w0mdrqqfiyh9eby7y4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3w0mdrqqfiyh9eby7y4.png" alt="ec2 use case role" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the permissions tab, select the permission &lt;code&gt;AmazonEC2RoleforAWSCodeDeploy&lt;/code&gt; like below. Then click next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb85t4yk9lqrhkkrtbnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb85t4yk9lqrhkkrtbnz.png" alt="permissions role" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give any meaningful name to your role, eg: &lt;code&gt;EC2CodeDeployRole&lt;/code&gt;. Then click Create Role.&lt;/p&gt;

&lt;h3&gt;
  
  
  CodeDeploy IAM Role:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Now we need to create a new role with the &lt;code&gt;AWSCodeDeployRole&lt;/code&gt; policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, you need to go to the AWS console and select the IAM web service. Then select Roles under the Access management section.&lt;/p&gt;

&lt;p&gt;Then click "Create Role". You will see a dashboard like below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4irvriqwf10kbmr8wjkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4irvriqwf10kbmr8wjkh.png" alt="Create role" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select "AWS Service" as Trusted Entity Type and then select &lt;code&gt;CodeDeploy&lt;/code&gt; use case like below. Then click next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1jjy7poi6710y24ti1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1jjy7poi6710y24ti1i.png" alt="Codedeploy use case" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the permissions tab, the required permission would already be selected, if not then select the permission &lt;code&gt;AWSCodeDeployRole&lt;/code&gt; like below. Then click next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjy0ad92ga9x0p4yxmwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjy0ad92ga9x0p4yxmwf.png" alt="Codedeploy role" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give any meaningful name to your role, eg: &lt;code&gt;CodeDeployServiceRole&lt;/code&gt;. Then click Create Role.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Spin Up EC2 Server with Necessary Configurations
&lt;/h2&gt;

&lt;p&gt;First, you need to go to the AWS console and select EC2 service. Then select Instances under the Instances section.&lt;/p&gt;

&lt;p&gt;Then click "Launch Instance". Give a name to the instance and select Ubuntu Operating system (you can choose any, this tutorial follows with Ubuntu). You will see a dashboard like below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9s21dipix6akatxs6b6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9s21dipix6akatxs6b6.png" alt="Launch instance dashboard" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set the Keypair Login, this is used for SSH connections to the instance. Use an existing Key Pair or create a new one.&lt;/p&gt;

&lt;p&gt;After that go to the Advanced details section at the bottom. In the IAM instance profile select the &lt;code&gt;EC2CodeDeployRole&lt;/code&gt; role that you had created earlier.&lt;/p&gt;

&lt;p&gt;Then scroll to the bottom till &lt;code&gt;User Data&lt;/code&gt; and paste the following script there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38a640izhazcuv5inby7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38a640izhazcuv5inby7.png" alt="user data script" width="800" height="370"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Update package list and install Ruby and wget using apt&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ruby-full &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;wget &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;span class="c"&gt;# Change to the home directory and download the CodeDeploy installation script&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/ubuntu
wget https://aws-codedeploy-ap-south-1.s3.ap-south-1.amazonaws.com/latest/install

&lt;span class="c"&gt;# Make the script executable and run it to install the CodeDeploy agent&lt;/span&gt;
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x ./install
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./install auto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then click "Launch Instance".&lt;/p&gt;

&lt;p&gt;After launching, SSH into your instance and check the installation of the CodeDeploy Agent:&lt;/p&gt;

&lt;p&gt;run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status codedeploy-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see status active(running) then it was installed correctly. If it doesnt show active or shows some error.&lt;/p&gt;

&lt;p&gt;Run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;see if there is an install script in the current directory.&lt;br&gt;
If there is, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ruby-full &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;wget &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;span class="c"&gt;# Change to the home directory and download the CodeDeploy installation script&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/ubuntu
wget https://aws-codedeploy-ap-south-1.s3.ap-south-1.amazonaws.com/latest/install

&lt;span class="c"&gt;# Make the script executable and run it to install the CodeDeploy agent&lt;/span&gt;
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x ./install
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./install auto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Set Up CodeDeploy Application and Deployment Group
&lt;/h2&gt;

&lt;p&gt;In the AWS Management Console:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Navigate to CodeDeploy&lt;/li&gt;
&lt;li&gt; Select Applications from the left bar under Deploy&lt;/li&gt;
&lt;li&gt; Then click "Create Application"&lt;/li&gt;
&lt;li&gt; Create a new application

&lt;ul&gt;
&lt;li&gt;  Select "EC2/On-premises" as the compute platform&lt;/li&gt;
&lt;li&gt;  Give it a meaningful name&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5g7dbi4lgnqmmievjtqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5g7dbi4lgnqmmievjtqc.png" alt="create application codedeploy" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create a deployment group

&lt;ul&gt;
&lt;li&gt;  Enter a deployment group name&lt;/li&gt;
&lt;li&gt;  Select the CodeDeploy service role created earlier &lt;code&gt;CodeDeployServiceRole&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Choose "In-place deployment" as the deployment type&lt;/li&gt;
&lt;li&gt;  Select EC2 Instances in Environment Configuration&lt;/li&gt;
&lt;li&gt;  Select your EC2 instance(s) using tag "name"&lt;/li&gt;
&lt;li&gt;  Configure deployment settings (I recommend starting with "CodeDeployDefault.AllAtOnce")&lt;/li&gt;
&lt;li&gt;  Disable load balancing initially for simplicity&lt;/li&gt;
&lt;li&gt;  Click "Create Deployment Group"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tns114owhos45b2o6dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tns114owhos45b2o6dg.png" alt="deployment group name" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2bd5fq3zv06hiwkreq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2bd5fq3zv06hiwkreq4.png" alt="config deployment group " width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Connect GitHub through a Manual Deployment
&lt;/h2&gt;

&lt;p&gt;Before setting up GitHub Actions, perform a manual deployment to ensure everything works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create a github repository and push your code to it.&lt;/li&gt;
&lt;li&gt; Copy the commit hash of the latest commit.&lt;/li&gt;
&lt;li&gt; In the CodeDeploy console, select your application and deployment group&lt;/li&gt;
&lt;li&gt; Click "Create deployment"

&lt;ul&gt;
&lt;li&gt;  Select "My application is stored in GitHub" and enter a token name in the input&lt;/li&gt;
&lt;li&gt;  Then click Connect Token and grant the required permissions&lt;/li&gt;
&lt;li&gt;  Then after the token is connected, in the repository name, enter your repository like "&lt;code&gt;username&lt;/code&gt;/&lt;code&gt;repository-name&lt;/code&gt;"&lt;/li&gt;
&lt;li&gt;  Then enter the hash of the latest commit&lt;/li&gt;
&lt;li&gt;  Then click "Create Deployment"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; Monitor the process&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ovax6casw2ndga7kkqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ovax6casw2ndga7kkqa.png" alt="manual deployment creation" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Set Up GitHub Identity Profile
&lt;/h2&gt;

&lt;p&gt;In the AWS Management Console:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Navigate to IAM Console&lt;/li&gt;
&lt;li&gt; Select Identity Providers under Access Management&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyc34t111w1ojvlu5f35x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyc34t111w1ojvlu5f35x.png" alt="identity provider" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Select OpenID Connect as the provider type&lt;/li&gt;
&lt;li&gt; Enter &lt;a href="https://token.actions.githubusercontent.com" rel="noopener noreferrer"&gt;https://token.actions.githubusercontent.com&lt;/a&gt; as the Provider URL&lt;/li&gt;
&lt;li&gt; Enter sts.amazonaws.com as the audience&lt;/li&gt;
&lt;li&gt; Click Add Provider&lt;/li&gt;
&lt;li&gt; Then Select the created provider from the identity provider section&lt;/li&gt;
&lt;li&gt; Click Assign role, and then Create new role&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqg1tz8u2jmb15nau45r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqg1tz8u2jmb15nau45r.png" alt="create a new role identity provider" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Select Web Entity as the Trusted Entity Type&lt;/li&gt;
&lt;li&gt; Then Select the audience, and enter your username in Github Organization and the repository name and branch name&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn0c89owqao48i44m6mh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn0c89owqao48i44m6mh.png" alt="config" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In permissions select &lt;code&gt;AWSCodeDeployFullAccess&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7ddrjwepyskcnua8xkb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7ddrjwepyskcnua8xkb.png" alt="permissions" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give a name and click create role&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the Role under Roles tab and copy its ARN.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 8: Set Up GitHub Actions Workflow
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt; file in your repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# name: Connect to an AWS role from a GitHub repository&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;AWS_REGION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;AWS_REGION&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Change to reflect your Region&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;  &lt;span class="c1"&gt;# Required for requesting the JWT&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;   &lt;span class="c1"&gt;# Required for actions/checkout&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;AssumeRoleAndCallIdentity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Git clone the repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v1.7.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;ARN from previous step&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;role-session-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GitHub_to_AWS_via_FederatedOIDC&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.AWS_REGION }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STS GetCallerIdentity&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;aws sts get-caller-identity&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create CodeDeploy Deployment&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;aws deploy create-deployment \&lt;/span&gt;
          &lt;span class="s"&gt;--application-name &amp;lt;APPLICATION_NAME&amp;gt; \&lt;/span&gt;
          &lt;span class="s"&gt;--deployment-group-name &amp;lt;DEPLOYMENT_GROUP_NAME&amp;gt; \&lt;/span&gt;
          &lt;span class="s"&gt;--deployment-config-name CodeDeployDefault.AllAtOnce \&lt;/span&gt;
          &lt;span class="s"&gt;--github-location repository=${{ github.repository }},commitId=${{ github.sha }}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et Voila! Your CI/CD setup is complete, you can now make changes and see the changes update through the pipeline. You can also monitor the deployments from the CodeDeploy Deployments section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Tips
&lt;/h2&gt;

&lt;p&gt;During my implementation, I encountered several specific issues that might save you hours of debugging:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Script Not Found Error&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Scripts failed with "not found" errors despite being in the correct location&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cause&lt;/strong&gt;: DOS line endings in script files edited on Windows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Convert scripts to Unix format using the &lt;code&gt;dos2unix&lt;/code&gt; utility:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;dos2unix
 dos2unix scripts/&lt;span class="k"&gt;*&lt;/span&gt;.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deployment Issues with Organization Repositories&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: CodeDeploy fails to access GitHub organization repositories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cause&lt;/strong&gt;: Restricted third-party OAuth access settings in organization settings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;Remove restrictions on third-party OAuth applications in your organization settings&lt;/li&gt;
&lt;li&gt;Always run a manual deployment first to verify GitHub access before setting up GitHub Actions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Permission Problems&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Scripts fail during execution despite being executable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cause&lt;/strong&gt;: Running scripts as root instead of the EC2 instance's default user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Modify your appspec.yml to run scripts as the correct user (e.g., "ubuntu" for Ubuntu instances):
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;BeforeInstall&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scripts/before_install.sh&lt;/span&gt;
       &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
       &lt;span class="na"&gt;runas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monorepo Deployment Challenges&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Difficult to deploy specific parts of a monorepo through GitHub&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cause&lt;/strong&gt;: Complex and hacky error-prone method of moving app specific appspec.yml to root during github actions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use S3 as an intermediary:

&lt;ul&gt;
&lt;li&gt;Configure GitHub Actions to zip only relevant directories&lt;/li&gt;
&lt;li&gt;Upload the zip to S3&lt;/li&gt;
&lt;li&gt;Configure CodeDeploy to deploy from S3 instead of directly from GitHub&lt;/li&gt;
&lt;li&gt;This provides more flexibility in what gets deployed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Setting up a CI/CD pipeline with GitHub Actions and AWS CodeDeploy might seem complex initially, but once you understand the components and their interactions, it becomes a powerful tool for automating your deployments.&lt;/p&gt;

&lt;p&gt;This approach allows you to automate deployments directly from your GitHub repository without the need for additional AWS services like CodePipeline, making it more cost-effective and straightforward for many use cases.&lt;/p&gt;

&lt;p&gt;Happy deploying!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cicd</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
