GitHub Actions の導入〜 AWS EC2 に SSH接続するまで

やりたいこと

main ブランチに何かしらマージ、プッシュされた時に、
GitHub Actions を使って自動的に AWS EC2 サーバーに SSH接続してデプロイする。

環境

  • Github
  • AWS EC2 AmazonLinux2023

とりあえず Github Actions を動かしてみる

  • 上部メニュー「Actions」→「New workflow」クリック
  • Choose a workflow
    • Suggested for this repository
      • Simple workflow
        • 「Configure」クリック
          • サンプルコードが出てくる

test.yaml

ファイル名は適当。
main ブランチに何かしらマージ、プッシュされた時に限定したいので、
サンプルコードの on の箇所をいくつかコメントアウトする。
あと最後に ls コマンド追加して終わり。

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the "main" branch
  push:
    branches: [ "main" ]
  #pull_request:
  #  branches: [ "main" ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v4

      # Runs a single command using the runners shell
      - name: Run a one-line script
        run: echo Hello, world!

      # Runs a set of commands using the runners shell
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
      # ls コマンド追加
      - run: ls -la

作業が終わったら、

  • 「Commit changes...」クリック
    • 「Commit directly to the main branch」にチェック
    • 「Commit changes」クリック

確認する

main ブランチにコミットしたので、
早速 Github Actions が動いている。

上部メニュー「Actions」→「All workflows」のリストから確認できる。

解説

サンプルコードでそれぞれ何をやっているか解説。
main ブランチが更新されたらサーバー内で echo と ls するだけの単純なアクション。

# workflow 名。
# 
# ここでは CI (デフォルトのまま)という名前になっている
# 
name: CI

# Github Actions の発火タイミングをここで指定する。
# 
on:
  # main ブランチにプッシュされたら発火する。
  # 
  # main ブランチに直接プッシュするか、
  # 他ブランチを main にマージすることで発火するみたい。
  #
  push:
    branches: [ "main" ]
  # main ブランチから派生したブランチのプルリクエストを送ったタイミング?
  # 検証してないので憶測。
  #
  pull_request:
    branches: [ "main" ]

  # 手動でこのワークフローを実行できるようになる。
  # 上部メニュー「Actions」→「All workflows」→ 作成したワークフロー
  # のリストから実行できる。
  #
  workflow_dispatch:

# Github Actions で実行される内容をここに書く。
jobs:
  # タイトル。デフォルトでは build という名前が付けられている。
  # 
  # deploy-to-prod-ec2 など、
  # 実行される内容が分かるような名前にするのが良さげかも。
  #
  build:
    # Github Actions をどの OS で実行するか指定する。
    # 
    # https://docs.github.com/ja/actions/writing-workflows/choosing-where-your-workflow-runs/choosing-the-runner-for-a-job#choosing-self-hosted-runners
    # 
    runs-on: ubuntu-latest

    # 実行内容
    # 
    steps:
      # github に公開されているリポジトリを使用する。
      # ここでは https://github.com/actions/checkout のバージョン4の中の最新版を使用。
      #
      # actions/checkout を使えば、
      # サーバー内で任意のブランチをクローンして使用する事ができる。
      # デフォルトでは自身のリポジトリの main ブランチ。
      # 他の人のリポジトリもクローン可能ぽい。
      #
      - uses: actions/checkout@v4

      # 実行項目に名前を付けることができる。
      # 可読性が上がるかもしれない。
      # 
      - name: Run a one-line script
      	# 実行内容。linux コマンドを叩いている
        run: echo Hello, world!

      # 実行項目名
      - name: Run a multi-line script
        # 複数行の場合、下記のような書き方もできる
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
	  # actions/checkout を使っているので、
	  # 自身のリポジトリがクローンされているのが確認できる。
	  #
      - run: ls -la

job: steps: 内の書き方色々

