DEV Community

alok-38
alok-38

Posted on

Automate your deployment using AWS SSM

Deploying DevOps App to EC2 via SSM using GitHub Actions

Table of contents:

  1. Initial Setup

  2. Issues Encountered

  3. Final GitHub Actions Workflow

  4. Secrets Used in GitHub

  5. Summary of Fixes

Initial Setup

  • Objective: Automate deployment of your app from GitHub to an EC2 instance via AWS SSM (no SSH key needed, zero-open-ports).

  • Environment: AWS Free Tier, EC2 t3.micro, Amazon Linux.

  • Tools: GitHub Actions, AWS Systems Manager (SSM), EC2, IAM roles and policies.

Issues Encountered

Git & Tagging Issues

git tag v1.0.0
git push origin v1.0.0
fatal: tag 'v1.0.0' already exists
Enter fullscreen mode Exit fullscreen mode
  • Cause: Tag already exists locally or on GitHub.

  • Fix: Use a new tag number (v1.0.2, v1.0.4) and push:

git tag -f v1.0.2  # force update if needed
git push origin v1.0.2
Enter fullscreen mode Exit fullscreen mode

SSH-based Deployment Issues

  • Initially tried using SSH with private key.

  • Errors included:

dial tcp ***:22: i/o timeout
Enter fullscreen mode Exit fullscreen mode
  • Cause: Security group rules were blocking access, had to restrict inbound to your IP.

  • Pain point: Maintaining SSH keys and updating them in GitHub secrets is brittle.

✅ Lesson: Using SSM avoids opening port 22 entirely, more secure and reliable.

SSM Managed Nodes

  • SSM Agent installed on EC2:
sudo systemctl status amazon-ssm-agent
Enter fullscreen mode Exit fullscreen mode
  • Initially, nodes were not appearing as managed instances in Fleet Manager.

  • Error in CLI:

aws ssm describe-instance-information
An error occurred (AccessDeniedException)
Enter fullscreen mode Exit fullscreen mode
  • Cause: EC2 IAM role EC2-SSM-Deploy-Role lacked proper SSM permissions.

IAM Role and Policy Issues

  • The IAM role attached: EC2-SSM-Deploy-Role

  • Initial policies: AmazonSSMManagedInstanceCore (AWS managed)

Missing: Permission for ssm:DescribeInstanceInformation and SSM commands.

  • Fix:
  1. Created a custom policy SSMManagedInstanceCoreCustom.

  2. Attached it to EC2-SSM-Deploy-Role.

  • Result: EC2 became a managed instance in Fleet Manager, Online status verified.

GitHub Actions Workflow Errors

  1. Wrong AWS CLI action:
Error: Unable to resolve action aws-actions/aws-cli
Error: Unable to resolve action amazon-actions/aws-cli
Enter fullscreen mode Exit fullscreen mode
  • Cause: No such repository exists; GitHub Actions cannot find it.

✅ Fix: Use aws-actions/configure-aws-credentials@v3 for credentials and run AWS CLI commands in run:.

Final GitHub Actions Workflow

File: .github/workflows/deploy.yml

name: Deploy to EC2 via SSM

on:
  push:
    tags:
      - "v*.*"

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Deploy via AWS SSM
        run: |
          aws ssm send-command \
            --targets "Key=InstanceIds,Values=i-068ca0d3a5b74206a" \
            --document-name "AWS-RunShellScript" \
            --comment "Deploy DevOps app" \
            --parameters '{"commands":["cd /usr/share/nginx/html/DevOps","git pull origin main","sudo systemctl reload nginx"]}' \
            --output text
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. Trigger: Runs on tag pushes (vX.X.X).

  2. Checkout: Pulls repo code into GitHub Actions runner.

  3. AWS Credentials: Uses GitHub secrets to authenticate via AWS CLI.

  • Secrets used: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION.
  1. Deployment via SSM:
  • ssm send-command runs shell commands on the EC2 instance without SSH.

    • Commands:
    • Change directory: /usr/share/nginx/html/DevOps
    • Pull latest code: git pull origin main
    • Reload Nginx: sudo systemctl reload nginx
    • Output set to text for readability in Actions logs.

Secrets Used in GitHub

Name Value
AWS_ACCESS_KEY_ID From IAM user alok-admin
AWS_SECRET_ACCESS_KEY From IAM user alok-admin
AWS_REGION us-east-1 (example)
EC2_HOST EC2 Public IP
EC2_SSH_KEY Not used in final SSM workflow

✅ No need to open SSH ports now; deployment works via SSM.

Summary of Fixes

Problem Fix
Git tag already exists Increment tag version, push
SSH deployment failing Moved to SSM, no open ports needed
EC2 not a managed node Installed SSM agent, attached IAM role
IAM role missing SSM permissions Added AmazonSSMManagedInstanceCore + custom policy
Workflow action not found Replaced with aws-actions/configure-aws-credentials@v3 + CLI run
AccessDeniedException from AWS CLI Fixed IAM policies attached to role

✅ Outcome

  • EC2 shows as managed node in Fleet Manager.

  • GitHub Actions workflow triggers on tag push, connects via SSM, pulls latest code, reloads Nginx.

  • Fully automated, zero-open-ports deployment.

  • Works on Free Tier, minimal IAM setup, no SSH maintenance.

Top comments (0)