[AWS] GitHub Actions 배포: SSH, PEM없이 AWS SSM으로 배포 방법 개선하기

2025년 4월 25일


기존 배포 파이프라인에서 GitHub Actions Runner가 EC2에 SSH로 접속해 Docker를 실행하는 단계가 있었다. appleboy/ssh-action을 사용하기 위해 GitHub Secrets에 **PEM(Private Key)**을 직접 등록해 사용했다.

문제:

  • GitHub 계정이 탈취되면 서버의 개인키도 함께 노출된다.
  • 외부 서비스(GitHub)에 PEM 키 원본을 저장하는 구조 자체가 보안 취약점이다.

해결: **AWS Systems Manager (SSM)**을 사용하면 SSH 없이 IAM 권한만으로 EC2에 명령을 실행할 수 있다. 접속 주체가 SSH에서 AWS SSM으로 바뀌는 구조다.


1단계 EC2에 SSM 권한 부여

EC2가 SSM 서비스와 통신할 수 있도록 IAM 역할을 부여한다.

  1. AWS 콘솔에서 IAM > 역할(Roles) > 역할 만들기(Create role) 클릭.
  2. 신뢰할 수 있는 엔터티 유형: AWS 서비스 선택.
  3. 사용 사례: EC2 선택 후 다음.
  4. 권한 정책 검색에서 AmazonSSMManagedInstanceCore 추가.
  5. 역할 이름 지정(예: EC2-SSM-Role) 후 생성 완료.

기존에 ECR 접근 등을 위해 만들어둔 역할이 있다면, 해당 역할에 AmazonSSMManagedInstanceCore 정책만 추가해도 된다.

2단계 GitHub Actions IAM 사용자에 권한 추가

aws-actions/configure-aws-credentials에서 사용하는 IAM 사용자에게 SSM 명령 실행 권한을 추가한다.

  1. IAM > 사용자(Users) > GitHub Secrets(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)에 등록된 사용자 클릭.
  2. 권한 탭 > 권한 추가 > 정책 연결(Attach policies) 클릭.
  3. AmazonSSMFullAccess 검색 후 연결.

3단계 EC2에 역할 적용

  1. EC2 콘솔 > 인스턴스 선택.
  2. 작업(Actions) > 보안(Security) > IAM 역할 수정(Modify IAM role).
  3. 생성한 EC2-SSM-Role 선택 후 IAM 역할 업데이트 클릭.

4단계 GitHub Actions 워크플로우 수정

deploy.yml에서 SSH 관련 부분을 SSM 명령으로 교체한다.

기존 방식 SSH

- name: Deploy to EC2
  uses: appleboy/ssh-action@v1.0.0
  env:
    ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
    ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
    IMAGE_TAG: ${{ env.IMAGE_TAG }}
    AWS_REGION: ${{ secrets.AWS_REGION }}
  with:
    host: ${{ secrets.EC2_HOST }} # 퍼블릭 주소
    username: ${{ secrets.EC2_USER }} # 우분투
    key: ${{ secrets.EC2_SSH_KEY }} # pem
    port: 22
    script: |
      # 도커 실행 스크립트...

변경 후 AWS SSM

- name: Deploy to EC2 via SSM
  env:
    ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
    ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
    AWS_REGION: ${{ secrets.AWS_REGION }}
    IMAGE_TAG: ${{ env.IMAGE_TAG }}
  run: |
    aws ssm send-command \
      --document-name "AWS-RunShellScript" \
      --targets "Key=instanceids,Values=${{ secrets.EC2_INSTANCE_ID }}" \
      --comment "Deploy Next.js App ($IMAGE_TAG)" \
      --parameters commands='[
         # 도커 실행 스크립트...
      ]'

AWS-RunShellScript 문서를 사용하면 기존 배포 스크립트를 리스트 형태로 그대로 넣을 수 있다.


GitHub Secrets에서 관리하던 EC2_HOST, EC2_USER, EC2_SSH_KEY를 모두 제거하고 EC2_INSTANCE_ID 하나만 남긴다.