DEV Community

Ashwin Venkatesan
Ashwin Venkatesan

Posted on

AWS CI/CD Made Easy: Build, Deploy, Repeat.

🚀 Tired of deploying your app manually every time you push code to GitHub?
What if I told you that with just a few clicks, you can automate the entire process — from a GitHub commit to your app running live on an EC2 instance.

In this tutorial, I’ll walk you through how AWS Developer Tools — CodeBuild, CodeDeploy, and CodePipeline — work together to create a seamless deployment pipeline. No more manual SSH into EC2, no more missed steps — just commit, build, deploy, repeat.

🔧Prerequisites
Before we jump into AWS, here’s what you’ll need:

  • Source Control: GitHub (you can also use CodeCommit, but here we’ll stick with GitHub).
  • Compute: EC2 instance.
  • CI/CD Tools: CodePipeline, CodeBuild, CodeDeploy.
  • IAM Roles: We’ll create service roles for CodePipeline, CodeBuild, and CodeDeploy, and instance profile for EC2.
  • Sample Application: This works with any stack — Node.js, Python, Java, or even a static website.
  • 👉 If you don’t have one, feel free to fork my GitHub repo and use that as your sample app.
  • Link to my Github repo: https://github.com/Imash24/AWS-CI-CD-DEMO

Step 1: Create an EC2 Instance:

  • Go to the EC2 Console → Launch a new instance.
  • Pick Amazon Linux 2 (free-tier eligible).
  • Create/attach a security group that allows:
  • Port 22 (SSH) → so you can connect to it.
  • Port 3000 (or whatever port your app runs on) → so you can actually access your app in the browser.

Once your Instance is up, you can use ssh to connect to your Instance or easiest way is to use EC2 Instance Connect.

After Connecting to your Console , We need to install the node.js as well the Codedeploy agent.

👉 But wait, what’s this CodeDeploy Agent thing?
Think of it as a messenger that lives inside your EC2 instance. When AWS CodeDeploy pushes a deployment, the agent is the one that:

  • Listens for instructions from the CodeDeploy service.
  • Pulls the application files (artifacts) from S3 or GitHub.
  • Runs the scripts you define in appspec.yml (like install dependencies, restart the app, etc.).

Without the agent, your EC2 has no idea that CodeDeploy even exists — so it’s a must-have.

Now Lets install the Node.js and CodeDeploy agent.

# Update packages
sudo yum update -y  

# Install Node.js and npm
sudo yum install -y nodejs npm  

# Install CodeDeploy Agent
sudo yum install -y ruby wget
cd /home/ec2-user
wget https://aws-codedeploy-<your-region>.s3.<your-region>.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
sudo service codedeploy-agent start

Enter fullscreen mode Exit fullscreen mode
  • Make sure to replace {your-region} to match your region, in my case it is ap-south-1.

Verify the CodeDeploy Agent

Now that we’ve installed the CodeDeploy agent, let’s make sure it’s actually running.

Run this command:

sudo systemctl status codedeploy-agent.service 
Enter fullscreen mode Exit fullscreen mode

Step 2: Setting up CodeDeploy Application

Now We have created an Ec2 instance and also setup the CodeDeploy agent on EC2, Lets set up the CodeDeploy Application.

A CodeDeploy Application = just a container that represents your app in AWS.

1️⃣ Create a CodeDeploy Application

  • Go to the AWS CodeDeploy Console → Applications → Create application.
  • Give it a name (e.g., cicd-demo-app).
  • Choose Compute platform → EC2/On-premises.

2️⃣ Create a Deployment Group:

Inside your application, click Create deployment group.

Give it a name (e.g., cicd-app-deployment-grp).

Service role:
You’ll need a service role for CodeDeploy (something like CodeDeployServiceRole).

Attach the managed policy: AWSCodeDeployRole.
This allows CodeDeploy to talk to your EC2.

Lets Create an Service role for CodeDeploy,

  • Go to the IAM Console → Roles → Create role.
  • For Trusted entity type, choose AWS service.
  • For Use case, select CodeDeploy → CodeDeploy.
  • Click Next and attach the managed policy:
  • AWSCodeDeployRole (this gives CodeDeploy the permissions it needs).
  • Give the role a name (e.g., CodeDeployServiceRole).
  • Click Create role.

Environment configuration:

  • Choose Amazon EC2 instances.
  • Pick your EC2 using Tags, My case i tagged as server.

Deployment settings:
Choose “One at a time” for simplicity (safe deployment).
Once done, CodeDeploy knows:
👉 “This application gets deployed to this EC2 instance with these rules.”

Step 3: Create a CodeBuild Project:
Now We Created and also setup the CodeDeploy that actually knows where to deploy our application (EC2).

1️⃣ Go to CodeBuild Console

  • Click Create build project.
  • Give it a name (e.g., cicd-demo-build).

2️⃣ Configure Source
Source provider: GitHub (connect your repo or forked repo). Or simply you can select the public repository option and paste my GitHub repository. link.

3️⃣ Environment

  • Environment image: Managed image.
  • Operating system: Amazon Linux 2.
  • Runtime: Standard.
  • Service role: Create a new role (CodeBuild will do this automatically).

4️⃣ Buildspec

