CI/CD (Continuous Integration and Continuous Deployment) is one of the most valuable skills a developer can learn today. In this guide, you'll learn how to set up a CI/CD pipeline that automatically deploys your HTML website to an AWS EC2 instance using GitHub Actions.
By the end, every time you push code to GitHub, your website will update automatically!
🧰 Prerequisites
Make sure you have the following ready:
- AWS Account
- A GitHub account
🛠️ Step 1: Create and Prepare Your EC2 Instance
🔹 1.1 Launch the EC2 Instance
- Head over to the EC2 Console.
- Click "Launch Instance".
- Fill in the form:
- Name:
MyStaticSite - AMI: Amazon Linux 2
- Instance Type:
t2.micro(Eligible for Free Tier) - Key Pair: Create or use existing (download the
.pemfile) - Security Group: Allow:
- SSH (port 22)
- HTTP (port 80)
- Name:
- Click "Launch".
🔹 1.2 Connect to Your Instance
- Move the PEM file to a secure location (optional)
mv ~/Downloads/your-key.pem ~/.ssh/
- Set correct permissions on the key file
chmod 400 ~/.ssh/your-key.pem
- SSH into your EC2 instance
ssh -i ~/.ssh/your-key.pem ec2-user@your-ec2-public-ip
If you're using Ubuntu, replace ec2-user with ubuntu.
🔑 Replace:
your-key.pem → with your actual file name
your-ec2-public-ip → with your EC2 instance’s public IP or DNS (You can find them when you click on your instance in AWS console)
🔹 1.3 Install a Web Server and grant user privilege
Amazon Linux 2:
sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
sudo chown ec2-user /var/www/html
Ubuntu:
sudo apt update
sudo apt install -y apache2
sudo systemctl start apache2
sudo systemctl enable apache2
sudo chown ubuntu /var/www/html
Test it: open your EC2 public IP in your browser — you should see the Apache test page.
📁 Step 2: Push Your HTML Code to GitHub
Here's a simple structure for your project:
.
├── index.html
└── .github
└── workflows
└── deploy.yml
Example index.html:
<!DOCTYPE html>
<html>
<head>
<title>Hello CI/CD</title>
</head>
<body>
<h1>This was deployed using GitHub Actions!</h1>
</body>
</html>
Commit and push this code to your GitHub repository.
⚙️ Step 3: Create GitHub Actions Workflow
In your GitHub repo, create the file: .github/workflows/deploy.yml
name: Deploy to EC2
on:
push:
branches:
- main # or 'master', based on your repo’s default branch
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Copy files via SCP
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_KEY }}
source: "index.html"
target: "/var/www/html"
This GitHub Action will trigger on every push to the main (or master, depending on your repo) branch and securely copy your index.html file to your EC2 instance using SSH.
🔐 Step 4: Add Secrets to GitHub
Go to your GitHub repository → Settings → Secrets and variables → Actions → New repository secret
Add the following secrets:
-
EC2_HOST→ your EC2 public IP -
EC2_USER→ usuallyec2-user(Amazon Linux) orubuntu(Ubuntu) -
EC2_KEY→ paste the contents of your private key.pemfile
⚠️ Never commit
.pemfiles or expose them in public repos. GitHub Secrets are encrypted, but use IAM roles or session-based credentials for production setups.
🚀 Step 5: Push Your Code and Deploy
Now commit and push to GitHub:
git add .
git commit -m "Initial CI/CD setup"
git push origin main # or 'master' if your repo uses that
Head over to the Actions tab in your GitHub repo — you'll see the deploy job running.
When it's finished, go to http://<your-ec2-public-ip>. Your site should be live with the new HTML!
🎉 You're Done!
Congrats! You’ve set up your first CI/CD pipeline using:
- GitHub Actions for automation
- EC2 as your deployment target
- SCP/SSH for secure transfer
Now, anytime you update your HTML and push to
main(ormaster), your changes go live automatically.
🔍 What Happens Behind the Scenes
Let’s break down what’s really going on when you push your code and GitHub Actions deploys it to EC2:
- GitHub Detects a Push to main
- GitHub watches for changes to your repository.
- When you push to the main branch, it checks .github/workflows/deploy.yml.
- This file tells GitHub: “Hey, run this workflow when there’s a push.”
- GitHub Actions Spins Up a Runner
- GitHub spins up a temporary virtual machine (Ubuntu in our case).
- This is where your workflow steps run.
- Your Code Is Cloned
- The actions/checkout step grabs your repo’s latest code.
- Secure Copy (SCP) Sends Files to EC2
- The appleboy/scp-action uses scp under the hood.
- It connects to your EC2 instance using your SSH key (EC2_KEY) and username.
- Then it uploads your index.html to the EC2 server — typically in /var/www/html.
- EC2 Serves the Updated HTML
- Your Apache or Nginx web server is already running on EC2.
- It’s watching the /var/www/html directory.
- When the new index.html is uploaded, it automatically starts serving the new version.
🔹 Local equivalent:
Let’s look at what you’d do manually without CI/CD, so you can better appreciate what GitHub Actions automates.
# GitHub Actions: checkout step
git clone https://github.com/your-username/your-repo.git
cd your-repo
# GitHub Actions: SCP upload step
scp -i your-key.pem index.html ec2-user@your-ec2-ip:/var/www/html
🔹 Summary of the Flow
GitHub Repo ---push---> GitHub Actions
↓ ↓
deploy.yml Ubuntu Runner
↓
SSH into EC2 via key
↓
Upload index.html via SCP
↓
Apache serves your site update
🧠 Bonus Ideas
- Add support for multiple environments (e.g., staging, production)
- Use Nginx instead of Apache for better performance
- Install SSL with Let’s Encrypt (Certbot)
- Automate EC2 provisioning with Terraform or CloudFormation
🙌 Final Thoughts
CI/CD doesn't have to be complicated. Starting with small projects like this builds the foundation for automating deployments in real-world applications.
🌐 Got stuck? Drop a comment below and I’ll help you out — or connect with me on LinkedIn!
Top comments (0)