Back to Guides
GitHub ActionsCI/CDAWSEC2DevOps

Automate Deployments to AWS EC2 with GitHub Actions CI/CD

Set up a complete CI/CD pipeline using GitHub Actions to automatically deploy your application to EC2 whenever you push code to your repository.

What You'll Build

This guide walks you through creating a GitHub Actions workflow that:

  • Triggers automatically on every push to your main branch
  • Connects securely to your EC2 instance via SSH
  • Pulls the latest code from your repository
  • Installs dependencies and restarts your application
  • Provides deployment status feedback directly in GitHub

Just Need a Quick Redeploy?

If you're managing just a handful of applications or only need to redeploy once or twice, you might not need the full CI/CD setup. Here's the quick manual way:

1. Stop your running app:

Terminal (EC2)
pkill -f 'streamlit run' # or pkill -f 'python app.py'

2. Pull latest changes (make sure they're committed to GitHub):

Terminal (EC2)
cd ~/your-repo && git pull origin main

3. Restart your application:

Terminal (EC2)
nohup streamlit run app.py > app.log 2>&1 &

This manual approach is perfectly fine for small projects. Only invest time in CI/CD automation when you're deploying frequently or managing multiple services.

1

Prepare Your EC2 Instance

First, ensure your EC2 instance has Git installed and your repository is already cloned. If not, follow these steps:

Terminal (EC2)
# Update package manager sudo yum update -y # Install Git sudo yum install git -y # Clone your repository git clone git@github.com:YourUsername/your-repo.git cd your-repo

Create a deployment script that will be executed by GitHub Actions:

~/your-repo/deploy.sh
#!/bin/bash set -e echo "Starting deployment..." # Navigate to project directory cd ~/your-repo # Pull latest changes echo "Pulling latest code..." git pull origin main # Install/update dependencies echo "Installing dependencies..." pip install -r requirements.txt # Restart application (adjust for your app type) echo "Restarting application..." pkill -f "streamlit run" || true nohup streamlit run app.py > app.log 2>&1 & echo "Deployment complete!"

Make the script executable:

Terminal (EC2)
chmod +x ~/your-repo/deploy.sh
2

Generate SSH Key for GitHub Actions

On your local machine, generate a dedicated SSH key pair for GitHub Actions to use:

Terminal (Local)
ssh-keygen -t ed25519 -C "github-actions" -f ~/.ssh/github-actions-deploy

This creates two files: github-actions-deploy (private key) and github-actions-deploy.pub (public key).

Copy the public key:

Terminal (Local)
cat ~/.ssh/github-actions-deploy.pub

Add it to your EC2 instance's authorized keys:

Terminal (EC2)
echo "ssh-ed25519 AAAAC3... github-actions" >> ~/.ssh/authorized_keys
3

Add Secrets to GitHub Repository

Store your sensitive information securely in GitHub Secrets. Navigate to your repository on GitHub:

  1. Go to SettingsSecrets and variablesActions
  2. Click New repository secret
  3. Add these three secrets:

EC2_SSH_KEY
Copy the entire contents of your private key file:

Get private key
cat ~/.ssh/github-actions-deploy

EC2_HOST
Your EC2 public IP or DNS (e.g., ec2-13-58-123-45.us-east-2.compute.amazonaws.com)

EC2_USERNAME
Your EC2 username (typically ec2-user for Amazon Linux, ubuntu for Ubuntu)

4

Create GitHub Actions Workflow

In your repository, create the workflow file that will handle automated deployments:

.github/workflows/deploy.yml
name: Deploy to EC2 on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Deploy to EC2 uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USERNAME }} key: ${{ secrets.EC2_SSH_KEY }} script: | cd ~/your-repo ./deploy.sh

Important: Replace ~/your-repo with the actual path to your project directory on EC2.

5

Test Your CI/CD Pipeline

Commit and push your workflow file to trigger the first deployment:

Terminal (Local)
git add .github/workflows/deploy.yml git commit -m "Add CI/CD workflow" git push origin main

Monitor the deployment progress:

  1. Go to your GitHub repository
  2. Click on the Actions tab
  3. You should see your workflow running
  4. Click on it to view detailed logs

Success! If everything is configured correctly, you'll see a green checkmark ✓ indicating successful deployment.

Advanced Enhancements

Add Build Tests Before Deployment

Prevent broken code from reaching production:

Add to deploy.yml (before deploy job)
test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Install dependencies run: pip install -r requirements.txt - name: Run tests run: pytest tests/ deploy: needs: test # Only deploy if tests pass runs-on: ubuntu-latest

Deploy to Multiple Environments

Set up separate staging and production deployments:

Multi-environment workflow
on: push: branches: - main # Triggers production deploy - staging # Triggers staging deploy jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Deploy uses: appleboy/ssh-action@v1.0.3 with: host: ${{ github.ref == 'refs/heads/main' && secrets.PROD_HOST || secrets.STAGING_HOST }} username: ${{ secrets.EC2_USERNAME }} key: ${{ secrets.EC2_SSH_KEY }} script: cd ~/app && ./deploy.sh

Add Slack Notifications

Get notified about deployment status in Slack:

Add notification step
- name: Notify Slack if: always() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} webhook_url: ${{ secrets.SLACK_WEBHOOK }} text: 'Deployment to EC2 ${{ job.status }}'

Common Issues & Solutions

❌ Permission denied (publickey)

Ensure the public key is added to ~/.ssh/authorized_keys on EC2 and the private key is correctly added to GitHub Secrets.

❌ deploy.sh: command not found

Make sure the script path in your workflow matches the actual location on EC2 and that it's executable (chmod +x deploy.sh).

❌ Git pull fails

Your EC2 instance needs a deploy key configured for the repository. See the "Deploy Streamlit App" guide for setting this up.

❌ Application doesn't restart

Check the process name in your pkill command matches your actual running process. Use ps aux | grep your-app to verify.

Pro Tips

  • Use tmux or systemd to manage your application process for better reliability
  • Implement health checks in your deploy script to verify the app started successfully
  • Add a rollback mechanism by tagging releases and keeping previous versions
  • Consider using AWS CodeDeploy for more advanced deployment strategies like blue-green deployments
  • Set up CloudWatch alarms to monitor your EC2 instance health and application metrics

Questions or Issues?

If you run into any problems setting up your CI/CD pipeline, feel free to reach out. I'm happy to help troubleshoot!

Email: its.royniloy@gmail.com