The buildspec.yml file gives main instructions to ** CodeBuild.** It tells AWS exactly how to build your application — whether that’s installing dependencies, running tests, or packaging files.

I’ve already pushed my own buildspec.yml file into my GitHub repo, so CodeBuild will automatically pick it up during the build stage.

👉 In short, this file is where we define:

  • How to install dependencies
  • How to run build/test steps
  • What files should be bundled as artifacts for deployment

CodeBuild Completed Successfully!
We’ve set up and completed our CodeBuild project, and our application can now be built automatically using the instructions we defined in the buildspec.yml file. (The YAML handles dependency installation, build, and artifact creation).

  • The next logical step is to orchestrate the entire CI/CD flow — and that’s exactly where AWS CodePipeline comes in.

🚀 What is CodePipeline?

AWS CodePipeline is a fully managed CI/CD orchestration service that automates the software release process. It connects different stages of delivery — Source → Build → Test → Deploy — into a single continuous pipeline.

  • With CodePipeline, every time you push code to your repository:
  • The pipeline automatically detects the change (via webhook or polling).
  • It triggers CodeBuild to build and test the application.
  • Once artifacts are ready, it hands them over to CodeDeploy (or another deploy service).
  • The application is deployed to the target environment (EC2, ECS, Lambda, etc.).

1️⃣ Go to CodePipeline in AWS Console
Open the AWS Management Console → Search for CodePipeline → Click Create pipeline and select Build a custom pipeline.

2️⃣ Pipeline Settings

Pipeline name → cicd-demo-pipeline (you can name it anything you want).
Service role → Select “New service role” (AWS will automatically create a role for CodePipeline with the right trust relationships).
Leave advanced settings as default → Click Next.

3️⃣Add Source Stage

This is where our code comes from (GitHub in this case).

  • Source provider → GitHub (v2).
  • Connect to GitHub → Authorize your GitHub account with AWS.
  • Repository → Select your repo.
  • Branch → main (or whatever branch you want to deploy).
  • Change detection → Leave as default (CodePipeline uses webhooks to detect new commits).
  • Click Next.

4️⃣ Add Build Stage

  • Now we connect the CodeBuild project we created earlier.
  • Build provider → AWS CodeBuild.
  • Project name → Select the project you just created.
  • Click Next.

5️⃣ Add Deploy Stage

This is where the built artifacts are deployed to your EC2 instance using CodeDeploy.

  • Deploy provider → AWS CodeDeploy.
  • Application name → Choose the CodeDeploy application you created.
  • Deployment group → Select the deployment group.
  • Click Next.

6️⃣ Review & Create

  • Double-check everything → Click Create pipeline.
  • AWS will immediately trigger the pipeline for the first time.
  • You’ll see stages: Source → Build → Deploy with live status updates.

🚨 Something Failed !!! Dont panic expected one😂
This is expected if your EC2 instance doesn’t yet have the correct IAM Instance Profile attached.

Why does this happen?
Because the CodeDeploy agent running inside your EC2 needs permissions to talk to CodeDeploy and pull artifacts from S3. Without that IAM role attached, the agent has no credentials → so the deployment fails.

👉 Fix: Go to your EC2 instance → attach an IAM role (Instance Profile) with permissions like AmazonS3ReadOnlyAccess and AWSCodeDeployRole. Once added, rerun the deployment and it should succeed.

  • We have attached AmazonS3ReadonlyAccess and AWSCodeDeployRole.

And there we go — Success! 🎉
After attaching the correct IAM Instance Profile to our EC2 and rerunning the pipeline, everything works smoothly.

  • Source Stage → grabbed the code from GitHub
  • Build Stage → CodeBuild installed dependencies and packaged the app
  • Deploy Stage → CodeDeploy agent pulled the artifact and deployed it to EC2.

🌐 Accessing Our Application

Now that our pipeline has successfully deployed, let’s confirm everything is working.

  • I opened my EC2 public IP in the browser at port 3000 — and boom, our Node.js application is up and running! 🚀
  • The best part? I didn’t have to SSH into the server or manually copy files. The whole thing was automated through CodePipeline → CodeBuild → CodeDeploy.

👉 Next, let’s test the real magic of CI/CD: we’ll make a small manual change in GitHub, push the code, and watch the pipeline automatically pick it up and deploy Version 2 to EC2.

After making a small change in my code, I pushed it to the main branch on GitHub.

Within seconds, CodePipeline detected the update, automatically triggered a new run, and started executing the stages again — Source → BuildDeploy.

🌟 Version 2 Deployed Successfully

After the pipeline finished its run, I opened the application in the browser again at port 3000, and the changes from Version 2 were live!

This proves that our CI/CD pipeline is fully functional: every time you push a commit to GitHub, CodePipeline detects it, CodeBuild packages it, and CodeDeploy deploys it — all automatically. No manual intervention, no missed steps.

Conclusion / Key Takeaways

Automation is powerful: Once set up, your pipeline handles every commit, build, and deployment.

CodePipeline = orchestrator: It connects Source → Build → Deploy seamlessly.
CodeBuild = builder: Packages and prepares your app artifacts.
CodeDeploy = delivery agent: Pushes the code to EC2 instances and runs lifecycle scripts.
IAM Roles Matter: Both the CodeDeploy service role and EC2 instance profile are critical for permissions.

Top comments (0)