jobs:
  runs-on: ubuntu-latest
  # steps 直下に記述できるキー名は、
  # name, run, uses など。
  # https://docs.github.com/ja/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idsteps
  #
  # また、steps を使用するのであれば、
  # run か uses のいずれかを必ず定義しないといけない。
  #
  steps:
  	# キー名の左についてるハイフン( - )は、
  	# yaml の記述法で配列を意味するらしい。
  	#
    #- uses: actions/checkout@v4
    - run: echo name がなくても run できる
    - run: echo steps 直下だと run を並べても問題ない
    - name: name を配置するなら直下に run か uses を必ず置かなければいけない
      run: echo name 直下では run と uses の両方を一緒に使うことはできない
      #uses: this/error@master
    #- name: name の直下には配列を置けない。
    #  - run: echo this is error

AWS EC2インスタンスに ssh接続する

シークレットな変数を設定する

  • 「Settings」→「Secrets and variables」→「Actions」→「Secrets」→「New repository secret」クリック
    • Name: 変数名
    • Secret: 値
    • 「Add secret」クリック

とりあえず下記変数を設定。

変数名 説明
EC2_HOST_01 EC2 のホスト名。自分は IPアドレスにした。
EC2_KEY 秘密鍵。EC2 で使う pem ファイルではない。
EC2_USER EC2 のユーザー名。デフォだと ec2-user になるやつ。
APP_PATH プロダクトまでのパス。/path/to/your/project 的なやつ。

使用する時は下記のように使う。

${{ secrets.EC2_HOST_01 }}

SSH 接続するための秘密鍵は、別途用意しなければいけない

SSH Key #6 - appleboy/ssh-action - GitHub に書いてある通り、
EC2インスタンスを用意した際に発行する秘密鍵(pem ファイル)では、
GitHub Actions 経由で SSH接続できない。

秘密鍵が原因で SSH接続できないと、
下記のようなエラーが出ると思う。

2025/xx/xx 06:00:00 ssh.ParsePrivateKey: ssh: no key found
2025/xx/xx 06:00:01 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none], no supported methods remain

秘密鍵を用意する

SSH Key Setup & OpenSSH Compatibility - appleboy/ssh-action - GitHub をなぞる。
OpenSSH Compatibility - appleboy/ssh-action - GitHub に書いてあるように、
runs-on: ubuntu-latest で立ち上げた Ubuntu のバージョンが 20.04 以上の場合、
ED25519 キーを使わないと下記エラーがでる。

ssh: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]

下記、秘密鍵生成。

$ ssh ec2 に SSH接続する
$ ssh-keygen -t ed25519 -a 200 -C "GitHubで使用しているメールアドレス"

# 公開鍵をコピーする
$ cat .ssh/id_ed25519.pub

# 下記ファイルに id_ed25519.pub の内容を追加
$ vi .ssh/authorized_keys

# 秘密鍵をコピーする。上記変数 EC2_KEY に使う
$ cat .ssh/id_ed25519

GitHub Actions を使って SSH接続してデプロイする

name: TEST

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

jobs:
  ssh-test:
    runs-on: ubuntu-latest
    steps:
      - name: AWSにSSH接続する
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.EC2_HOST_01 }}
          username: ${{ secrets.EC2_USER }}
          key: ${{ secrets.EC2_KEY }}
          script: |
            # 自分は zsh を使っているのだけど、
            # zsh 特有の省略コマンドが使えなかった。
            #
            echo $SHELL
            # npm 等のいつも使用しているコマンドが効かない時は
            # .bashrc や .zshrc に記述している export コマンドを叩く必要がある
            #
            # ex) NodeJS
            #
            export PATH=$HOME/.nodebrew/current/bin:$PATH
            echo npm -v
            npm -v
            # ex) Golang
            #
            export PATH=$PATH:/usr/local/go/bin
            export GOPATH=$HOME/.go
            export PATH=$PATH:$GOPATH/bin
            go version
            # whoami や ls -la すると、
            # ユーザー名とグループ名が *** 表示になっており、
            # 確認することができない。
            # ファイル名等は確認できる
            #
            whoami
            ls -la
            # デプロイ
            cd ${{ secrets.APP_PATH }}
            git checkout main
            git pull origin main

おまけ

runs-on で立ち上げたサーバー内で何かしらの言語を使いたい時