Help us understand the problem. What is going on with this article?

GitHub ActionsでSSHを使う

はじめに

現在ベータ版で、来月正式リリースが予定されているGitHub Actions
v2になってからは、HCLではなくYAMLで書けるようになったり、実行環境のOSを選べるようになったりと機能が充実してきたので、これから使われる機会が増えていくと思います。

このGitHub ActionsをCDに使う場合、SSHが必要になることがあります。

そんなときにはこの記事のことを思い出すと幸せになれるかもしれません。

対象者

  • GitHub上でアプリケーションを開発している
    • 特にウェブアプリケーションの開発でこの記事が役に立つかも
  • GitHub Actionsを使ってデプロイしたい
    • GitHubへのイベント(ブランチへのマージやリリースタグの作成等)をトリガーにして、開発環境や本番環境にデプロイしたい
  • デプロイにSSHを使う
    • SCPとかSFTPとかrsync over SSHとか
  • デプロイ用シェルスクリプトを自前で用意している
    • SSH以外にもいろいろな処理を行っていて、一連の処理をスクリプト化しているような場合

やりたいこと

SSHやSCPを単独で使うのではなく、スクリプト内で実行したい

SSHやSCPを単独で使うだけ(SSHサーバー上でコマンドを実行するだけ、特定のファイルをコピーするだけetc)なら、GitHub Marketplaceに登録されているactionの中に有用なものがあると思います。

しかし、スクリプトファイル内でSSHを使う場合はこれらのactionを使えません。
例えばこんなとき。

  1. SSHの前後でいろいろな処理を行っている
    • 例1: SCP前にビルド処理を行っている
    • 例2: pushされたブランチによって転送先を変更したいので、そのための分岐処理を行っている(developブランチなら開発環境、masterブランチなら本番環境等)
  2. GitHubへの依存度を減らすためにスクリプトファイルを使いたい
    • SSH前後に処理が必要な場合でもGitHub Actionsなら一連の処理をYAMLファイルで記述できますが、それだとGitHubへの依存度が高くなるのでスクリプトファイルを使いたい場合
  3. 以前に作ったデプロイ用スクリプトを再利用したい
    • 以前にGitHub Actions以外のCI/CDを使っていて、そこで作ったデプロイ用スクリプトを再利用したい場合

SSHで鍵認証を使いたい

GitHub Actionsの実行環境(Windows, macOS, Ubuntu)には、いずれもsshコマンドが標準で入っています。
そのため、SSHを使うこと自体は簡単にできます。

しかし、当然ながらSSHサーバーへの接続鍵(authorized_keysに登録されている鍵)はGitHub Actionsの実行環境に存在しないので、そのままでは鍵認証を行えません。

かといって、パスワード認証はセキュリティー上使いたくない場合も多いでしょう。

解決方法

上記の問題は、GitHub Actionsの実行環境にSSH鍵(+接続先サーバーの公開鍵)を登録できれば解決します。

Marketplaceを探したところ、これをやってくれるactionが見つからなかったので作ってみました

Install SSH Key

長い前フリですが、これの紹介と使い方の説明が本記事の主題です。

使い方

鍵を登録

最初に注意事項ですが、秘密鍵は極秘情報なので、Gitでバージョン管理してはいけません

以下のようにしてプロジェクトに鍵を登録してください。

GitHubのプロジェクトページのSettings - Secrets - Add a new secretの順にクリックし、例えば以下のような名前でそれぞれ登録してください。別の名前でも構いません。

  • SSH_KEY - SSH秘密鍵
  • SSH_KEY_PUBLIC - SSH公開鍵
  • KNOWN_HOSTS - サーバーの公開鍵+ホスト名/IPアドレス(.ssh/known_hostsファイルのフォーマット)

SSH_KEY以外は公開鍵なのでGit管理しても問題ないかもしれませんが、とりあえず全てSecretsに登録しておきます。

デプロイスクリプトを用意

次に、リポジトリにデプロイスクリプトを追加してください。
ここではdeploy.shという名前で用意したとします。

内容はたとえばこのようになるでしょう。
必要に応じてビルド処理や転送先の切り替え処理などを入れてください。

deploy.sh
#!/bin/bash
# outputディレクトリ内のファイルをrsync over SSHで転送
rsync -acvz --delete ./output/ user@remote:/path/to/deploy/
# サービスを再起動
ssh user@remote "<run restart or graceful-reload command>"

ワークフローファイルを記述

リポジトリに.github/workflows/deploy.ymlファイルを作り、以下のように記述してください。
ファイル名は変えても構いませんが、ディレクトリ名は変えてはいけません

ワークフローファイルの書き方の詳細は、GitHub Actionsのワークフロー構文を参照してください。

deploy.yml
on:
  release:
    types:
    - published # 新しいリリースが作成されたときに実行
name: Deploy
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Install SSH key
      uses: shimataro/ssh-key-action@v1
      with: # shimataro/ssh-key-actionに渡すパラメーター
        private-key: ${{ secrets.SSH_KEY }} # 必須
        public-key: ${{ secrets.SSH_KEY_PUBLIC }} # 必須
        name: id_rsa # 省略可
        known-hosts: ${{ secrets.KNOWN_HOSTS }} # 省略可
    - name: run deploy script
      run: bash deploy.sh

secrets.SSH_KEY等は、上で登録したSSH鍵等の名前と同じものを指定してください。

最初のステップ(Install SSH Key)で、以下の処理が行われます。

  • private-keyで指定した秘密鍵を.ssh/id_rsaに保存
  • public-keyで指定した公開鍵を.ssh/id_rsa.pubに保存
  • known-hostsで指定したサーバー公開鍵を.ssh/known_hostsに保存

ファイルのパーミッションは、それぞれ適切なものに設定されます。

以上で、リリースの作成をトリガーとしてdeploy.shが実行されるようになります

諸注意

withの中で必須のものはprivate-keypublic-keyだけで、それ以外は省略できます。
nameを省略した場合は"id_rsa"が、known-hostsを指定した場合は空文字列が、それぞれ使われます。

known-hostsを省略した場合は接続先サーバーの公開鍵の検証を省略する必要があるのでsshコマンドに-o StrictHostKeyChecking=noが必要ですが、このオプションは中間者攻撃を許してしまいます
特別な理由がなければ、サボらずにきちんと設定しましょう。

中間者攻撃のリスクを許容してまで設定しない理由も特にないと思うので、将来のバージョンアップで必須パラメーターにするかもしれません。

3行で

長くなったので3行でまとめます。

  • GitHub Actions便利だよ
  • スクリプト内でSSHを使いたいときはInstall SSH Keyを使うといいよ
  • サーバー公開鍵もできるだけ登録しておこうね
  • ついでにStarつけてくれたらうれしいな(4行目)

GitHub Actionsについての資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away